[PATCH] [WinApi]: added a tool for server's protocol analysis

Eric Pouech eric.pouech at wanadoo.fr
Sat Mar 25 03:49:06 CST 2006


- added winapi_server to monitor usage of server's call
  across modules

A+
---

 tools/winapi/server.api    |  213 +++++++++++++++++++++++++++++++++++
 tools/winapi/winapi_server |  268 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 481 insertions(+), 0 deletions(-)

diff --git a/tools/winapi/server.api b/tools/winapi/server.api
new file mode 100644
index 0000000..9a88e7b
--- /dev/null
+++ b/tools/winapi/server.api
@@ -0,0 +1,213 @@
+new_process			ntdll				process
+get_new_process_info		ntdll				process
+new_thread			ntdll				process
+get_startup_info		ntdll				process
+init_process_done		ntdll				process
+init_thread			ntdll				process
+terminate_process		ntdll				process
+terminate_thread		ntdll				process
+get_process_info		ntdll				process
+set_process_info		ntdll				process
+get_thread_info			ntdll				process
+set_thread_info			ntdll				process
+get_dll_info			ntdll				dll
+suspend_thread			ntdll				process
+resume_thread			ntdll				process
+load_dll			ntdll				dll
+unload_dll			ntdll				dll
+queue_apc			ntdll				ipc
+get_apc				ntdll				ipc
+close_handle			ntdll				ipc
+set_handle_info			ntdll				handle
+dup_handle			ntdll				handle
+open_process			ntdll				process
+open_thread			ntdll				process
+select				ntdll				ipc
+create_event			ntdll				ipc
+event_op			ntdll				ipc
+open_event			ntdll				ipc
+create_mutex			ntdll				ipc
+release_mutex			ntdll				ipc
+open_mutex			ntdll				ipc
+create_semaphore		ntdll				ipc
+release_semaphore		ntdll				ipc
+open_semaphore			ntdll				ipc
+create_file			ntdll				file
+alloc_file_handle		ntdll				file
+get_handle_fd			ntdll				handle
+flush_file			ntdll				file
+lock_file			ntdll				file
+unlock_file			ntdll				file
+unmount_device			ntdll				file
+create_socket			ntdll				socket
+accept_socket			ntdll				socket
+set_socket_event		ntdll				socket
+get_socket_event		ntdll				socket
+enable_socket_event		ntdll				socket
+set_socket_deferred		ntdll				socket
+create_mapping			ntdll				process
+open_mapping			ntdll				process
+get_mapping_info		ntdll				process
+create_snapshot			ntdll				process
+next_process			ntdll				process
+next_thread			ntdll				process
+next_module			ntdll				process
+wait_debug_event		ntdll				debug
+queue_exception_event		ntdll				debug
+get_exception_status		ntdll				debug
+output_debug_string		ntdll				debug
+continue_debug_event		ntdll				debug
+debug_process			ntdll				debug
+debug_break			ntdll				debug
+set_debugger_kill_on_exit	ntdll				debug
+read_process_memory		ntdll				process
+write_process_memory		ntdll				process
+create_key			ntdll				registry
+open_key			ntdll				registry
+delete_key			ntdll				registry
+flush_key			ntdll				registry
+enum_key			ntdll				registry
+set_key_value			ntdll				registry
+get_key_value			ntdll				registry
+enum_key_value			ntdll				registry
+delete_key_value		ntdll				registry
+load_registry			ntdll				registry
+unload_registry			ntdll				registry
+save_registry			ntdll				registry
+set_registry_notification	ntdll				registry
+create_timer			ntdll				misc
+open_timer			ntdll				misc
+set_timer			ntdll				misc
+cancel_timer			ntdll				misc
+get_timer_info			ntdll				misc
+get_thread_context		ntdll				process
+set_thread_context		ntdll				process
+get_selector_entry		ntdll				process
+add_atom			ntdll				misc
+delete_atom			ntdll				misc
+find_atom			ntdll				misc
+get_atom_information		ntdll				misc
+set_atom_information		ntdll				misc
+empty_atom_table		ntdll				misc
+init_atom_table			ntdll				misc
+get_serial_info			ntdll				serial
+set_serial_info			ntdll				serial
+register_async			ntdll				ipc
+cancel_async			ntdll				ipc
+create_named_pipe		ntdll				ipc
+open_named_pipe			ntdll				ipc
+connect_named_pipe		ntdll				ipc
+wait_named_pipe			ntdll				ipc
+disconnect_named_pipe		ntdll				ipc
+get_named_pipe_info		ntdll				ipc
+open_token			ntdll				token
+query_virtual_memory_info	ntdll				process
+adjust_token_privileges		ntdll				token
+get_token_privileges		ntdll				token
+check_token_privileges		ntdll				token
+duplicate_token			ntdll				token
+access_check			ntdll				token
+create_mailslot			ntdll				ipc
+open_mailslot			ntdll				ipc
+set_mailslot_info		ntdll				ipc
+get_token_user			ntdll				token
+set_handle_fd			ntdll				handle
+open_directory			ntdll				om
+create_directory		ntdll				om
+open_symlink			ntdll				om
+create_symlink			ntdll				om
+query_symlink			ntdll				om
+open_file_object		ntdll				om
+read_directory_changes		ntdll				file
+read_change			ntdll				file
+alloc_console			wineconsole			console
+free_console			kernel				console
+get_console_renderer_events	wineconsole			console
+open_console			kernel,wineconsole		console
+get_console_wait_event		kernel				console
+get_console_mode		kernel				console
+set_console_mode		kernel				console
+set_console_input_info		kernel,wineconsole		console
+get_console_input_info		kernel,wineconsole		console
+append_console_input_history	kernel				console
+get_console_input_history	kernel				console
+create_console_output		kernel,wineconsole		console
+set_console_output_info		kernel,wineconsole		console
+get_console_output_info		kernel,wineconsole		console
+write_console_input		kernel				console
+read_console_input		kernel				console
+write_console_output		kernel				console
+fill_console_output		kernel				console
+read_console_output		kernel,wineconsole		console
+move_console_output		kernel				console
+send_console_signal		kernel				console
+get_msg_queue			user				message
+set_queue_mask			user				message
+get_queue_status		user				message
+wait_input_idle			user				message
+send_message			user,x11drv			message
+get_message			user				message
+reply_message			user				message
+accept_hardware_message		user				message
+get_message_reply		user				message
+set_win_timer			user				message
+kill_win_timer			user				message
+create_window			user				window
+destroy_window			user				window
+set_window_owner		user				window
+get_window_info			user				window
+set_window_info			user				window
+set_parent			user,x11drv			window
+get_window_parents		user				window
+get_window_children		user				window
+get_window_children_from_point	user				window
+get_window_tree			user				window
+set_window_pos			x11drv				window
+get_window_rectangles		user				window
+get_window_text			user				window
+set_window_text			user				window
+get_windows_offset		user				window
+get_visible_region		x11drv				window
+get_window_region		user				window
+set_window_region		user				window
+get_update_region		user				window
+update_window_zorder		x11drv				window
+redraw_window			user				window
+set_window_property		user				window
+remove_window_property		user				window
+get_window_property		user				window
+get_window_properties		user				window
+create_winstation		user				window
+open_winstation			user				window
+close_winstation		user				window
+get_process_winstation		user				window
+set_process_winstation		user				window
+create_desktop			user				window
+open_desktop			user				window
+close_desktop			user				window
+get_thread_desktop		user				window
+set_thread_desktop		user				window
+set_user_object_info		user				window
+attach_thread_input		user				window
+get_thread_input		user				window
+get_last_input_time		user				window
+get_key_state			user				window
+set_key_state			user				window
+set_foreground_window		user				window
+set_focus_window		user				window
+set_active_window		user				window
+set_capture_window		user,x11drv			window
+set_caret_window		user				window
+set_caret_info			user				window
+set_hook			user				window
+remove_hook			user				window
+start_hook_chain		user				window
+finish_hook_chain		user				window
+get_next_hook			user				window
+create_class			user				window
+destroy_class			user				window
+set_class_info			user				window
+set_clipboard_info		user,x11drv			window
+set_global_windows		user				window
+get_desktop_window		user				window
+post_quit_message		user				window
diff --git a/tools/winapi/winapi_server b/tools/winapi/winapi_server
new file mode 100755
index 0000000..d8faba7
--- /dev/null
+++ b/tools/winapi/winapi_server
@@ -0,0 +1,268 @@
+#!/usr/bin/perl -w
+
+# Copyright 2005-2006 Eric Pouech
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+use strict;
+
+my @files;
+
+my $data_file = 'server.api';
+
+sub is_in_list()
+{
+	my ($list, $name) = @_;
+
+	return 0 if (!defined($list));
+	# FIXME: this test is not so right... we should check the ,
+	# as we only get ntdll kernel user x11drv winsock as DLL names
+	# it should be just fine
+	return index($list, $name) != -1;
+}
+
+sub file_in_cmd_dir()
+{
+	my ($file) = @_;
+	my $idx = rindex($0, '/');
+	return $file if ($idx == -1);
+	return substr($0, 0, $idx + 1) . $file;
+}
+
+# grabs the list of source files (actually *.c) in Wine source tree
+sub browse_tree()
+{
+	my ($dlldir) = @_;
+
+	opendir(DIR, $dlldir) || die "can't opendir $dlldir: $!";
+	foreach my $sdir (sort readdir(DIR))
+	{
+		my $dir = "$dlldir/$sdir";
+
+		next if (! -d $dir);
+		opendir(SDIR, $dir) || die "can't opendir $dir: $!";
+		foreach my $file (sort readdir(SDIR))
+		{
+			push @files, "$dir/$file" if ($file =~ /^.*\.c$/);
+		}
+		closedir(SDIR);
+	}
+	closedir(DIR);
+}
+
+# list, for each server call, in which DLL this server call is used
+sub calls_by_dlls()
+{
+	my %out;
+	foreach my $file (@files)
+	{
+		open F, "<$file" || die "can't open $file: $!";
+		my ($dlldir, $sdir, $lfile) = split /\//, $file;
+		while (<F>)
+		{
+			if ($_ =~ /SERVER_START_REQ[ \t]*\([ \t]*([^ ^\t]*)[ \t]*\)/g)
+			{
+				if (!&is_in_list($out{$1}, $sdir))
+				{
+					$out{$1} .= ',' if (defined $out{$1});
+					$out{$1} .= $sdir;
+				}
+			}
+		}
+		close F;
+	}
+	foreach my $k (sort keys %out)
+	{
+		printf("%-30s -> $out{$k}\n", $k);
+	}
+	return 1;
+}
+
+# parse and return a hash of allowed DLL per server call
+sub load_api_data()
+{
+	my ($file) = @_;
+	my %data;
+
+	open F, "<$file" || die "can't open $file: $!";
+	while (<F>)
+	{
+		if ($_ =~ /([_a-z]+)[ \t]+(.*)[ \t]+(.*)/)
+		{
+			$data{$1} = $2;
+		}
+		else
+		{
+			die "wrong line $_";
+		}
+	}
+	close F;
+	return %data;
+}
+
+# prints out the count of calls (NT form and Kernel form) from
+# the files stored in global @files
+sub split_by_dlls()
+{
+	my ($opt) = @_;
+	my $last_sdir = '';
+	my $mode = 0;
+	my $count1 = 0;
+	my $count2 = 0;
+
+	$mode = 1 if (defined($opt) && $opt eq '--wiki');
+
+	$mode == 0 && printf "Call Krn NT\n";
+	$mode == 1 && printf "||||||<tablewidth=\"33%%\">||\n||<:>Call||<:>Kernel||<:>NT||\n";
+
+	foreach my $file (@files)
+	{
+		open F, "<$file" || die "can't open $file: $!";
+		my ($dlldir, $sdir, $lfile) = split /\//, $file;
+
+		if ($last_sdir ne $sdir)
+		{
+			if ($count1 != 0)
+			{
+				$mode == 0 && printf "%3d: %-3d %-3d $last_sdir\n", $count1, $count2, $count1 - $count2;
+				$mode == 1 && printf "||<:>$count1||<:>$count2||<:>%d||<:>$last_sdir||\n", $count1 - $count2;
+				$count1 = $count2 = 0;
+			}
+			$last_sdir = $sdir;
+		}
+		while (<F>)
+		{
+			$count1++ if (index($_, 'wine_server_call') != -1 && index($_, "\"wine_server_call\"") == -1);
+			$count2++ if (index($_, 'wine_server_call_err') != -1 && index($_, "\"wine_server_call_err\"") == -1);
+		}
+		close F;
+	}
+	if ($count1 != 0)
+	{
+		$mode == 0 && printf "%3d: %-3d %-3d $last_sdir\n", $count1, $count2, $count1 - $count2;
+		$mode == 1 && printf "||<:>$count1||<:>$count2||<:>%d||<:>$last_sdir||\n", $count1 - $count2;
+	}
+	return 1;
+}
+
+# validates that all server calls are actually made in the allowed
+# DLL. Requires a server.api file with the allowed mappings
+sub validate()
+{
+	my ($api) = @_;
+	my %data = &load_api_data(&file_in_cmd_dir($api));
+	my %notused = &load_api_data(&file_in_cmd_dir($api));
+	my $nw = 0;
+	my %used;
+	my %bydll;
+	my %warned;
+
+	foreach my $file (@files)
+	{
+		my $line = 0;
+		open F, "<$file" || die "can't open $file: $!";
+		my ($dlldir, $sdir, $lfile) = split /\//, $file;
+		while (<F>)
+		{
+			$line++;
+			if ($_ =~ /SERVER_START_REQ[ \t]*\([ \t]*([^ ^\t]*)[ \t]*\)/g)
+			{
+				$used{$1} = 1;
+				if (defined($data{$1}))
+				{
+				 	if (!&is_in_list($data{$1}, $sdir))
+					{
+						printf("$sdir/$lfile:$line: warning: server-call `$1' is not allowed in module $sdir\n");
+						$bydll{$sdir}++;
+						$nw++;
+						$warned{$1}++;
+					}
+				}
+				else
+				{
+					printf("$sdir/$lfile:$line: warning: server-call `$1' is not included in API list\n");
+					$nw++;
+					$warned{$1}++;
+				}
+				$notused{$1} =~ s/$sdir//;
+			}
+		}
+		close F;
+	}
+	foreach my $i (sort keys %data)
+	{
+		if (!defined($used{$i}))
+		{
+			printf("warning: server-call `$i' is never used\n");
+			$nw++;
+			$warned{$i}++;
+		}	
+	}
+	foreach my $i (sort keys %notused)
+	{
+		if (defined($notused{$i}))
+		{
+			my $s = $notused{$i};
+			$s =~ s/[ \t]+//g;
+			if ($s ne '' && $s ne ',' && $s ne ',,' && !defined($warned{$i}))
+			{
+				printf("warning: dll '$s' remains for server call '$i'\n");
+				$nw++;
+			}
+		}
+	}
+	if ($nw != 0)
+	{
+		my $count = 0;
+		printf("$nw warnings (");
+		foreach my $i (keys %bydll)
+		{
+			printf(", ") if ($count++);
+			printf("%d in %s", $bydll{$i}, $i);
+		}
+		printf(")\n");
+	}
+	return 1;
+}
+
+sub usage()
+{
+	print
+"Usage: $0 [call|split|validate] [options]
+ + call:       list per server call the DLLs where this call is used
+ + split:      counts the number of calls per DLL
+               with --wiki option, use formatting for wiki inclusion
+ + validate:   checks whether a call is allowed in a given DLL
+               (information is gotten from $data_file file)\n";
+}
+
+sub check_cur_dir()
+{
+	if (! -f 'README' || ! -f 'VERSION' || ! -f 'DEVELOPERS-HINTS' ||
+		 ! -d 'dlls' || ! -d 'programs' || ! -d 'server')
+	{
+		print "$0 should be run from the top of Wine source tree\n";
+		exit;
+	}
+}
+
+&check_cur_dir();
+&usage() && exit if (!defined($ARGV[0]));
+&browse_tree('dlls');
+&browse_tree('programs');
+&calls_by_dlls() && exit if ($ARGV[0] eq 'call');
+&split_by_dlls($ARGV[1], $ARGV[2]) && exit if ($ARGV[0] eq 'split');
+&validate($data_file) && exit if ($ARGV[0] eq 'validate');
+&usage();





More information about the wine-patches mailing list