diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm
index 87c880c6d5f5f437b12ac6b05e9f1d5b9cdb0463..ac517e65715bf65ca2b0c6d164c502d97ba1bfb6 100644
--- a/tools/winapi/c_parser.pm
+++ b/tools/winapi/c_parser.pm
@@ -29,6 +29,7 @@ sub new {
     my $create_function = \${$self->{CREATE_FUNCTION}};
     my $found_function = \${$self->{FOUND_FUNCTION}};
     my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+    my $found_line = \${$self->{FOUND_LINE}};
     my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
     my $found_statement = \${$self->{FOUND_STATEMENT}};
     my $found_variable = \${$self->{FOUND_VARIABLE}};
@@ -40,6 +41,7 @@ sub new {
     $$create_function = sub { return new c_function; };
     $$found_function = sub { return 1; };
     $$found_function_call = sub { return 1; };
+    $$found_line = sub { return 1; };
     $$found_preprocessor = sub { return 1; };
     $$found_statement = sub { return 1; };
     $$found_variable = sub { return 1; };
@@ -91,6 +93,17 @@ sub set_found_function_call_callback {
     $$found_function_call = shift;
 }
 
+########################################################################
+# set_found_line_callback
+#
+sub set_found_line_callback {
+    my $self = shift;
+
+    my $found_line = \${$self->{FOUND_LINE}};
+
+    $$found_line = shift;
+}
+
 ########################################################################
 # set_found_preprocessor_callback
 #
@@ -162,6 +175,8 @@ sub _parse_c {
 
 ########################################################################
 # _parse_c_error
+#
+# FIXME: Use caller (See man perlfunc)
 
 sub _parse_c_error {
     my $self = shift;
@@ -172,40 +187,43 @@ sub _parse_c_error {
     my $line = shift;
     my $column = shift;
     my $context = shift;
+    my $message = shift;
 
-    my @lines = split(/\n/, $_);
+    $message = "parse error" if !$message;
 
-    my $current = "\n";
-    $current .= $lines[0] . "\n" || "";
-    $current .= $lines[1] . "\n" || "";
+    my $current = "";
+    if($_) {
+	my @lines = split(/\n/, $_);
+
+	$current .= $lines[0] . "\n" if $lines[0];
+        $current .= $lines[1] . "\n" if $lines[1];
+    }
 
     if($output->prefix) {
 	$output->write("\n");
 	$output->prefix("");
     }
-    $output->write("$$file:$line." . ($column + 1) . ": $context: parse error: \\$current");
+    
+    if($current) {
+	$output->write("$$file:$line." . ($column + 1) . ": $context: $message: \\\n$current");
+    } else {
+	$output->write("$$file:$line." . ($column + 1) . ": $context: $message\n");
+    }
 
     exit 1;
 }
 
 ########################################################################
-# _parse_c_output
+# _parse_c_warning
 
-sub _parse_c_output {
+sub _parse_c_warning {
     my $self = shift;
 
-    local $_ = shift;
     my $line = shift;
     my $column = shift;
     my $message = shift;
 
-    my @lines = split(/\n/, $_);
-
-    my $current = "\n";
-    $current .= $lines[0] . "\n" || "";
-    $current .= $lines[1] . "\n" || "";
-
-    $output->write("$line." . ($column + 1) . ": $message: \\$current");
+    $output->write("$line." . ($column + 1) . ": $message\n");
 }
 
 ########################################################################
@@ -472,23 +490,25 @@ sub parse_c_declaration {
     # Variable
     my $type;
 
-    # $self->_parse_c_output($_, $line, $column, "declaration");
-
     if(0) {
 	# Nothing
     } elsif(s/^(?:DEFAULT|DECLARE)_DEBUG_CHANNEL\s*\(\s*(\w+)\s*\)\s*//s) { # FIXME: Wine specific kludge
 	$self->_update_c_position($&, \$line, \$column);
-    } elsif(s/^extern\s*\"(.*?)\"\s*//s) {
+    } elsif(s/^__ASM_GLOBAL_FUNC\(\s*(\w+)\s*,\s*//s) { # FIXME: Wine specific kludge
 	$self->_update_c_position($&, \$line, \$column);
-	my $declarations;
-	my $declarations_line;
-	my $declarations_column;
-	if(!$self->parse_c_block(\$_, \$line, \$column, \$declarations, \$declarations_line, \$declarations_column)) {
-	    return 0;
-	}
-	if(!$self->parse_c_declarations(\$declarations, \$declarations_line, \$declarations_column)) {
-	    return 0;
+	$self->_parse_c_until_one_of("\)", \$_, \$line, \$column);
+	if(s/\)//) {
+	    $column++;
 	}
+    } elsif(s/^(?:jump|strong)_alias//s) { # FIXME: GNU C library specific kludge
+    } elsif(s/^extern\s*\"C\"\s*{//s) {
+	$self->_update_c_position($&, \$line, \$column);
+    } elsif(s/^(?:__asm__|asm)\s*\(//) {
+	$self->_update_c_position($&, \$line, \$column);
+    } elsif($self->parse_c_typedef(\$_, \$line, \$column)) {
+	# Nothing
+    } elsif($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type, \$name)) {
+	# Nothing
     } elsif($self->parse_c_function(\$_, \$line, \$column, \$function)) {
 	if(&$$found_function($function))
 	{
@@ -502,10 +522,6 @@ sub parse_c_declaration {
 		}
 	    }
 	}
-    } elsif($self->parse_c_typedef(\$_, \$line, \$column)) {
-	# Nothing
-    } elsif($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type, \$name)) {
-	# Nothing
     } else {
 	$self->_parse_c_error($_, $line, $column, "declaration");
     }
@@ -548,38 +564,33 @@ sub parse_c_expression {
 
     $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
 
-    if(s/^(.*?)(\w+\s*\()/$2/s) {
-	$column += length($1);
-
-	my $begin_line = $line;
-	my $begin_column = $column + 1;
-
-	my $name;
-	my @arguments;
-	my @argument_lines;
-	my @argument_columns;
-	if(!$self->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns)) {
-	    return 0;
-	}
-
-	if($name =~ /^sizeof$/ || 
-	   &$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
-	{
-	    while(defined(my $argument = shift @arguments) &&
-		  defined(my $argument_line = shift @argument_lines) &&
-		  defined(my $argument_column = shift @argument_columns))
+    while($_) {
+	if(s/^(.*?)(\w+\s*\()/$2/s) {
+	    $self->_update_c_position($1, \$line, \$column);
+
+	    my $begin_line = $line;
+	    my $begin_column = $column + 1;
+	    
+	    my $name;
+	    my @arguments;
+	    my @argument_lines;
+	    my @argument_columns;
+	    if(!$self->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns)) {
+		return 0;
+	    }
+	    
+	    if(&$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
 	    {
-		$self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
+		while(defined(my $argument = shift @arguments) &&
+		      defined(my $argument_line = shift @argument_lines) &&
+		      defined(my $argument_column = shift @argument_columns))
+		{
+		    $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
+		}
 	    }
+	} else {
+	    $_ = "";
 	}
-    } elsif(s/^return//) {
-	$column += length($&);
-	$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
-	if(!$self->parse_c_expression(\$_, \$line, \$column)) {
-	    return 0;
-	}
-    } else {
-	return 0;
     }
 
     $self->_update_c_position($_, \$line, \$column);
@@ -598,6 +609,7 @@ sub parse_c_file {
     my $self = shift;
 
     my $found_comment = \${$self->{FOUND_COMMENT}};
+    my $found_line = \${$self->{FOUND_LINE}};
 
     my $refcurrent = shift;
     my $refline = shift;
@@ -614,24 +626,46 @@ sub parse_c_file {
     my $previous_line = 0;
     my $previous_column = -1;
 
+    my $if = 0;
+    my $if0 = 0;
+
     my $blevel = 1;
     my $plevel = 1;
     while($plevel > 0 || $blevel > 0) {
 	my $match;
 	$self->_parse_c_until_one_of("#/\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
-
-	if($line == $previous_line && $column == $previous_column) {
-	    # $self->_parse_c_error($_, $line, $column, "file: no progress");
+	
+	if($line != $previous_line) {
+	    &$$found_line($line);
+	} elsif($column == $previous_column) {
+	    $self->_parse_c_error($_, $line, $column, "file", "no progress");
+	} else {
+	    # &$$found_line("$line.$column");
 	}
 	$previous_line = $line;
 	$previous_column = $column;
 
-	# $self->_parse_c_output($_, $line, $column, "'$match'");
+	# $output->write("file: $plevel $blevel: '$match'\n");
 
 	if(!$declaration && $match =~ s/^\s+//s) {
 	    $self->_update_c_position($&, \$declaration_line, \$declaration_column);
 	}
-	$declaration .= $match;
+	if(!$if0) {
+	    $declaration .= $match;
+	} else {
+	    my $blank_lines = 0;
+
+	    local $_ = $match;
+	    while(s/^.*?\n//) { $blank_lines++; }
+
+	    if(!$declaration) {
+		$declaration_line = $line;
+		$declaration_column = $column;
+	    } else {
+		$declaration .= "\n" x $blank_lines;
+	    }
+
+	}
 
 	if(/^[\#\/]/) {
 	    my $blank_lines = 0;
@@ -644,7 +678,14 @@ sub parse_c_file {
 		    $blank_lines++;
 		    $preprocessor .= "$1\n";
 		}
-		if(s/^(.*?)(\/[\*\/].*)?\n//) {
+		if(s/^(.*?)(\/\*.*?\*\/)(.*?)\n//) {
+		    $_ = "$2\n$_";
+		    if(defined($3)) {
+			$preprocessor .= "$1$3";
+		    } else {
+			$preprocessor .= $1;
+		    }
+		} elsif(s/^(.*?)(\/[\*\/].*?)?\n//) {
 		    if(defined($2)) {
 			$_ = "$2\n$_";
 		    } else {
@@ -653,24 +694,44 @@ sub parse_c_file {
 		    $preprocessor .= $1;
 		}
 
+		if($if0 && $preprocessor =~ /^\#\s*endif/) {
+		    if($if0 > 0) {
+			if($if > 0) {
+			    $if--;
+			} else {
+			    $if0--;
+			}
+		    }
+	        } elsif($preprocessor =~ /^\#\s*if/) {
+		    if($preprocessor =~ /^\#\s*if\s*0/) {
+			$if0++;
+		    } elsif($if0 > 0) {
+			$if++;
+		    }
+		}
+
 		if(!$self->parse_c_preprocessor(\$preprocessor, \$preprocessor_line, \$preprocessor_column)) {
-		    return 0;
+		     return 0;
+		}
+	    }
+
+	    if(s/^\/\*.*?\*\///s) {
+		&$$found_comment($line, $column + 1, $&);
+	        local $_ = $&;
+		while(s/^.*?\n//) {
+		    $blank_lines++; 
 		}
-	    } 
-
-	    if(s/^\/\*(.*?)\*\///s) {
-		&$$found_comment($line, $column + 1, "/*$1*/");
-		my @lines = split(/\n/, $1);
-		if($#lines > 0) {
-		    $blank_lines += $#lines;
-		} else {
-		    $column += length($1);
+		if($_) {
+		    $column += length($_);
 		}
 	    } elsif(s/^\/\/(.*?)\n//) {
-		&$$found_comment($line, $column + 1, "//$1");
+		&$$found_comment($line, $column + 1, $&);
 		$blank_lines++;
 	    } elsif(s/^\///) {
-		$declaration .= $&;
+		if(!$if0) {
+		    $declaration .= $&;
+		    $column++;
+		}
 	    }
 
 	    $line += $blank_lines;
@@ -681,27 +742,49 @@ sub parse_c_file {
 	    if(!$declaration) {
 		$declaration_line = $line;
 		$declaration_column = $column;
-	    } else {
+	    } elsif($blank_lines > 0) {
 		$declaration .= "\n" x $blank_lines;
 	    }
 
 	    next;
-	} 
+	}
 
 	$column++;
+
+	if($if0) {
+	    s/^.//;
+	    next;
+	}
+
 	if(s/^[\(\[]//) {
 	    $plevel++;
 	    $declaration .= $&;
-	} elsif(s/^[\)\]]//) {
+	} elsif(s/^\]//) {
+	    $plevel--;
+	    $declaration .= $&;
+	} elsif(s/^\)//) {
 	    $plevel--;
 	    $declaration .= $&;
+	    if($plevel == 1 && $declaration =~ /^__ASM_GLOBAL_FUNC/) {
+		if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
+		    return 0;
+		}
+		$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+		$declaration = "";
+		$declaration_line = $line;
+		$declaration_column = $column;
+	    }
 	} elsif(s/^\{//) {
 	    $blevel++;
 	    $declaration .= $&;
 	} elsif(s/^\}//) {
 	    $blevel--;
 	    $declaration .= $&;
-	    if($plevel == 1 && $blevel == 1 && $declaration !~ /^typedef/) {
+	    if($declaration =~ /^typedef/s ||
+	       $declaration =~ /^(?:const\s+|extern\s+|static\s+)*(?:struct|union)(?:\s+\w+)?\s*\{/s)
+	    {
+		# Nothing
+	    } elsif($plevel == 1 && $blevel == 1) {
 		if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
 		    return 0;
 		}
@@ -709,9 +792,20 @@ sub parse_c_file {
 		$declaration = "";
 		$declaration_line = $line;
 		$declaration_column = $column;
+	    } elsif($column == 1) {
+		$self->_parse_c_error("", $line, $column, "file", "inner } ends on column 1");
 	    }
 	} elsif(s/^;//) {
-	    if($plevel == 1 && $blevel == 1) {
+	    $declaration .= $&;
+	    if($blevel == 1 && 
+	       $declaration !~ /^typedef/ && 
+	       $declaration !~ /^(?:const\s+|extern\s+|static\s+)(?:struct|union)(?:\s+\w+)?\s*\{/s &&
+	       $declaration =~ /^(?:\w+\s*)*(?:(?:\*\s*)+|\s+)(\w+)\s*\(\s*(?:(?:\w+\s*,\s*)*\w+\s*)?\)(.*?);/s && 
+	       $1 ne "ICOM_VTABLE" && $2) # K&R 
+	    {
+		$self->_parse_c_warning($line, $column, "function $1: warning: function has K&R format");
+	    } elsif($plevel == 1 && $blevel == 1) {
+		$declaration =~ s/\s*;$//;
 		if($declaration && !$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
 		    return 0;
 		}
@@ -719,14 +813,12 @@ sub parse_c_file {
 		$declaration = "";
 		$declaration_line = $line;
 		$declaration_column = $column;
-	    } else {
-		$declaration .= $&;
 	    }
 	} elsif(/^\s*$/ && $declaration =~ /^\s*$/ && $match =~ /^\s*$/) {
 	    $plevel = 0;
 	    $blevel = 0;
 	} else {
-	    $self->_parse_c_error($_, $line, $column, "file");
+	    $self->_parse_c_error($_, $line, $column, "file", "'$declaration' '$match'");
 	}
     }
 
@@ -772,21 +864,51 @@ sub parse_c_function {
     my $begin_line = $line;
     my $begin_column = $column + 1;
 
-    $self->_parse_c("inline", \$_, \$line, \$column);
-    $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
-    $self->_parse_c("inline", \$_, \$line, \$column);
-    if(!$self->parse_c_type(\$_, \$line, \$column, \$return_type)) {
-	return 0;
+    my $match;
+    while($self->_parse_c('const|inline|extern|static|volatile|' . 
+			  'signed(?=\\s+char|s+int|\s+long(?:\s+long)?|\s+short)|' .
+			  'unsigned(?=\s+char|\s+int|\s+long(?:\s+long)?|\s+short)',
+			  \$_, \$line, \$column, \$match)) 
+    {
+	if($match =~ /^extern|static$/) {
+	    if(!$linkage) {
+		$linkage = $match;
+	    }
+	}
     }
 
-    $self->_parse_c("__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK", 
-	     \$_, \$line, \$column, \$calling_convention);
-    if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) { 
-	return 0; 
+
+    if(0) {
+	# Nothing
+    } elsif($self->_parse_c('DECL_GLOBAL_CONSTRUCTOR', \$_, \$line, \$column, \$name)) { # FIXME: Wine specific kludge
+	# Nothing
+    } elsif($self->_parse_c('WINE_EXCEPTION_FILTER\(\w+\)', \$_, \$line, \$column, \$name)) { # FIXME: Wine specific kludge
+	# Nothing
+    } else {
+	if(!$self->parse_c_type(\$_, \$line, \$column, \$return_type)) {
+	    return 0;
+	}
+
+	$self->_parse_c("__cdecl|__stdcall|inline|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK|WINE_UNUSED|PASCAL", 
+			\$_, \$line, \$column, \$calling_convention);
+	
+	if(!$self->_parse_c('\w+', \$_, \$line, \$column, \$name)) { 
+	    return 0; 
+	}
+
+	if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+	    return 0; 
+	}
     }
-    if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
-	return 0; 
+
+    my $kar;
+    # FIXME: Implement proper handling of K&R C functions
+    $self->_parse_c_until_one_of("{", \$_, \$line, \$column, $kar);
+
+    if($kar) {
+	$output->write("K&R: $kar\n");
     }
+
     if($_ && !$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
 	return 0;
     }
@@ -848,8 +970,8 @@ sub parse_c_function_call {
     my @argument_lines;
     my @argument_columns;
 
-    if(s/^(\w+)(\s*)\(/\(/s) {
-	$column += length("$1$2");
+    if(s/^(\w+)(\s*)(?=\()//s) {
+	$self->_update_c_position($&, \$line, \$column);
 
 	$name = $1;
 
@@ -899,13 +1021,13 @@ sub parse_c_preprocessor {
     
     if(0) {
 	# Nothing
-    } elsif(/^\#\s*define\s+(.*?)$/s) {
+    } elsif(/^\#\s*define\s*(.*?)$/s) {
 	$self->_update_c_position($_, \$line, \$column);
     } elsif(/^\#\s*else/s) {
 	$self->_update_c_position($_, \$line, \$column);
     } elsif(/^\#\s*endif/s) {
 	$self->_update_c_position($_, \$line, \$column);
-    } elsif(/^\#\s*(?:if|ifdef|ifndef)?\s+(.*?)$/s) {
+    } elsif(/^\#\s*(?:if|ifdef|ifndef)?\s*(.*?)$/s) {
 	$self->_update_c_position($_, \$line, \$column);
     } elsif(/^\#\s*include\s+(.*?)$/s) {
 	$self->_update_c_position($_, \$line, \$column);
@@ -940,12 +1062,9 @@ sub parse_c_statement {
 
     $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
 
-    if(s/^(?:case\s+)?(\w+)\s*://) {
-	$column += length($&);
-	$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
-    }
+    $self->_parse_c('(?:case\s+)?(\w+)\s*:\s*', \$_, \$line, \$column);
 
-    # $output->write("$line.$column: '$_'\n");
+    # $output->write("$line.$column: statement: '$_'\n");
 
     if(/^$/) {
 	# Nothing
@@ -959,11 +1078,10 @@ sub parse_c_statement {
 	if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
 	    return 0;
 	}
-    } elsif(/^(for|if|switch|while)(\s*)\(/) {
-	$column += length("$1$2");
-	my $name = $1;
+    } elsif(s/^(for|if|switch|while)\s*(?=\()//) {
+	$self->_update_c_position($&, \$line, \$column);
 
-	$_ = "($'";
+	my $name = $1;
 
 	my @arguments;
 	my @argument_lines;
@@ -985,10 +1103,16 @@ sub parse_c_statement {
 	    $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
 	}
     } elsif(s/^else//) {
-	$column += length($&);
+	$self->_update_c_position($&, \$line, \$column);
 	if(!$self->parse_c_statement(\$_, \$line, \$column)) {
 	    return 0;
 	}
+    } elsif(s/^return//) {
+	$self->_update_c_position($&, \$line, \$column);
+	$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+	if(!$self->parse_c_expression(\$_, \$line, \$column)) {
+	    return 0;
+	}
     } elsif($self->parse_c_expression(\$_, \$line, \$column)) {
 	# Nothing
     } else {
@@ -1022,20 +1146,31 @@ sub parse_c_statements {
 
     $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
 
+    # $output->write("$line.$column: statements: '$_'\n");
+
     my $statement = "";
     my $statement_line = $line;
     my $statement_column = $column;
 
+    my $previous_line = -1;
+    my $previous_column = -1;
+
     my $blevel = 1;
     my $plevel = 1;
     while($plevel > 0 || $blevel > 0) {
 	my $match;
 	$self->_parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
 
+	if($previous_line == $line && $previous_column == $column) {
+	    $self->_parse_c_error($_, $line, $column, "statements", "no progress");
+	}
+	$previous_line = $line;
+	$previous_column = $column;
+
 	# $output->write("'$match' '$_'\n");
 
-	$column++;
 	$statement .= $match;
+	$column++;
 	if(s/^[\(\[]//) {
 	    $plevel++;
 	    $statement .= $&;
@@ -1186,12 +1321,11 @@ sub parse_c_type {
 
     $self->_parse_c("const", \$_, \$line, \$column);
 
-
     if(0) {
 	# Nothing
     } elsif($self->_parse_c('ICOM_VTABLE\(.*?\)', \$_, \$line, \$column, \$type)) {
-		# Nothing
-    } elsif($self->_parse_c('\w+\s*(\*\s*)*', \$_, \$line, \$column, \$type)) {
+	# Nothing
+    } elsif($self->_parse_c('(?:enum\s+|struct\s+|union\s+)?\w+\s*(\*\s*)*', \$_, \$line, \$column, \$type)) {
 	# Nothing
     } else {
 	return 0;
@@ -1225,7 +1359,11 @@ sub parse_c_typedef {
 
     my $type;
 
-    if(!$self->_parse_c("typedef", \$_, \$line, \$column)) {
+    if($self->_parse_c("typedef", \$_, \$line, \$column)) {
+	# Nothing
+    } elsif($self->_parse_c('enum(?:\s+\w+)?\s*\{', \$_, \$line, \$column)) {
+	# Nothing
+    } else {
 	return 0;
     }
 
@@ -1264,12 +1402,137 @@ sub parse_c_variable {
     my $begin_column = $column + 1;
 
     my $linkage = "";
-    my $type;
-    my $name;
+    my $type = "";
+    my $name = "";
+
+    my $match;
+    while($self->_parse_c('const|inline|extern|static|volatile|' . 
+			  'signed(?=\\s+char|s+int|\s+long(?:\s+long)?|\s+short)|' .
+			  'unsigned(?=\s+char|\s+int|\s+long(?:\s+long)?|\s+short)',
+			  \$_, \$line, \$column, \$match)) 
+    {
+	if($match =~ /^extern|static$/) {
+	    if(!$linkage) {
+		$linkage = $match;
+	    }
+	}
+    }
+
+    my $finished = 0;
+
+    if($finished) {
+	# Nothing
+    } elsif($self->_parse_c('SEQ_DEFINEBUF', \$_, \$line, \$column, \$match)) { # Linux specific
+	$type = $match;
+	$finished = 1;
+    } elsif($self->_parse_c('DEFINE_GUID', \$_, \$line, \$column, \$match)) { # Windows specific
+	$type = $match;
+	$finished = 1;
+    } elsif($self->_parse_c('DEFINE_REGS_ENTRYPOINT_\w+|DPQ_DECL_\w+|HANDLER_DEF|IX86_ONLY', # Wine specific
+			    \$_, \$line, \$column, \$match))
+    { 
+	$type = $match;
+	$finished = 1;
+    } elsif($self->_parse_c('(?:struct\s+)?ICOM_VTABLE\s*\(\w+\)', \$_, \$line, \$column, \$match)) {
+	$type = $match;
+	$finished = 1;
+    } elsif(s/^(?:enum\s+|struct\s+|union\s+)(\w+)?\s*\{.*?\}\s*//s) {
+	$self->_update_c_position($&, \$line, \$column);
+
+	if(defined($1)) {
+	    $type = "struct $1 { }";
+	} else {
+	    $type = "struct { }";
+	}
+	if(defined($2)) {
+	    my $stars = $2;
+	    $stars =~ s/\s//g;
+	    if($stars) {
+		$type .= " $type";
+	    }
+	}
+    } elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+)\s*(?:\*\s*)*//s) {
+	$type = $&;
+	$type =~ s/\s//g;
+    } else {
+	return 0;
+    }
+
+    # $output->write("$type: '$_'\n");
+
+    if($finished) {
+	# Nothing
+    } elsif(s/^WINAPI\s*//) {
+	$self->_update_c_position($&, \$line, \$column);
+    }
+
+    if($finished) {
+	# Nothing
+    } elsif(s/^(\((?:__cdecl)?\s*\*?\s*(?:__cdecl)?\w+\s*(?:\[[^\]]*\]\s*)*\))\s*\(//) {
+	$self->_update_c_position($&, \$line, \$column);
+
+	$name = $1;
+	$name =~ s/\s//g;
+
+	$self->_parse_c_until_one_of("\\)", \$_, \$line, \$column);
+	if(s/^\)//) { $column++; }
+	$self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+        if(!s/^(?:=\s*|,\s*|$)//) {
+	    return 0;
+	}
+    } elsif(s/^(?:\*\s*)*(?:const\s+)?(\w+)\s*(?:\[[^\]]*\]\s*)*\s*(?:=\s*|,\s*|$)//) {
+	$self->_update_c_position($&, \$line, \$column);
+
+	$name = $1;
+	$name =~ s/\s//g;
+    } elsif(/^$/) {
+	$name = "";
+    } else {
+	return 0;
+    }
+ 
+    # $output->write("$type: $name: '$_'\n");
+
+    if(1) {
+	# Nothing
+    } elsif($self->_parse_c('(?:struct\s+)?ICOM_VTABLE\s*\(.*?\)', \$_, \$line, \$column, \$match)) {
+	$type = "<type>";
+	$name = "<name>";
+    } elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+)\s*
+		(?:\*\s*)*(\w+|\s*\*?\s*\w+\s*\))\s*(?:\[[^\]]*\]|\([^\)]*\))?
+		(?:,\s*(?:\*\s*)*(\w+)\s*(?:\[[^\]]*\])?)*
+	    \s*(?:=|$)//sx)
+    {
+	$self->_update_c_position($&, \$line, \$column);
+
+	$type = $1;
+	$name = $2;
+
+	$type =~ s/\s//g;
+	$type =~ s/^struct/struct /;
+    } elsif(/^(?:enum|struct|union)(?:\s+(\w+))?\s*\{.*?\}\s*((?:\*\s*)*)(\w+)\s*(?:=|$)/s) {
+	$self->_update_c_position($&, \$line, \$column);
 
-    $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
-    if(!$self->parse_c_type(\$_, \$line, \$column, \$type)) { return 0; }
-    if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) { return 0; }
+	if(defined($1)) {
+	    $type = "struct $1 { }";
+	} else {
+	    $type = "struct { }";
+	}
+	my $stars = $2;
+	$stars =~ s/\s//g;
+	if($stars) {
+	    $type .= " $type";
+	}
+
+	$name = $3;
+    } else {
+	return 0;
+    }
+
+    if(!$name) {
+        $name = "<name>";
+    }
 
     $$refcurrent = $_;
     $$refline = $line;
diff --git a/tools/winapi/make_parser.pm b/tools/winapi/make_parser.pm
index 1fa6e9d205d9d992f93e86eb7eb1197b42f8c605..3b389c590d1f8e5c1b05301e897387c08202640f 100644
--- a/tools/winapi/make_parser.pm
+++ b/tools/winapi/make_parser.pm
@@ -80,20 +80,22 @@ sub line {
 	my $progress = "";
 	if($directory && $directory ne ".") {
 	    $progress .= "$directory: ";
+	} 
+	if($tool) {
+	    $progress .= "$tool: ";
 	}
-	$progress .= "$tool: ";
 
 	if($tool =~ /^cd|make$/) {
 	    # Nothing
 	} elsif($tool =~ /^ld$/) {
 	    foreach my $file (@{$read_files}) {
-		$output->lazy_progress("$progress: reading '$file'");
+		$output->lazy_progress("${progress}reading '$file'");
 	    }
 	    my $file = $$write_files[0];
 	    $output->progress("$progress: writing '$file'");
 	} elsif($tool =~ /^rm$/) {
 	    foreach my $file (@{$remove_files}) {
-		$output->lazy_progress("$progress: removing '$file'");
+		$output->lazy_progress("${progress}removing '$file'");
 	    }
 	} else {
 	    if($#$read_files >= 0) {
@@ -118,24 +120,34 @@ sub line {
 	return 0;
     }
 
+    my $make = $options->make;
+
     if(/^Wine build complete\.$/) {
 	# Nothing
     } elsif(/^(.*?) is newer than (.*?), please rerun (.*?)\!$/) {
 	$message = "$_";
     } elsif(/^(.*?) is older than (.*?), please rerun (.*?)$/) {
 	$message = "$_";
-    } elsif(s/^make(?:\[(\d+)\])?:\s*//) {
+    } elsif(/^\`(.*?)\' is up to date.$/) {
+	$tool = "make";
+	make_output($1, $_);
+    } elsif(s/^$make(?:\[(\d+)\])?:\s*//) {
 	$tool = "make";
 	make_output($1, $_);
     } elsif(!defined($tool)) {
 	error("line");
+    } elsif($tool eq "make") {
+	make_output($1, $_);
     } elsif($tool eq "bison" && /^conflicts:\s+\d+\s+shift\/reduce$/) {
 	# Nothing
     } elsif($tool eq "gcc" && /^(?:In file included |\s*)from (.+?):(\d+)[,:]$/) {
 	# Nothing
     } elsif($tool =~ /^gcc|ld$/ && s/^(.+?\.s?o)(?:\(.*?\))?:\s*//) {
 	$tool = "ld";
-	ld_output($1, $_);
+	ld_output($1, $_)
+    } elsif($tool =~ /^gcc|ld$/ && s/^(.*?)ld:\s*//) {
+	$tool = "ld";
+	ld_output("", $_)
     } elsif($tool =~ /^gcc|ld$/ && s/^collect2:\s*//) {
 	$tool = "ld";
 	ld_output("collect2", $_);
@@ -149,6 +161,8 @@ sub line {
 	wrc_output($1, $_);
     } elsif($tool eq "cd" && s/^\/bin\/sh:\s*cd:\s*//) {
 	parse_cd_output($_);
+    } elsif(/^\s*$/) {
+	# Nothing
     } else {
 	error("line");
     }
@@ -172,7 +186,9 @@ sub make_output {
     if(0) {
 	# Nothing
     } elsif(/^\*\*\* \[(.*?)\] Error (\d+)$/) {
-	$message = "$_";
+	# Nothing
+    } elsif(/^\*\*\* Error code (\d+)$/) {
+	# Nothing
     } elsif(/^\*\*\* Warning:\s+/) { # 
 	if(/^File \`(.+?)\' has modification time in the future \((.+?) > \(.+?\)\)$/) {
 	    # Nothing
@@ -183,6 +199,8 @@ sub make_output {
 	# Nothing
     } elsif(/^\[(.*?)\] Error (\d+) \(ignored\)$/) {
 	# Nothing
+    } elsif(/^don\'t know how to make (.*?)\. Stop$/) {
+	$message = "$_";
     } elsif(/^(Entering|Leaving) directory \`(.*?)\'$/) {
 	if($1 eq "Entering") {
 	    $directory = $2;
@@ -209,6 +227,10 @@ sub make_output {
 	} else {
 	    error("make_output");
 	}
+    } elsif(/^Stop in (.*?)\.$/) {
+	# Nothing
+    } elsif(/^\s*$/) {
+	# Nothing
     } else {
 	error("make_output");
     }
@@ -399,13 +421,27 @@ sub gcc_command {
     my $write_files;
 
     if(/-o\s+(\S+)\s+(\S+)$/) {
-	$write_files = [$1];
-	$read_files = [$2];
+	my $write_file = $1;
+	my $read_file = $2;
+
+	$write_file =~ s%^\./%%;
+	$read_file =~ s%^\./%%;
+
+	$write_files = [$write_file];
+	$read_files = [$read_file];
     } elsif(/-o\s+(\S+)/) {
-	$write_files = [$1];
+	my $write_file = $1;
+
+	$write_file =~ s%^\./%%;
+
+	$write_files = [$write_file];
 	$read_files = ["<???>"];
     } elsif(/^-shared.*?-o\s+(\S+)/) {
-	$write_files = [$1];
+	my $write_file = $1;
+
+	$write_file =~ s%^\./%%;
+
+	$write_files = [$write_file];
 	$read_files = ["<???>"];
     } else {
 	error("gcc_command");
@@ -588,8 +624,16 @@ sub ld_output {
 	# Nothing
     } elsif(/^In function \`(.*?)\':$/) {
 	$function = $1;
-    } elsif(0 && /^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
+    } elsif(/^more undefined references to \`(.*?)\' follow$/) {
+	# Nothing
+    } elsif(/^the use of \`(.+?)\' is dangerous, better use \`(.+?)\'$/) {
 	# Nothing
+    } elsif(/^undefined reference to \`(.*?)\'$/) {
+	# Nothing
+    } elsif(/^warning: (.*?)\(\) possibly used unsafely; consider using (.*?)\(\)$/) {
+	# Nothing
+    } elsif(/^warning: type and size of dynamic symbol \`(.*?)\' are not defined$/) {
+	$message = "$_";
     } else {
 	$message = "$_";
     }
diff --git a/tools/winapi/options.pm b/tools/winapi/options.pm
index 4f2e6c51c2b6414ba90fd294f09c2fa69de9c4db..3f7cdf6659b841d4cc6896b4fbf097853ffbf252 100644
--- a/tools/winapi/options.pm
+++ b/tools/winapi/options.pm
@@ -63,6 +63,7 @@ sub new {
     $self->options_set("default");
 
     my $arguments = \@{$self->{_ARGUMENTS}};
+    @$arguments = ();
 
     my $end_of_options = 0;
     while(defined($_ = shift @ARGV)) {
@@ -121,6 +122,9 @@ sub new {
 		}
 
 		if(defined($parser)) { 
+		    if(!defined($value)) {
+			$value = shift @ARGV;
+		    }
 		    $$refvalue = &$parser($prefix,$value);
 		} else {
 		    if(defined($value)) {
diff --git a/tools/winapi/output.pm b/tools/winapi/output.pm
index c6154ed0d4b8bbec7e9cebb0b7193e244932f66d..49939740f82774cc566c4452bd6fbca163e21569 100644
--- a/tools/winapi/output.pm
+++ b/tools/winapi/output.pm
@@ -137,10 +137,17 @@ sub progress {
     my $progress = \${$self->{PROGRESS}};
     my $last_time = \${$self->{LAST_TIME}};
 
-    $$progress = shift;
+    my $new_progress = shift;
+    if(defined($new_progress)) {
+	if(!defined($$progress) || $new_progress ne $$progress) {
+	    $$progress = $new_progress;
 
-    $self->update_progress;
-    $$last_time = 0;
+	    $self->update_progress;
+	    $$last_time = 0;
+	}
+    } else {
+	return $$progress;
+    }
 }
 
 sub lazy_progress {
@@ -164,8 +171,10 @@ sub prefix {
 
     my $new_prefix = shift;
     if(defined($new_prefix)) {
-	$$prefix = $new_prefix;
-	$$prefix_callback = undef;
+	if(!defined($$prefix) || $new_prefix ne $$prefix) {
+	    $$prefix = $new_prefix;
+	    $$prefix_callback = undef;
+	}
     } else {
 	return $$prefix;
     }
diff --git a/tools/winapi/winapi_fixup b/tools/winapi/winapi_fixup
index 6f79c368496ccb670e39812f5c217f7565590762..4ac4b3946ed89772a42b2868d5f6f3d0b8cdc6b5 100755
--- a/tools/winapi/winapi_fixup
+++ b/tools/winapi/winapi_fixup
@@ -53,9 +53,43 @@ foreach my $file (@c_files) {
 	$_ = <IN>;
 	close(IN);
     }
-    
+   
+    my $max_line = 0;
+    { 
+      local $_ = $_;
+      while(s/^.*?\n//) { $max_line++; }
+      if($_) { $max_line++; }
+    }
+
     my $parser = new c_parser($file);
 
+    my $function;
+    my $line;
+
+    my $update_output = sub {
+	my $progress = "";
+	my $prefix = "";
+
+	$progress .= "$file (file $progress_current of $progress_max)";
+	$prefix .= "$file:";
+
+	if(defined($function)) {
+	    my $name = $function->name;
+	    my $begin_line = $function->begin_line;
+	    my $begin_column = $function->begin_column;
+
+	    $progress .= ": function $name";
+	    $prefix .= "$begin_line.$begin_column: function $name: ";
+	}
+
+	if(defined($line)) {
+	    $progress .= ": line $line of $max_line";
+	}
+
+	$output->progress($progress);
+	$output->prefix($prefix);
+    };
+
     my $found_preprocessor = sub {
 	my $begin_line = shift;
 	my $begin_column = shift;
@@ -80,6 +114,17 @@ foreach my $file (@c_files) {
 
     $parser->set_found_comment_callback($found_comment);  
 
+    my $found_line = sub {
+	$line = shift;
+	# local $_ = shift;
+
+	&$update_output;
+
+	# $output->progress("$file: line $line of ?");
+    };
+
+    $parser->set_found_line_callback($found_line);
+
     my $found_declaration = sub {
 	my $begin_line = shift;
 	my $begin_column = shift;
@@ -94,19 +139,17 @@ foreach my $file (@c_files) {
 
     $parser->set_found_declaration_callback($found_declaration);  
 
-    my $function;
-
     my $found_function = sub {
 	$function = shift;
-	
+
+	&$update_output;
+
 	my $name = $function->name;
 	my $begin_line = $function->begin_line;
 	my $begin_column = $function->begin_column;
-	
-	$output->progress("$file (file $progress_current of $progress_max): $name");
-	$output->prefix("$file:$begin_line: function $name: ");
-	# $output->prefix_callback(sub { return $function->prefix; });
-	
+	my $end_line = $function->end_line;
+	my $end_column = $function->end_column;
+
 	if($options->documentation) {
 	    # fixup_documentation($function, $editor);
 	}
@@ -119,6 +162,8 @@ foreach my $file (@c_files) {
 	if(!defined($statements)) {
 	    $function = undef;
 	    $output->prefix("$file: ");
+	} else {
+	    # $output->write("$begin_line.$begin_column-$end_line.$end_column: function $name\n");
 	}
 
 	return 0;
@@ -133,20 +178,38 @@ foreach my $file (@c_files) {
 	my $type = shift;
 	my $name = shift;
 
-	# $output->write("$begin_line.$begin_column: $linkage $type $name\n");
+	# $output->write("$begin_line.$begin_column: $linkage $type $name = /* ... */\n");
 	
 	return 1;
     };
 
     $parser->set_found_variable_callback($found_variable);        
 
-    my $line = 1;
-    my $column = 0;
-    if(!$parser->parse_c_file(\$_, \$line, \$column)) {
-	$output->write("can't parse file\n");
+    my $found_function_call = sub {
+	my $begin_line = shift;
+	my $begin_column = shift;
+	my $end_line = shift;
+	my $end_column = shift;
+	my $name = shift;
+	my $arguments = shift;
+
+	$output->write("$begin_line.$begin_column-$end_line.$end_column: $name(" . join(", ", @$arguments) . ")\n");
+
+	return 1;
+    };
+
+    $parser->set_found_function_call_callback($found_function_call);
+
+    {
+	my $line = 1;
+	my $column = 0;
+	if(!$parser->parse_c_file(\$_, \$line, \$column)) {
+	    $output->write("can't parse file\n");
+	}
     }
 
     $output->prefix("");
 
     $editor->flush;
 }
+
diff --git a/tools/winapi/winapi_fixup_statements.pm b/tools/winapi/winapi_fixup_statements.pm
index 9eb648c6d693d5cde7b6bafb560adbadf7a88e53..83b92febfc777f7bf56da43eaf91c7ff1e02ff6b 100644
--- a/tools/winapi/winapi_fixup_statements.pm
+++ b/tools/winapi/winapi_fixup_statements.pm
@@ -162,20 +162,26 @@ sub fixup_user_message_2_windowsx {
 }
 
 ########################################################################
-# _fixup_user_message
+# _get_messages
 
 sub _get_messages {
     local $_ = shift;
 
-    if(/^WM_\w+$/) {
-	return ($_)
-    } elsif(/^(.*?)\s*\?\s*(WM_\w+)\s*:\s*(WM_\w+)$/) {
+    if(/^(?:BM|CB|EM|LB|STM|WM)_\w+(.*?)$/) {
+	if(!$1) {
+	    return ($_);
+	} else {
+	    return ();
+	}
+    } elsif(/^(.*?)\s*\?\s*((?:BM|CB|EM|LB|STM|WM)_\w+)\s*:\s*((?:BM|CB|EM|LB|STM|WM)_\w+)$/) {
 	return ($2, $3);
     } elsif(/^\w+$/) {
 	return ();
+    } elsif(/^RegisterWindowMessage[AW]\s*\(.*?\)$/) {
+	return ();
     } else {
-	$output->write("_fixup_user_message: '$_'\n");
-	exit 1;
+	$output->write("warning: _get_messages: '$_'\n");
+	return ();
     }
 }
 
@@ -215,7 +221,9 @@ sub _fixup_user_message {
 
 	if(!defined($kind)) {
 	    if($msg =~ /^WM_/) {
-		$output->write("messsage $msg not defined\n");
+		$output->write("messsage $msg not properly defined\n");
+		$modified = 0;
+		last;
 	    }
 	} elsif($kind eq "ptr") {
 	    if($$refparam =~ /^(\(${upper}PARAM\))?\s*($lower[pP]aram)$/) {
@@ -263,15 +271,6 @@ sub fixup_statements {
 	return;
     }
 
-    if(0 && $statements_line > 490) {
-	$output->write("$statements_line: \\\n");
-	my $line = $statements_line;
-	foreach my $statement (split(/\n/, $statements)) {
-	    $output->write("$line: $statement\n");
-	    $line++;
-	}
-    }
-
     my $parser = new c_parser($file);
     
     my $found_function_call = sub {
@@ -302,7 +301,7 @@ sub fixup_statements {
 	    if(defined($replace)) {
 		$editor->replace($begin_line, $begin_column, $end_line, $end_column, $replace);
 	    }
-	}  elsif(0 || $options->debug) {
+	} elsif($options->debug) {
 	    $output->write("$begin_line.$begin_column-$end_line.$end_column: " .
 			   "$name(" . join(", ", @$arguments) . ")\n");
 	}
diff --git a/tools/winapi/winapi_module_user.pm b/tools/winapi/winapi_module_user.pm
index be853c5a9aa5aece5e96909a6296708db6ea57e9..afb23dcdb39c9951147b6006c41ca325702400f1 100644
--- a/tools/winapi/winapi_module_user.pm
+++ b/tools/winapi/winapi_module_user.pm
@@ -41,32 +41,65 @@ sub is_user_function {
 
 $message = {
     WM_ACTIVATE => {
-	id => 0, result => "void", wparam => ["", ""], lparam => "HWND" },
+	id => 0x0006, result => "void", wparam => ["", ""], lparam => "HWND" },
     WM_ACTIVATEAPP => {
-	id => 0, result => "void", wparam => "BOOL", lparam => "LPARAM" },
+	id => 0x001c, result => "void", wparam => "BOOL", lparam => "DWORD" },
+    WM_ACTIVATESHELLWINDOW => {
+        id => 0x003e, result => "", wparam => "", lparam => "" },
+    WM_ACTIVATETOPLEVEL => {
+        id => 0x036e, result => "", wparam => "", lparam => "" },
+    WM_ALTTABACTIVE => {
+        id => 0x0029, result => "", wparam => "", lparam => "" },
+    WM_APP => {
+        id => 0x8000, result => "", wparam => "", lparam => "" },
+    WM_ASKCBFORMATNAME => {
+        id => 0x030c, result => "void", wparam => "int", lparam => "LPTSTR" },
 
     WM_BEGINDRAG => {
-	id => 0, result => "", wparam => "", lparam => "" },
+	id => 0x022c, result => "", wparam => "", lparam => "" },
 
     WM_CANCELMODE => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x001f, result => "void", wparam => "void", lparam => "void" },
+    WM_CANCELJOURNAL => {
+        id => 0x004b, result => "", wparam => "", lparam => "" },
+    WM_CAPTURECHANGED => {
+        id => 0x0215, result => "void", wparam => "void", lparam => "HWND" },
+    WM_CHANGECBCHAIN => {
+        id => 0x030d, result => "void", wparam => "HWND", lparam => "HWND" },
+    WM_CHILDACTIVATE => {
+        id => 0x0022, result => "void", wparam => "void", lparam => "void" },
+    WM_CLEAR => {
+        id => 0x0303, result => "void", wparam => "void", lparam => "void" },
     WM_CHAR => {
-	id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+	id => 0x0102, result => "void", wparam => "TCHAR", lparam => ["", ""] },
     WM_CHARTOITEM => {
-	id => 0x002f, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+	id => 0x002f, result => "int", wparam => ["UINT", "UINT"], lparam => "HWND" },
     WM_CLOSE => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0010, result => "void", wparam => "void", lparam => "void" },
+    WM_COALESCE_FIRST => {
+        id => 0x0390, result => "", wparam => "", lparam => "" },
+    WM_COALESCE_LAST => {
+        id => 0x039f, result => "", wparam => "", lparam => "" },
     WM_COMMAND => {
-	id => 0, result => "void", wparam => ["int", "UINT"], lparam => "HWND" },
+	id => 0x0111, result => "void", wparam => ["UINT", "UINT"], lparam => "HWND" },
+    WM_COMMANDHELP => {
+        id => 0x0365, result => "", wparam => "", lparam => "" },
+    WM_COMMNOTIFY => {
+        id => 0x0044, result => "void", wparam => "int", lparam => ["", ""] },
+    WM_CONTEXTMENU => {
+        id => 0x007b, result => "void", wparam => "HWND", lparam => ["UINT", "UINT"] },
     WM_COPY => {
 	id => 0x0301, result => "void", wparam => "void", lparam => "void" },
+    WM_COPYDATA => {
+        id => 0x004a, result => "", wparam => "", lparam => "" },
     WM_COMPACTING => { 
-	id => 0, result => "void", wparam => "UINT", lparam => "void" },
+	id => 0x0041, result => "void", wparam => "UINT", lparam => "void" },
     WM_COMPAREITEM => { 
-	id => 0, result => "int", wparam => "UINT", lparam => "const COMPAREITEMSTRUCT *" },
-
+	id => 0x0039, result => "int", wparam => "UINT", lparam => "const COMPAREITEMSTRUCT *" },
     WM_CREATE => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
+	id => 0x0001, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
+    WM_CTLCOLOR => {
+        id => 0x0019, result => "", wparam => "", lparam => "" },
     WM_CTLCOLORBTN => {
 	id => 0x0135, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
     WM_CTLCOLORDLG => {
@@ -81,199 +114,427 @@ $message = {
 	id => 0x137, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
     WM_CTLCOLORSTATIC => {
 	id => 0x138, result => "HBRUSH", wparam => "HDC", lparam => "HWND" },
-
     WM_CUT => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0300, result => "void", wparam => "void", lparam => "void" },
 
+    WM_DDE_ACK => { # FIXME: Only correct if replying to WM_DDE_INITIATE
+	id => 0x03E4, result => "void", wparam => "HWND", lparam => ["ATOM", "ATOM"] },
+    WM_DDE_INITIATE => {
+	id => 0x03E0, result => "void", wparam => "HWND", lparam => ["ATOM", "ATOM"] },
     WM_DEADCHAR => {
-	id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+	id => 0x0103, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+    WM_DEVICECHANGE => {
+        id => 0x0219, result => "BOOL", wparam => "UINT", lparam => "DWORD" },
     WM_DELETEITEM => { 
-	id => 0, result => "void", wparam => "UINT", lparam => "const DELETEITEMSTRUCT *" },
+	id => 0x002d, result => "void", wparam => "UINT", lparam => "const DELETEITEMSTRUCT *" },
     WM_DEVMODECHANGE => {
-	id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" },
+	id => 0x001b, result => "void", wparam => "void", lparam => "LPCTSTR" },
     WM_DESTROY => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0002, result => "void", wparam => "void", lparam => "void" },
+    WM_DESTROYCLIPBOARD => {
+        id => 0x0307, result => "void", wparam => "void", lparam => "void" },
+    WM_DISABLEMODAL => {
+        id => 0x036c, result => "", wparam => "", lparam => "" },
+    WM_DISPLAYCHANGE => {
+        id => 0x007e, result => "void", wparam => "UINT", lparam => ["UINT", "UINT"] },
+    WM_DRAGLOOP => {
+        id => 0x022d, result => "", wparam => "", lparam => "" },
+    WM_DRAGMOVE => {
+        id => 0x022f, result => "", wparam => "", lparam => "" },
+    WM_DRAGSELECT => {
+        id => 0x022e, result => "", wparam => "", lparam => "" },
+    WM_DRAWCLIPBOARD => {
+        id => 0x0308, result => "void", wparam => "void", lparam => "void" },
     WM_DRAWITEM => {
-	id => 0, result => "void", wparam => "void", lparam => "const DRAWITEMSTRUCT *" },
+	id => 0x002b, result => "void", wparam => "UINT", lparam => "const DRAWITEMSTRUCT *" },
     WM_DROPFILES => {
-	id => 0, result => "void", wparam => "HDROP", lparam => "void" },
+	id => 0x0233, result => "void", wparam => "HDROP", lparam => "void" },
+    WM_DROPOBJECT => {
+        id => 0x022a, result => "", wparam => "", lparam => "" },
 
     WM_ENABLE => {
-	id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+	id => 0x000a, result => "void", wparam => "BOOL", lparam => "void" },
     WM_ENDSESSION => {
-	id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+	id => 0x0016, result => "void", wparam => "BOOL", lparam => "void" },
     WM_ENTERIDLE => {
 	id => 0x0121, result => "void", wparam => "UINT", lparam => "HWND" },
+    WM_ENTERSIZEMOVE => {
+        id => 0x0231, result => "", wparam => "", lparam => "" },
     WM_ENTERMENULOOP => {
 	id => 0x0211, result => "", wparam => "", lparam => "" },
     WM_ERASEBKGND => {
-	id => 0, result => "BOOL", wparam => "HDC", lparam => "void" },
+	id => 0x0014, result => "BOOL", wparam => "HDC", lparam => "void" },
+    WM_EXITHELPMODE => {
+        id => 0x0367, result => "", wparam => "", lparam => "" },
     WM_EXITMENULOOP => {
 	id => 0x0212, result => "", wparam => "", lparam => "" },
+    WM_EXITSIZEMOVE => {
+        id => 0x0232, result => "", wparam => "", lparam => "" },
 
+    WM_FILESYSCHANGE => {
+        id => 0x0034, result => "", wparam => "", lparam => "" },
+    WM_FLOATSTATUS => {
+        id => 0x036d, result => "", wparam => "", lparam => "" },
     WM_FONTCHANGE => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
-
+	id => 0x001d, result => "void", wparam => "void", lparam => "void" },
+
+    WM_GETDLGCODE => {
+        id => 0x0087, result => "UINT", wparam => "WPARAM", lparam => "LPMSG" },
+    WM_GETFONT => {
+        id => 0x0031, result => "HFONT", wparam => "void", lparam => "void" },
+    WM_GETHOTKEY => {
+        id => 0x0033, result => "", wparam => "", lparam => "" },
+    WM_GETICON => {
+        id => 0x007f, result => "", wparam => "", lparam => "" },
+    WM_GETMINMAXINFO => {
+        id => 0x0024, result => "void", wparam => "void", lparam => "LPMINMAXINFO" },
     WM_GETTEXT => {
-	id => 0, result => "int", wparam => "int", lparam => "LPTSTR" },
+	id => 0x000d, result => "int", wparam => "int", lparam => "LPTSTR" },
     WM_GETTEXTLENGTH => {
-	id => 0, result => "int", wparam => "void", lparam => "void" },
+	id => 0x000e, result => "int", wparam => "void", lparam => "void" },
 
     WM_HELP => {
-	id => 0x0053, result => "", wparam => "", lparam => "" },
+	id => 0x0053, result => "void", wparam => "void", lparam => "LPHELPINFO" },
+    WM_HELPHITTEST => {
+        id => 0x0366, result => "", wparam => "", lparam => "" },
+    WM_HOTKEY => {
+        id => 0x0312, result => "", wparam => "", lparam => "" },
     WM_HSCROLL => {
-	id => 0, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+	id => 0x0114, result => "void", wparam => ["int", "int"], lparam => "HWND" },
+    WM_HSCROLLCLIPBOARD => {
+        id => 0x030e, result => "void", wparam => "HWND", lparam => "" },
 
     WM_ICONERASEBKGND => {
-	id => 0, result => "BOOL", wparam => "HDC", lparam => "void" },
+	id => 0x0027, result => "BOOL", wparam => "HDC", lparam => "void" },
+    WM_IME_CHAR => {
+        id => 0x0286, result => "", wparam => "", lparam => "" },
+    WM_IME_COMPOSITION => {
+        id => 0x010f, result => "", wparam => "", lparam => "" },
+    WM_IME_COMPOSITIONFULL => {
+        id => 0x0284, result => "", wparam => "", lparam => "" },
+    WM_IME_CONTROL => {
+        id => 0x0283, result => "", wparam => "", lparam => "" },
+    WM_IME_ENDCOMPOSITION => {
+        id => 0x010e, result => "", wparam => "", lparam => "" },
+    WM_IME_KEYDOWN => {
+	id => 0x0290, result => "void", wparam => "UINT", lparam => ["int", "UINT"] },
+    WM_IME_KEYLAST => {
+        id => 0x010f, result => "", wparam => "", lparam => "" },
+    WM_IME_KEYUP => {
+	id => 0x0291, result => "void", wparam => "UINT", lparam => ["int", "UINT"] },
+    WM_IME_NOTIFY => {
+        id => 0x0282, result => "", wparam => "", lparam => "" },
+    WM_IME_REQUEST => {
+        id => 0x0288, result => "", wparam => "", lparam => "" },
+    WM_IME_SELECT => {
+        id => 0x0285, result => "", wparam => "", lparam => "" },
+    WM_IME_SETCONTEXT => {
+        id => 0x0281, result => "", wparam => "", lparam => "" },
+    WM_IME_STARTCOMPOSITION => {
+        id => 0x010d, result => "", wparam => "", lparam => "" },
+    WM_IDLEUPDATECMDUI => {
+        id => 0x0363, result => "", wparam => "", lparam => "" },
+    WM_INITDIALOG => {
+        id => 0x0110, result => "BOOL", wparam => "HWND", lparam => "LPARAM" },
+    WM_INITIALUPDATE => {
+        id => 0x0364, result => "", wparam => "", lparam => "" },
     WM_INITMENU => {
-	id => 0, result => "void", wparam => "HMENU", lparam => "void" },
+	id => 0x0116, result => "void", wparam => "HMENU", lparam => "void" },
     WM_INITMENUPOPUP => {
-	id => 0, result => "void", wparam => "HMENU", lparam => ["UINT", "BOOL"] },
+	id => 0x0117, result => "void", wparam => "HMENU", lparam => ["UINT", "BOOL"] },
+    WM_INPUTLANGCHANGE => {
+        id => 0x0051, result => "", wparam => "", lparam => "" },
+    WM_INPUTLANGCHANGEREQUEST => {
+        id => 0x0050, result => "", wparam => "", lparam => "" },
     WM_ISACTIVEICON => {
-	id => 0, result => "", wparam => "", lparam => "" },
+	id => 0x0035, result => "", wparam => "", lparam => "" },
 
     WM_KEYDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0100, result => "void", wparam => "UINT", lparam => ["int", "UINT"] },
+    WM_KEYLAST => {
+	id => 0x0108, result => "", wparam => "", lparam => "" },
+    WM_KICKIDLE => {
+	id => 0x036a, result => "", wparam => "", lparam => "" },
     WM_KEYUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0101, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_KILLFOCUS => {
-	id => 0, result => "void", wparam => "HWND", lparam => "void" },
+	id => 0x0008, result => "void", wparam => "HWND", lparam => "void" },
 
     WM_LBTRACKPOINT => {
-	id => 0, result => "", wparam => "", lparam => "" },
+	id => 0x0131, result => "", wparam => "", lparam => "" },
     WM_LBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0203, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_LBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0201, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_LBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0202, result => "void", wparam => "UINT", lparam => ["", ""] },
 
     WM_MBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0209, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_MBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0207, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_MBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0208, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_MDIACTIVATE => {
+	id => 0x0222, result => "void", wparam => "HWND", lparam => "HWND" },
+    WM_MDICASCADE => {
+	id => 0x0227, result => "BOOL", wparam => "UINT", lparam => "void" },
+    WM_MDICREATE => {
+	id => 0x0220, result => "HWND", wparam => "void", lparam => "const LPMDICREATESTRUCT" },
+    WM_MDIDESTROY => {
+	id => 0x0221, result => "void", wparam => "HWND", lparam => "void" },
+    WM_MDIGETACTIVE => {
+	id => 0x0229, result => "HWND", wparam => "void", lparam => "void" },
+    WM_MDIICONARRANGE => {
+	id => 0x0228, result => "void", wparam => "void", lparam => "void" },
+    WM_MDIMAXIMIZE => {
+	id => 0x0225, result => "void", wparam => "HWND", lparam => "void" },
+    WM_MDINEXT => {
+	id => 0x0224, result => "HWND", wparam => "HWND", lparam => "BOOL" },
+    WM_MDIREFRESHMENU => {
+	id => 0x0234, result => "", wparam => "", lparam => "" },
+    WM_MDIRESTORE => {
+	id => 0x0223, result => "void", wparam => "HWND", lparam => "void" },
+    WM_MDISETMENU => {
+	id => 0x0230, result => "HMENU", wparam => "BOOL", lparam => "HMENU" },
+    WM_MDITILE => {
+	id => 0x0226, result => "BOOL", wparam => "UINT", lparam => "void" },
     WM_MEASUREITEM => {
-	id => 0, result => "void", wparam => "UINT", lparam => "MEASUREITEMSTRUCT *" },
+	id => 0x002c, result => "void", wparam => "UINT", lparam => "MEASUREITEMSTRUCT *" },
     WM_MENUSELECT => {
-	id => 0, result => "void", wparam => ["", ""], lparam => "HMENU" },
+	id => 0x011f, result => "void", wparam => ["", ""], lparam => "HMENU" },
     WM_MENUCHAR => {
-	id => 0, result => "DWORD", wparam => ["", ""], lparam => "HMENU" },
+	id => 0x0120, result => "DWORD", wparam => ["", "WORD"], lparam => "HMENU" },
     WM_MOUSEACTIVATE => {
-	id => 0, result => "int", wparam => "HWND", lparam => ["", ""] },
+	id => 0x0021, result => "int", wparam => "HWND", lparam => ["", ""] },
     WM_MOUSEMOVE => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0200, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_MOUSEWHEEL => {
+	id => 0x020a, result => "void", wparam => ["DWORD", "int"], lparam => ["UINT", "UINT"] },
     WM_MOVE => {
-	id => 0, result => "void", wparam => "void", lparam => ["", ""] },
+	id => 0x0003, result => "void", wparam => "void", lparam => ["", ""] },
+    WM_MOVING => {
+	id => 0x0216, result => "", wparam => "", lparam => "" },
 
     WM_NCACTIVATE => {
-	id => 0, result => "BOOL", wparam => "BOOL", lparam => "void" },
+	id => 0x0086, result => "BOOL", wparam => "BOOL", lparam => "void" },
     WM_NCLBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a3, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCLBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a1, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCLBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a2, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCMOUSEMOVE => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a0, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCMBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a9, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCMBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a7, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCMBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a8, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCRBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a6, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCRBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a4, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCRBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x00a5, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_NCCALCSIZE => {
-	id => 0, result => "UINT", wparam => "void", lparam => "LPARAM" },
+	id => 0x0083, result => "UINT", wparam => "void", lparam => "NCCALCSIZE_PARAMS *" },
     WM_NCCREATE => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
+	id => 0x0081, result => "BOOL", wparam => "void", lparam => "LPCREATESTRUCT" },
     WM_NCDESTROY => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0082, result => "void", wparam => "void", lparam => "void" },
+    WM_NCHITTEST => {
+	id => 0x0084, result => "UINT", wparam => "void", lparam => ["int", "int"] },
     WM_NCPAINT => {
-	id => 0, result => "void", wparam => "HRGN", lparam => "void" },
+	id => 0x0085, result => "void", wparam => "HRGN", lparam => "void" },
+    WM_NEXTDLGCTL => {
+	id => 0x0028, result => "HWND", wparam => "HWND", lparam => "BOOL" },
     WM_NEXTMENU => {
-	id => 0x0213, result => "", wparam => "", lparam => "" },
+	id => 0x0213, result => "void", wparam => "UINT", lparam => "LPMDINEXTMENU" },
     WM_NOTIFY => {
 	id => 0x004e, result => "LRESULT", wparam => "int", lparam => "NMHDR *" },
+    WM_NOTIFYFORMAT => {
+	id => 0x0055, result => "", wparam => "", lparam => "" },
+    WM_NULL => {
+	id => 0x0000, result => "", wparam => "", lparam => "" },
+
+    WM_OCC_INITNEW => {
+	id => 0x0378, result => "", wparam => "", lparam => "" },
+    WM_OCC_LOADFROMSTORAGE => {
+	id => 0x0377, result => "", wparam => "", lparam => "" },
+    WM_OCC_LOADFROMSTORAGE_EX => {
+	id => 0x037b, result => "", wparam => "", lparam => "" },
+    WM_OCC_LOADFROMSTREAM => {
+	id => 0x0376, result => "", wparam => "", lparam => "" },
+    WM_OCC_LOADFROMSTREAM_EX => {
+	id => 0x037a, result => "", wparam => "", lparam => "" },
+    WM_OTHERWINDOWCREATED => {
+	id => 0x003c, result => "", wparam => "", lparam => "" },
+    WM_OTHERWINDOWDESTROYED => {
+	id => 0x003d, result => "", wparam => "", lparam => "" },
 
-
+    WM_PAINT => {
+	id => 0x000f, result => "void", wparam => "void", lparam => "void" },
+    WM_PAINTCLIPBOARD => {
+	id => 0x0309, result => "void", wparam => "HWND", lparam => "const LPPAINTSTRUCT" },
+    WM_PAINTICON => {
+	id => 0x0026, result => "", wparam => "", lparam => "" },
     WM_PALETTEISCHANGING => {
-	id => 0, result => "void", wparam => "HWND", lparam => "void" },
+	id => 0x0310, result => "void", wparam => "HWND", lparam => "void" },
     WM_PALETTECHANGED => {
-	id => 0, result => "void", wparam => "HWND", lparam => "void" },
-    WM_PAINT => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0311, result => "void", wparam => "HWND", lparam => "void" },
+    WM_PARENTNOTIFY => {
+	id => 0x0210, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
     WM_PASTE => {
 	id => 0x0302, result => "void", wparam => "void", lparam => "void" },
+    WM_PENWINFIRST => {
+	id => 0x0380, result => "", wparam => "", lparam => "" },
+    WM_PENWINLAST => {
+	id => 0x038f, result => "", wparam => "", lparam => "" },
+    WM_POPMESSAGESTRING => {
+	id => 0x0375, result => "", wparam => "", lparam => "" },
     WM_POWER => {
-	id => 0, result => "void", wparam => "int", lparam => "void" },
-
+	id => 0x0048, result => "void", wparam => "int", lparam => "void" },
+    WM_POWERBROADCAST => {
+	id => 0x0218, result => "", wparam => "", lparam => "" },
+    WM_PRINT => {
+	id => 0x0317, result => "", wparam => "", lparam => "" },
+    WM_PRINTCLIENT => {
+	id => 0x0318, result => "void", wparam => "HDC", lparam => "DWORD" },
+
+    WM_QUERY3DCONTROLS => {
+	id => 0x036f, result => "", wparam => "", lparam => "" },
+    WM_QUERYAFXWNDPROC => {
+	id => 0x0360, result => "", wparam => "", lparam => "" },
+    WM_QUERYCENTERWND => {
+	id => 0x036b, result => "", wparam => "", lparam => "" },
     WM_QUERYDRAGICON => {
-	id => 0, result => "HICON", wparam => "void", lparam => "void" },
+	id => 0x0037, result => "HICON", wparam => "void", lparam => "void" },
+    WM_QUERYDROPOBJECT => {
+	id => 0x022b, result => "", wparam => "", lparam => "" },
     WM_QUERYENDSESSION => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+	id => 0x0011, result => "BOOL", wparam => "void", lparam => "void" },
     WM_QUERYNEWPALETTE => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+	id => 0x030f, result => "BOOL", wparam => "void", lparam => "void" },
     WM_QUERYOPEN => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "void" },
+	id => 0x0013, result => "BOOL", wparam => "void", lparam => "void" },
+    WM_QUERYPARKICON => {
+	id => 0x0036, result => "", wparam => "", lparam => "" },
+    WM_QUERYSAVESTATE => {
+	id => 0x0038, result => "", wparam => "", lparam => "" },
+    WM_QUEUESYNC => {
+	id => 0x0023, result => "void", wparam => "void", lparam => "void" },
+    WM_QUEUE_SENTINEL => {
+	id => 0x0379, result => "", wparam => "", lparam => "" },
     WM_QUIT => {
-	id => 0, result => "void", wparam => "WPARAM", lparam => "void" },
+	id => 0x0012, result => "void", wparam => "int", lparam => "void" },
 
     WM_RBUTTONDBLCLK => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0206, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_RBUTTONDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0204, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_RBUTTONUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0205, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_RECALCPARENT => {
+	id => 0x0368, result => "", wparam => "", lparam => "" },
+    WM_RENDERALLFORMATS => {
+	id => 0x0306, result => "void", wparam => "void", lparam => "void" },
+    WM_RENDERFORMAT => {
+	id => 0x0305, result => "HANDLE", wparam => "UINT", lparam => "void" },
 
     WM_SETCURSOR => {
-	id => 0x0020, result => "", wparam => "HWND", lparam => ["UINT", "UINT"] },
+	id => 0x0020, result => "BOOL", wparam => "HWND", lparam => ["UINT", "UINT"] },
     WM_SETFOCUS => {
-	id => 0, result => "void", wparam => "HWND", lparam => "void" },
+	id => 0x0007, result => "void", wparam => "HWND", lparam => "void" },
     WM_SETFONT => {
 	id => 0x0030, result => "void", wparam => "HFONT", lparam => "BOOL" },
+    WM_SETHOTKEY => {
+	id => 0x0032, result => "", wparam => "", lparam => "" },
+    WM_SETICON => {
+	id => 0x0080, result => "HICON", wparam => "DWORD", lparam => "HICON" },
+    WM_SETMESSAGESTRING => {
+	id => 0x0362, result => "", wparam => "", lparam => "" },
     WM_SETREDRAW => {
-	id => 0, result => "void", wparam => "BOOL", lparam => "void" },
+	id => 0x000b, result => "void", wparam => "BOOL", lparam => "void" },
     WM_SETTEXT => {
-	id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" },
+	id => 0x000c, result => "void", wparam => "void", lparam => "LPCTSTR" },
+    WM_SETVISIBLE => {
+	id => 0x0009, result => "", wparam => "", lparam => "" },
     WM_SHOWWINDOW => {
-	id => 0, result => "void", wparam => "BOOL", lparam => "UINT" },
+	id => 0x0018, result => "void", wparam => "BOOL", lparam => "UINT" },
     WM_SIZE => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0005, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_SIZECHILD => {
+	id => 0x0369, result => "", wparam => "", lparam => "" },
+    WM_SIZECLIPBOARD => {
+	id => 0x030b, result => "void", wparam => "HWND", lparam => "const LPRECT" },
+    WM_SIZEPARENT => {
+	id => 0x0361, result => "", wparam => "", lparam => "" },
+    WM_SIZEWAIT => {
+	id => 0x0004, result => "", wparam => "", lparam => "" },
+    WM_SIZING => {
+	id => 0x0214, result => "", wparam => "", lparam => "" },
+    WM_SOCKET_DEAD => {
+	id => 0x0374, result => "", wparam => "", lparam => "" },
+    WM_SOCKET_NOTIFY => {
+	id => 0x0373, result => "", wparam => "", lparam => "" },
     WM_SPOOLERSTATUS => {
-	id => 0, result => "void", wparam => "WPARAM", lparam => ["", ""] },
+	id => 0x002a, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_STYLECHANGED => {
+	id => 0x007d, result => "void", wparam => "DWORD", lparam => "LPSTYLESTRUCT" },
+    WM_STYLECHANGING => {
+	id => 0x007c, result => "void", wparam => "DWORD", lparam => "LPSTYLESTRUCT" },
+    WM_SYNCPAINT => {
+	id => 0x0088, result => "", wparam => "", lparam => "" },
+    WM_SYNCTASK => {
+	id => 0x0089, result => "", wparam => "", lparam => "" },
     WM_SYSCHAR => {
-	id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+	id => 0x0106, result => "void", wparam => "TCHAR", lparam => ["", ""] },
     WM_SYSCOLORCHANGE => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x0015, result => "void", wparam => "void", lparam => "void" },
+    WM_SYSCOMMAND => {
+	id => 0x0112, result => "void", wparam => "UINT", lparam => "int" },
     WM_SYSDEADCHAR => {
-	id => 0, result => "void", wparam => "TCHAR", lparam => ["", ""] },
+	id => 0x0107, result => "void", wparam => "TCHAR", lparam => ["", ""] },
     WM_SYSKEYDOWN => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
+	id => 0x0104, result => "void", wparam => "UINT", lparam => ["", ""] },
     WM_SYSKEYUP => {
-	id => 0, result => "void", wparam => "UINT", lparam => ["", ""] },
-
+	id => 0x0105, result => "void", wparam => "UINT", lparam => ["", ""] },
+    WM_SYSTEMERROR => {
+	id => 0x0017, result => "", wparam => "", lparam => "" },
+    WM_SYSTIMER => {
+	id => 0x0118, result => "", wparam => "", lparam => "" },
+
+    WM_TCARD => {
+	id => 0x0052, result => "", wparam => "", lparam => "" },
+    WM_TESTING => {
+	id => 0x003a, result => "", wparam => "", lparam => "" },
     WM_TIMECHANGE => {
-	id => 0, result => "void", wparam => "void", lparam => "void" },
+	id => 0x001e, result => "void", wparam => "void", lparam => "void" },
+    WM_TIMER => {
+	id => 0x0113, result => "void", wparam => "UINT", lparam => "void" },
+
+    WM_UNDO => {
+	id => 0x0304, result => "void", wparam => "void", lparam => "void" },
+    WM_USER => {
+	id => 0x0400, result => "", wparam => "", lparam => "" },
+    WM_USERCHANGED => {
+	id => 0x0054, result => "", wparam => "", lparam => "" },
 
     WM_VKEYTOITEM => {
-	id => 0x002e, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+	id => 0x002e, result => "int", wparam => ["UINT", "int"], lparam => "HWND" },
     WM_VSCROLL => {
-	id => 0, result => "void", wparam => ["UINT", "int"], lparam => "HWND" },
+	id => 0x0115, result => "void", wparam => ["int", "int"], lparam => "HWND" },
+    WM_VSCROLLCLIPBOARD => {
+	id => 0x030a, result => "void", wparam => "HWND", lparam => ["", ""] },
 
     WM_WINDOWPOSCHANGING => {
-	id => 0, result => "BOOL", wparam => "void", lparam => "LPWINDOWPOS" },
+	id => 0x0046, result => "BOOL", wparam => "void", lparam => "LPWINDOWPOS" },
     WM_WINDOWPOSCHANGED => {
-	id => 0, result => "void", wparam => "void", lparam => "LPARAM" },
+	id => 0x0047, result => "void", wparam => "void", lparam => "const LPWINDOWPOS" },
     WM_WININICHANGE => { 
-	id => 0, result => "void", wparam => "void", lparam => "LPCTSTR" }
+	id => 0x001a, result => "void", wparam => "void", lparam => "LPCTSTR" }
 };
 
 ########################################################################
@@ -282,7 +543,7 @@ $message = {
 sub _get_kind {
     local $_ = shift;
 
-    if(!defined($_)) {
+    if(!$_) {
 	return undef;
     } elsif(/^(?:HBRUSH|HDC|HFONT|HMENU|HRGN|HWND)$/ || /\*$/ ||
 	    /^LP(?!ARAM)/)
@@ -339,10 +600,13 @@ sub get_message_lparam_kind {
 }
 
 ########################################################################
-# _parse_windowsx_h
+# _parse_file
+
+sub _parse_file {
+    my $file = shift;
+    my $found_preprocessor = shift;
+    my $found_comment = shift;
 
-sub _parse_windowsx_h {
-    my $file = "$wine_dir/include/windowsx.h";
     {
 	open(IN, "< $file");
 	local $/ = undef;
@@ -350,8 +614,65 @@ sub _parse_windowsx_h {
 	close(IN);
     }
 
+    my @lines = split(/\n/, $_);
+    my $max_line = scalar(@lines);
+
     my $parser = new c_parser($file);
 
+    $parser->set_found_preprocessor_callback($found_preprocessor);
+    $parser->set_found_comment_callback($found_comment);
+
+    my $found_line = sub {
+	my $line = shift;
+	local $_ = shift;
+
+	$output->progress("$file: line $line of $max_line");
+    };
+
+    $parser->set_found_line_callback($found_line);
+
+    my $line = 1;
+    my $column = 0;
+
+    my $old_prefix = $output->prefix;
+    $output->progress("$file");
+    $output->prefix("$file: ");
+
+    if(!$parser->parse_c_file(\$_, \$line, \$column)) {
+	$output->write("can't parse file\n");
+    }
+
+    $output->prefix($old_prefix);
+}
+
+########################################################################
+# _get_tuple_arguments
+
+sub _get_tuple_arguments {
+    local $_ = shift;
+
+    my $parser = new c_parser;
+
+    my $line = 1;
+    my $column = 0;
+
+    my @arguments;
+    my @argument_lines;
+    my @argument_columns;
+    if(!$parser->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+	return undef;
+    }
+
+    return @arguments;
+}
+
+########################################################################
+# _parse_windowsx_h
+
+
+sub _parse_windowsx_h {
+    my $last_comment;
+
     my $found_preprocessor = sub {
 	my $begin_line = shift;
 	my $begin_column = shift;
@@ -361,85 +682,210 @@ sub _parse_windowsx_h {
 	    return 1;
 	}
 	
-	my $msg;
+	my $name;
 	if(s/^FORWARD_(\w+)\([^\)]*\)\s*(.*?)\s*$/$2/s) {
-	    $msg = $1;
+	    $name = $1;
 	}
 
-	if($msg eq "WM_SYSTEMERROR") {
+	if($name eq "WM_SYSTEMERROR") {
 	    return 1;
 	}
 
-	my $return_type;
-	if(s/^\(\s*(\w+)\s*\)(?:\(\s*\w+\s*\))*\(\s*\w+\s*\)\(\s*(?:hwnd|\(hwnd\))\s*,\s*(.*?)\s*\)$/$2/) {
-	    $return_type = $1;
+	my $result;
+	if(s/^\(\s*(\w+)\s*\)(?:\(\s*\w+\s*\))*\(\s*\w+\s*\)//) {
+	    $result = $1;
 	} else {
-	    die "$msg: '$_'";
+	    die "$name: '$_'";
 	}
-	
-	my @msgs = ();
-	if(s/^$msg\s*,\s*//) {
-	    @msgs = $msg;
-	} elsif(s/^\(\w+\)\s*\?\s*(\w+)\s*:\s*(\w+)\s*,\s*//s) {
-	    @msgs = ($1, $2);
+
+	(undef, $_, my $wparam, my $lparam) = _get_tuple_arguments($_);
+
+	my @names = ();
+	if(/^$name$/) {
+	    @names = $name;
+	} elsif(/^\(\w+\)\s*\?\s*(\w+)\s*:\s*(\w+)$/) {
+	    @names = ($1, $2);
 	} else {
-	    die "$msg: '$_'";
+	    die "$name: '$_'";
 	}
-	
-	my $wparam;
-	if(s/^\(WPARAM\)(?:\(\s*(\w+)\s*\))*\((.*?)\)\s*,\s*//) {
-	    if(defined($1)) {
-		$wparam = $1;
-	    } else {
-		$wparam = "WPARAM";
+
+	local $_ = $last_comment;
+	s%^/\*\s*(.*?)\s*\*/$%$1%;
+
+	my %arguments;
+	if(s/^(\w+)\s+\w+\s*\(\s*(.*?)\s*\)$/$2/) {
+	    my $result2 = $1;
+	    if($result2 eq "INT") { $result2 = "int"; }
+	    if($result ne $result2) {
+		$output->write("message $name: result type mismatch '$result' != '$result2'\n");
+	    }
+	    foreach (split(/\s*,\s*/)) {
+		if(/^((?:const\s+)?\w+(?:\s*\*\s*|\s+)?)(\w+)$/) {
+		    my $type = $1;
+		    my $name = $2;
+
+		    $type =~ s/^\s*(.*?)\s*$/$1/;
+
+		    $arguments{$name} = $type;
+		} else {
+		    die "$name: '$_'";
+		}
 	    }
-	} elsif(s/^MAKEWPARAM\(\s*(.*?)\s*,\s*(.*?)\s*\)\s*,\s*//) {
-	    $wparam = "(,)"; # "($1, $2)";
-	} elsif(s/^\((.*?)\)$//) {
-	    $wparam = "WPARAM";
-	} elsif(s/^0L\s*,\s*//) {
-	    $wparam = "void";
+	    # $output->write("$1: $_\n");    
 	} else {
-	    die "$msg: '$_'";
-	} 
+	    die "$name: '$_'";
+	}
 
-	my $lparam;
-	if(s/^\(LPARAM\)(?:\(\s*(\w+)\s*\))*\((.*?)\)$//) {
-	    if(defined($1)) {
-		$lparam = $1;
+	my $find_inner_cast = sub {
+	    local $_ = shift;
+	    if(/^(?:\(\s*((?:const\s+)?\w+(?:\s*\*)?)\s*\))*\(.*?\)$/) {
+		if(defined($1)) {
+		    return $1;
+		} else {
+		    return "";
+		}
+	    }
+	    
+	};
+
+	my @entries = (
+	    [ \$wparam, "W", "w" ],
+	    [ \$lparam, "L", "l" ]
+	);
+	foreach my $entry (@entries) {
+	    (my $refparam, my $upper, my $lower) = @$entry;
+
+	    local $_ = $$refparam;
+	    if(s/^\(\s*$upper(?:)PARAM\s*\)\s*(?:\(\s*((?:const\s+)?\w+(?:\s*\*)?)\s*\))*\(\s*(.*?)\s*\)$/$2/) {
+		if(defined($1)) {
+		    $$refparam = $1;
+		} else {
+		    $$refparam = "";
+		}
+
+		if(/^\w+$/) {
+		    if(exists($arguments{$_})) {
+			$$refparam = $arguments{$_};
+		    }
+		} elsif(/^\(\s*(\w+)\s*\)\s*\?\s*\(\s*(\w+)\s*\)\s*:\s*(?:\(\s*(\w+)\s*\)|0)$/) {
+		    foreach ($1, $2, $3) {
+			if(exists($arguments{$_})) {
+			    $$refparam = $arguments{$_};
+			    last;
+			}
+		    }
+		} elsif(/^\(\((?:const\s+)?\w+\s*(?:\*\s*)?\)\s*(?:\(\s*\w+\s*\)|\w+)\s*\)\s*\->\s*\w+$/) {
+		    $$refparam = "UINT";
+		} else {
+		    die "$name: '$_'";
+		}
+	    } elsif(s/^(?:\(\s*$upper(?:)PARAM\s*\)\s*)?MAKE$upper(?:)PARAM\s*//) {
+                (my $low, my $high) = _get_tuple_arguments($_);
+
+		$low = &$find_inner_cast($low);
+		$high = &$find_inner_cast($high);
+
+		$$refparam = "($low,$high)";
+	    } elsif(s/^\(.*?$lower(?:)Param.*?\)$//) {
+		$$refparam = $upper . "PARAM";
+	    } elsif(s/^\(\s*(.*?)\s*\)$//) {
+		$$refparam = "$1";
+	    } elsif(s/^0L$//) {
+		$$refparam = "void";
 	    } else {
-		$lparam = "LPARAM";
+		die "$name: '$_'";
+            }
+        } 
+
+	# $output->write("$result: '@names', '$wparam', '$lparam'\n");
+
+        foreach my $name (@names) {
+	    my $result2 = $$message{$name}{result};
+            my $wparam2 = $$message{$name}{wparam};
+	    my $lparam2 = $$message{$name}{lparam};
+
+	    if(ref($wparam2)) {
+		$wparam2 = "(" . join(",", @$wparam2) . ")";
+	    }
+
+	    if(ref($lparam2)) {
+		$lparam2 = "(" . join(",", @$lparam2) . ")";
+	    }
+
+	    if($result ne $result2) {
+		$output->write("message $name: wrong result type '$result2' should be '$result'\n");
 	    }
-	} elsif(s/^MAKELPARAM\(\s*(.*?)\s*,\s*(.*?)\s*\)$//) {
-	    $lparam = "(,)"; # "($1, $2)";
-	} elsif(s/^\((.*?)\)$//) {
-	    $lparam = "LPARAM";
-	} elsif(s/^0L$//) {
-	    $lparam = "void";
-	} else {
-	    die "$msg: '$_'";
-	} 
 
-	foreach my $msg (@msgs) {
-	    $output->write("$msg => { result => \"$return_type\", wparam => \"$wparam\", lparam => \"$lparam\" },\n");
+	    if($wparam ne $wparam2) {
+		# if($wparam ne "WPARAM" && $wparam ne "(,)") {
+		    $output->write("message $name: wrong wparam type '$wparam2' should be '$wparam'\n");
+		# }
+	    }
+
+	    if($lparam ne $lparam2) {
+		# if($lparam ne "LPARAM" && $lparam ne "(,)") {
+		    $output->write("message $name: wrong lparam type '$lparam2' should be '$lparam'\n");
+		# }
+	    }
 	}
 
 	return 1;
     };
 
-    $parser->set_found_preprocessor_callback($found_preprocessor);
+    my $found_comment = sub {
+	my $begin_line = shift;
+	my $begin_column = shift;
+	my $comment = shift;
 
-    my $line = 1;
-    my $column = 0;
+	$last_comment = $comment;
 
-    my $old_prefix = $output->prefix;
-    $output->progress("$file");
-    $output->prefix("$file: ");
+	return 1;
+    };
 
-    if(!$parser->parse_c_file(\$_, \$line, \$column)) {
-	$output->write("can't parse file\n");
-    }
+    _parse_file("$wine_dir/include/windowsx.h", $found_preprocessor, $found_comment);
+}
 
-    $output->prefix($old_prefix);
+
+########################################################################
+# _parse_winuser_h
+
+sub _parse_winuser_h {
+    my %not_found = ();
+
+    my $found_preprocessor = sub {
+	my $begin_line = shift;
+	my $begin_column = shift;
+	local $_ = shift;
+
+	if(/^\#\s*define\s+(WM_\w+)\s+(0x[0-9a-fA-F]+)\s*$/) {
+	    my $name = $1;
+	    my $id = lc($2);
+	    	
+	    if(exists($$message{$name})) {
+		my $id2 = sprintf("0x%04x", $$message{$name}{id});
+		if($id ne $id2) {
+		    $output->write("message $name: wrong value ($id2) should be $id\n");
+		}
+	    } else {
+		$output->write("message $name: exists but is not supported\n");
+		$not_found{$name} = $id;
+	    }
+	}
+
+	return 1;
+    };
+
+    _parse_file("$wine_dir/include/winuser.h", $found_preprocessor);
+
+    foreach my $name (sort(keys(%not_found))) {
+	my $id = $not_found{$name};
+
+	print "    $name => {\n";
+	print "\tid => $id, result => \"\", wparam => \"\", lparam => \"\" },\n";
+    }
 }
 
+# _parse_windowsx_h;
+# _parse_winuser_h;
+
+1;
diff --git a/tools/winapi_check/win16/winsock.api b/tools/winapi_check/win16/winsock.api
index 436577f3886abd06eed426c6cf2a0ef85b24607f..1fa77a0d68d3d65f1d285c28107acab5209b258e 100644
--- a/tools/winapi_check/win16/winsock.api
+++ b/tools/winapi_check/win16/winsock.api
@@ -11,7 +11,7 @@ u_long
 %ptr
 
 INT16 *
-LPWSADATA
+LPWSADATA16
 ULONG *
 char *
 struct sockaddr *
diff --git a/tools/winapi_check/win32/quartz.api b/tools/winapi_check/win32/quartz.api
index c9b87919974abd123a5f05b02b350d0a6fd4496a..555b0339011b29df685f01b568f5b8ef377e61e0 100644
--- a/tools/winapi_check/win32/quartz.api
+++ b/tools/winapi_check/win32/quartz.api
@@ -1,5 +1,6 @@
 %long
 
+DWORD
 HRESULT
 
 %ptr
@@ -7,3 +8,11 @@ HRESULT
 CLSID *
 IID *
 void **
+
+%str
+
+LPSTR
+
+%wstr
+
+LPWSTR
diff --git a/tools/winapi_check/win32/rpcrt4.api b/tools/winapi_check/win32/rpcrt4.api
index 57223adb7b8a31c5eb3bf4ddf8574434fa89404d..0acc8bc308cb3592906364092f128665296a7260 100644
--- a/tools/winapi_check/win32/rpcrt4.api
+++ b/tools/winapi_check/win32/rpcrt4.api
@@ -18,8 +18,10 @@ RPC_AUTH_KEY_RETRIEVAL_FN
 RPC_BINDING_HANDLE *
 RPC_IF_CALLBACK_FN *
 RPC_MGR_EPV *
+RPC_STATUS *
 UUID *
 unsigned char **
+unsigned short
 void **
 
 %str
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
index 16b6102635d7b6392a5a3bebcc3136c18d2e42fe..24ce8392045fcaac0418ee47d6e0419ea6e18736 100755
--- a/tools/winapi_check/winapi_check
+++ b/tools/winapi_check/winapi_check
@@ -169,7 +169,9 @@ if($options->headers) {
 		} elsif($options->headers_duplicated) {
 		    my $file = $previous_function->file;
 		    my $function_line = $previous_function->function_line;
-		    $output->write("duplicate declaration (first declaration at $file:$function_line)\n");
+		    if($file =~ /\.h$/) {
+			$output->write("duplicate declaration (first declaration at $file:$function_line)\n");
+		    }
 		}
 	    }
 	    $output->prefix("");