From f93f998e8c5caed4dcc4784d4f864a6cc82ea9fd Mon Sep 17 00:00:00 2001 From: Patrik Stridvall Date: Thu, 11 May 2000 21:46:17 +0000 Subject: [PATCH] - Check for missing modules in modules.dat. - New options --debug-messages for debug message checking (turned off by default) - Do not discard the argument name (use in debug message checking) - Improved parsing - Minor bug fixes --- tools/winapi_check/modules.dat | 4 ++ tools/winapi_check/win16/ole2disp.api | 5 +- tools/winapi_check/win32/advapi32.api | 2 +- tools/winapi_check/win32/crtdll.api | 4 +- tools/winapi_check/win32/imagehlp.api | 2 +- tools/winapi_check/win32/kernel32.api | 4 +- tools/winapi_check/win32/ntdll.api | 4 +- tools/winapi_check/win32/oleaut32.api | 2 +- tools/winapi_check/win32/riched32.api | 7 +++ tools/winapi_check/winapi.pm | 71 ++++++++++++++++++++++++++ tools/winapi_check/winapi_check | 41 +++++++-------- tools/winapi_check/winapi_function.pm | 19 +++++-- tools/winapi_check/winapi_local.pm | 72 +++++++++++++++++++++++++++ tools/winapi_check/winapi_options.pm | 4 +- tools/winapi_check/winapi_parser.pm | 51 +++++++++++++------ 15 files changed, 240 insertions(+), 52 deletions(-) create mode 100644 tools/winapi_check/win32/riched32.api diff --git a/tools/winapi_check/modules.dat b/tools/winapi_check/modules.dat index 5a484481fe4..aedb6b7b0d9 100644 --- a/tools/winapi_check/modules.dat +++ b/tools/winapi_check/modules.dat @@ -145,6 +145,10 @@ files dlls/ole32 +% dlls/ole32/ole2nls.spec + +dlls/ole32 + % dlls/ole32/ole32.spec dlls/ole32 diff --git a/tools/winapi_check/win16/ole2disp.api b/tools/winapi_check/win16/ole2disp.api index 432931b60c7..35454574eba 100644 --- a/tools/winapi_check/win16/ole2disp.api +++ b/tools/winapi_check/win16/ole2disp.api @@ -7,7 +7,6 @@ LCID %long # --forbidden int -unsigned %ptr @@ -19,6 +18,10 @@ IUnknown * REFCLSID char * +%ptr # --forbidden + +unsigned long * + %segstr BSTR16 diff --git a/tools/winapi_check/win32/advapi32.api b/tools/winapi_check/win32/advapi32.api index b1e1a48619d..7103cbfdc32 100644 --- a/tools/winapi_check/win32/advapi32.api +++ b/tools/winapi_check/win32/advapi32.api @@ -9,7 +9,6 @@ HCRYPTKEY HKEY LONG NTSTATUS -PHANDLE POLICY_INFORMATION_CLASS REGSAM SC_HANDLE @@ -50,6 +49,7 @@ PACL PACL * PDWORD PGENERIC_MAPPING +PHANDLE PLSA_HANDLE PLSA_OBJECT_ATTRIBUTES PLSA_REFERENCED_DOMAIN_LIST * diff --git a/tools/winapi_check/win32/crtdll.api b/tools/winapi_check/win32/crtdll.api index 1adaaeb9874..6252013a00a 100644 --- a/tools/winapi_check/win32/crtdll.api +++ b/tools/winapi_check/win32/crtdll.api @@ -16,7 +16,8 @@ time_t int long -unsigned +unsigned int +unsigned long %ptr @@ -44,6 +45,7 @@ struct find_t * struct stat * struct win_stat * time_t * +unsigned char * va_list void * diff --git a/tools/winapi_check/win32/imagehlp.api b/tools/winapi_check/win32/imagehlp.api index e58ba51cc99..304990df42d 100644 --- a/tools/winapi_check/win32/imagehlp.api +++ b/tools/winapi_check/win32/imagehlp.api @@ -2,7 +2,6 @@ BOOL BOOLEAN -DIGEST_HANDLE DWORD HANDLE HMODULE @@ -13,6 +12,7 @@ WORD %ptr DIGEST_FUNCTION +DIGEST_HANDLE LPDWORD LPSYSTEMTIME LPVOID diff --git a/tools/winapi_check/win32/kernel32.api b/tools/winapi_check/win32/kernel32.api index 71d842c35a7..5b501f16617 100644 --- a/tools/winapi_check/win32/kernel32.api +++ b/tools/winapi_check/win32/kernel32.api @@ -20,7 +20,6 @@ INT LANGID LCID LONG -PHANDLE UINT WCHAR WORD @@ -121,12 +120,13 @@ OFSTRUCT * OSVERSIONINFOA * OSVERSIONINFOW * PAPCFUNC +PDWORD PEXCEPTION_POINTERS +PHANDLE PLARGE_INTEGER PLONG PTIMERAPCROUTINE PULARGE_INTEGER -PDWORD PVOID PVOID * SECURITY_ATTRIBUTES * diff --git a/tools/winapi_check/win32/ntdll.api b/tools/winapi_check/win32/ntdll.api index 67fdc9e00bc..e81dea6ff42 100644 --- a/tools/winapi_check/win32/ntdll.api +++ b/tools/winapi_check/win32/ntdll.api @@ -15,7 +15,6 @@ KEY_VALUE_INFORMATION_CLASS LONG NTSTATUS OBJECT_INFORMATION_CLASS -PHANDLE PROCESSINFOCLASS SECTION_INHERIT SECURITY_IMPERSONATION_LEVEL @@ -32,7 +31,7 @@ WCHAR %long # --forbidden int -unsigned +unsigned int %longlong @@ -65,6 +64,7 @@ PDWORD PEXCEPTION_FRAME PEXCEPTION_RECORD PGENERIC_MAPPING +PHANDLE PIMAGE_NT_HEADERS PIO_APC_ROUTINE PIO_STATUS_BLOCK diff --git a/tools/winapi_check/win32/oleaut32.api b/tools/winapi_check/win32/oleaut32.api index c40efc3a436..7a0b5e14dd2 100644 --- a/tools/winapi_check/win32/oleaut32.api +++ b/tools/winapi_check/win32/oleaut32.api @@ -34,7 +34,7 @@ WORD int short -unsigned +unsigned int %ptr diff --git a/tools/winapi_check/win32/riched32.api b/tools/winapi_check/win32/riched32.api new file mode 100644 index 00000000000..96f362918a6 --- /dev/null +++ b/tools/winapi_check/win32/riched32.api @@ -0,0 +1,7 @@ +%long + +HRESULT + +%ptr + +DLLVERSIONINFO * diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm index 18c468efe91..79575c769b5 100644 --- a/tools/winapi_check/winapi.pm +++ b/tools/winapi_check/winapi.pm @@ -41,11 +41,13 @@ sub parse_api_file { my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}}; my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}}; my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}}; + my $type_format = \%{$self->{TYPE_FORMAT}}; my $file = shift; my $module = shift; my $kind; + my $format; my $extension = 0; my $forbidden = 0; @@ -62,6 +64,7 @@ sub parse_api_file { if(s/^%(\S+)\s*//) { $kind = $1; + $format = undef; $forbidden = 0; $extension = 0; @@ -70,6 +73,36 @@ sub parse_api_file { $forbidden = 1; } elsif(/^--extension/) { $extension = 1; + } elsif(/^--format=(\".*?\"|\S*)/) { + $format = $1; + $format =~ s/^\"(.*?)\"$/$1/; + } + + if(!defined($format)) { + if($kind eq "long") { + $format = "%d|%u|%x|%X|"; + $format .= "%hd|%hu|%hx|%hX|"; + $format .= "%ld|%lu|%lx|%lX|"; + $format .= "%04x|%04X|0x%04x|0x%04X|"; + $format .= "%08x|%08X|0x%08x|0x%08X|"; + $format .= "%08lx|%08lX|0x%08lx|0x%08lX"; + } elsif($kind eq "longlong") { + $format = "%lld"; + } elsif($kind eq "ptr") { + $format = "%p"; + } elsif($kind eq "segptr") { + $format = "%p"; + } elsif($kind eq "str") { + $format = "%p|%s"; + } elsif($kind eq "wstr") { + $format = "%p|%s"; + } elsif($kind eq "word") { + $format = "%d|%u|%x|%X|"; + $format .= "%hd|%hu|%hx|%hX|"; + $format .= "%04x|%04X|0x%04x|0x%04X"; + } else { + $format = ""; + } } } elsif(defined($kind)) { my $type = $_; @@ -94,6 +127,8 @@ sub parse_api_file { } else { $$translate_argument{$type} = $kind; } + + $$type_format{$module}{$type} = $format; } else { $$output->write("$file: file must begin with % statement\n"); exit 1; @@ -437,6 +472,42 @@ sub type_found { return $$type_found{$name}; } +sub is_allowed_type_format { + my $self = shift; + my $type_format = \%{$self->{TYPE_FORMAT}}; + + my $module = shift; + my $type = shift; + my $format = shift; + + my $formats; + + if(defined($module) && defined($type)) { + local $_; + foreach (split(/ & /, $module)) { + if(defined($formats)) { + $formats .= "|"; + } else { + $formats = ""; + } + if(defined($$type_format{$_}{$type})) { + $formats .= $$type_format{$_}{$type}; + } + } + } + + if(defined($formats)) { + local $_; + foreach (split(/\|/, $formats)) { + if($_ eq $format) { + return 1; + } + } + } + + return 0; +} + sub all_modules { my $self = shift; my $modules = \%{$self->{MODULES}}; diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check index 389b78ad9c5..21c7f92532a 100755 --- a/tools/winapi_check/winapi_check +++ b/tools/winapi_check/winapi_check @@ -222,14 +222,16 @@ foreach my $file ($options->c_files) { my $calling_convention = shift; my $internal_name = shift; my $external_name = $internal_name; - my $refarguments = shift; - my @arguments = @$refarguments; + my $refargument_types = shift; + my @argument_types = @$refargument_types; + my $refargument_names = shift; + my @argument_names = @$refargument_names; my $statements = shift; if($options->global) { $win16api->found_type($return_type) if $options->win16; $win32api->found_type($return_type) if $options->win32; - for my $argument (@arguments) { + for my $argument (@argument_types) { $win16api->found_type($argument) if $options->win16; $win32api->found_type($argument) if $options->win32; } @@ -285,7 +287,8 @@ foreach my $file ($options->c_files) { $function->calling_convention($calling_convention); $function->external_name($external_name); $function->internal_name($internal_name); - $function->arguments([@arguments]); + $function->argument_types([@argument_types]); + $function->argument_names([@argument_names]); $function->statements($statements); $function->module16($module16); $function->module32($module32); @@ -296,7 +299,7 @@ foreach my $file ($options->c_files) { my $msg = shift; $output->write("$file: $module: $return_type "); $output->write("$calling_convention ") if $calling_convention; - $output->write("$internal_name(" . join(",", @arguments) . "): $msg\n"); + $output->write("$internal_name(" . join(",", @argument_types) . "): $msg\n"); } }; my $output16 = &$output_module($module16); @@ -348,31 +351,21 @@ foreach my $file ($options->c_files) { 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, [@arguments], $win16api; + $return_type, $calling_convention, $external_name, $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, [@arguments], $win32api; + $return_type, $calling_convention, $external_name, $internal_name, [@argument_types], $win32api; } } - if($options->local && $options->cross_call) { - local $_ = $statements; - my $called_function_names = {}; - while(defined($_)) { - if(/(\w+)\((.*?)\)/) { - $_ = $'; - my $called_name = $1; - if($called_name !~ /^if|for|while|switch|sizeof$/) { - $functions{$internal_name}->function_called($called_name); - if(!defined($functions{$called_name})) { - $functions{$called_name} = 'winapi_function'->new; - } - $functions{$called_name}->function_called_by($internal_name); - } - } else { - undef $_ - } + if($options->local && $options->statements) { + if($options->win16 && $options->report_module($module16)) { + winapi_local::check_statements $options, $output16, $win16api, \%functions, $function; + } + + if($options->win32 && $options->report_module($module32)) { + winapi_local::check_statements $options, $output32, $win32api, \%functions, $function; } } diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm index d70cf9c1829..fa166ca86d9 100644 --- a/tools/winapi_check/winapi_function.pm +++ b/tools/winapi_check/winapi_function.pm @@ -88,15 +88,26 @@ sub internal_name { return $$internal_name; } -sub arguments { +sub argument_types { my $self = shift; - my $arguments = \${$self->{ARGUMENTS}}; + my $argument_types = \${$self->{ARGUMENT_TYPES}}; local $_ = shift; - if(defined($_)) { $$arguments = $_; } + if(defined($_)) { $$argument_types = $_; } - return $$arguments; + return $$argument_types; +} + +sub argument_names { + my $self = shift; + my $argument_names = \${$self->{ARGUMENT_NAMES}}; + + local $_ = shift; + + if(defined($_)) { $$argument_names = $_; } + + return $$argument_names; } sub module16 { diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm index fc1fabb9478..576c5722f09 100644 --- a/tools/winapi_check/winapi_local.pm +++ b/tools/winapi_check/winapi_local.pm @@ -173,6 +173,78 @@ sub check_function { } } +sub check_statements { + my $options = shift; + my $output = shift; + my $winapi = shift; + my $functions = shift; + my $function = shift; + + my $module = $function->module; + my $internal_name = $function->internal_name; + + my $first_debug_message = 1; + local $_ = $function->statements; + while(defined($_)) { + if(s/(\w+)\s*(?:\(\s*(\w+)\s*\))?\s*\(\s*((?:\"[^\"]*\"|\([^\)]*\)|[^\)])*?)\s*\)//) { + my $called_name = $1; + my $channel = $2; + my $called_arguments = $3; + if($called_name =~ /^if|for|while|switch|sizeof$/) { + # Nothing + } elsif($called_name =~ /^ERR|FIXME|MSG|TRACE|WARN$/) { + if($first_debug_message && $called_name =~ /^FIXME|TRACE$/) { + $first_debug_message = 0; + if($called_arguments =~ /^\"\((.*?)\)(.*?)\"\s*,\s*(.*?)$/) { + my $formating = $1; + my $extra = $2; + my $arguments = $3; + + my $format; + my $argument; + my $n = 0; + while($formating && ($formating =~ s/^([^,]*),?//, $format = $1, $format =~ s/^\s*(.*?)\s*$/$1/) && + $arguments && ($arguments =~ s/^([^,]*),?//, $argument = $1, $argument =~ s/^\s*(.*?)\s*$/$1/)) + { + my $type = @{$function->argument_types}[$n]; + my $name = @{$function->argument_names}[$n]; + + $n++; + + if(!defined($type)) { last; } + + $format =~ s/^\w+\s*[:=]?\s*//; + $format =~ s/\s*\{[^\{\}]*\}$//; + $format =~ s/\s*\[[^\[\]]*\]$//; + $format =~ s/^\'(.*?)\'$/$1/; + $format =~ s/^\\\"(.*?)\\\"$/$1/; + + if($argument !~ /$name/) { + &$output("$called_name: argument $n is wrong ($name != '$argument')"); + } elsif(!$winapi->is_allowed_type_format($module, $type, $format)) { + &$output("$called_name: argument $n ($type $name) has illegal format ($format)"); + } + } + + my $count = $#{$function->argument_types} + 1; + if($n != $count) { + &$output("$called_name: argument count mismatch ($n != $count)"); + } + } + } + } else { + $$functions{$internal_name}->function_called($called_name); + if(!defined($$functions{$called_name})) { + $$functions{$called_name} = 'winapi_function'->new; + } + $$functions{$called_name}->function_called_by($internal_name); + } + } else { + undef $_; + } + } +} + sub check_file { my $options = shift; my $output = shift; diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm index a66713f3f9d..90f7e2d4a35 100644 --- a/tools/winapi_check/winapi_options.pm +++ b/tools/winapi_check/winapi_options.pm @@ -60,13 +60,15 @@ my %options = ( }, "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" }, "misplaced" => { default => 1, parent => "local", description => "check for misplaced functions" }, - "cross-call" => { default => 0, parent => "local", description => "check for cross calling 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-win32-win16" => { default => 0, parent => "cross-call", description => "check for cross calls between win32 and win16" }, "cross-call-unicode-ascii" => { default => 0, parent => "cross-call", description => "check for cross calls between Unicode and ASCII" }, + "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" }, diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm index cfe246d2b94..558d06904f6 100644 --- a/tools/winapi_check/winapi_parser.pm +++ b/tools/winapi_check/winapi_parser.pm @@ -14,7 +14,8 @@ sub parse_c_file { my $return_type; my $calling_convention; my $function = ""; - my $arguments; + my $argument_types; + my $argument_names; my $statements; my $function_begin = sub { @@ -23,13 +24,20 @@ sub parse_c_file { $return_type= shift; $calling_convention = shift; $function = shift; - $arguments = shift; + $argument_types = shift; + $argument_names = shift; + + if($#$argument_names == -1) { + foreach my $n (0..$#$argument_types) { + push @$argument_names, ""; + } + } $statements = ""; }; my $function_end = sub { - &$function_found_callback($documentation,$linkage,$return_type,$calling_convention,$function,$arguments,$statements); - + &$function_found_callback($documentation,$linkage,$return_type,$calling_convention, + $function,$argument_types,$argument_names,$statements); $function = ""; }; @@ -214,33 +222,48 @@ sub parse_c_file { $arguments =~ s/^\s*(.*?)\s*$/$1/; if($arguments eq "") { $arguments = "void" } + my @argument_types; + my @argument_names; my @arguments = split(/,/, $arguments); foreach my $n (0..$#arguments) { + my $argument_type = ""; + my $argument_name = ""; my $argument = $arguments[$n]; $argument =~ s/^\s*(.*?)\s*$/$1/; - #print " " . ($n + 1) . ": '$argument'\n"; + # print " " . ($n + 1) . ": '$argument'\n"; $argument =~ s/^(IN OUT(?=\s)|IN(?=\s)|OUT(?=\s)|\s*)\s*//; $argument =~ s/^(const(?=\s)|CONST(?=\s)|\s*)\s*//; if($argument =~ /^\.\.\.$/) { - $argument = "..."; - } elsif($argument =~ /^((struct\s+|union\s+|enum\s+)?\w+)\s*((\*\s*?)*)\s*/) { - $argument = "$1"; - if($3 ne "") { - $argument .= " $3"; + $argument_type = "..."; + $argument_name = "..."; + } elsif($argument =~ /^((?:struct\s+|union\s+|enum\s+|(?:signed\s+|unsigned\s+)(?:short\s+(?=int)|long\s+(?=int))?)?\w+)\s*((?:const)?\s*(?:\*\s*?)*)\s*(?:WINE_UNUSED\s+)?(\w*)\s*(?:\[\]|\s+OPTIONAL)?/) { + $argument_type = "$1"; + if($2 ne "") { + $argument_type .= " $2"; } + $argument_name = $3; + + $argument_type =~ s/\s*const\s*/ /; + $argument_type =~ s/^\s*(.*?)\s*$/$1/; + + $argument_name =~ s/^\s*(.*?)\s*$/$1/; } else { die "$file: $.: syntax error: '$argument'\n"; } - $arguments[$n] = $argument; - #print " " . ($n + 1) . ": '" . $arguments[$n] . "'\n"; + $argument_types[$n] = $argument_type; + $argument_names[$n] = $argument_name; + # print " " . ($n + 1) . ": '" . $argument_types[$n] . "', '" . $argument_names[$n] . "'\n"; + } + if($#argument_types == 0 && $argument_types[0] =~ /^void$/i) { + $#argument_types = -1; + $#argument_names = -1; } - if($#arguments == 0 && $arguments[0] =~ /^void$/i) { $#arguments = -1; } if($options->debug) { print "$file: $return_type $calling_convention $name(" . join(",", @arguments) . ")\n"; } - &$function_begin($documentation,$linkage,$return_type,$calling_convention,$name,\@arguments); + &$function_begin($documentation,$linkage,$return_type,$calling_convention,$name,\@argument_types,\@argument_names); if($level == 0) { &$function_end; }