Made a new improved version of winapi-check in perl.

diff --git a/tools/winapi-check b/tools/winapi-check
deleted file mode 100755
index 346d3e2..0000000
--- a/tools/winapi-check
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-# This quick and dirty script prints the names of functions that don't have a
-# WINAPI in its header declaration or don't appear in any .c file at all.
-# I don't think it's very intelligent to use it when having < 64 MB ;)
-# FIXME: This script skips .spec function entries that occupy two or more
-# .spec lines !
-
-if [ ! -e ./ChangeLog ] ; then
-  echo You are not in Wine main directory !
-  exit
-fi
-echo crtdll.spec, ntdll.spec and wsock32.spec will be mentioned many times,
-echo as they use original UNIX functions that don\'t exist in Wine .c code.
-echo
-FIND_LIST="`find . -name "*.c"`"
-for i in if1632/*.spec relay32/*.spec
-do
-# skip wprocs.spec, as it contains many funcs that don't need a WINAPI
-  if [ $i = "if1632/wprocs.spec" ] ; then
-    continue
-  fi
-  LINE="`egrep "stdcall|cdecl|pascal|register" $i|grep -v "^#"|tr -d " "|tr "\n" " "`"
-  for j in $LINE
-  do
-    if [ -n "`echo "$j"|grep \)`" ] ; then
-      FUNC="`echo $j|cut -f2 -d\)|cut -f1 -d'#'`"
-      if [ -n "$FUNC" ] ; then
-        if [ -z "`grep -B 1 $FUNC $FIND_LIST|egrep "WINAPI|__cdecl|VFWAPI|DC_GET_VAL|DC_SET_MODE|REGS_ENTRYPOINT"`" ] ; then
-	  case $FUNC in		# "black list"
-	   "GetBrushOrgEx16" ) ;;
-	   "GetCurrentPositionEx16" ) ;;
-	   "GetViewportExtEx16" ) ;;
-	   "GetViewportOrgEx16" ) ;;
-	   "GetWindowExtEx16" ) ;;
-	   "GetWindowOrgEx16" ) ;;
-
-	   "GetBrushOrgEx32" ) ;;
-           "GetCurrentPositionEx32" ) ;;
-           "GetViewportExtEx32" ) ;;
-           "GetViewportOrgEx32" ) ;;
-           "GetWindowExtEx32" ) ;;
-           "GetWindowOrgEx32" ) ;;
-	   * ) echo "$i: $FUNC" ;;
-	  esac
-	fi
-      fi
-    fi 
-  done
-done
diff --git a/tools/winapi_check/nativeapi.dat b/tools/winapi_check/nativeapi.dat
new file mode 100644
index 0000000..8a3de0f
--- /dev/null
+++ b/tools/winapi_check/nativeapi.dat
@@ -0,0 +1,217 @@
+__ctype
+__divdi3
+__eprintf
+__fixunsdfdi
+__flsbuf
+__iob
+__moddi3
+_environ
+_exit
+_fxstat
+_lwp_create
+_lwp_exit
+_lwp_makecontext
+_lxstat
+_sysconf
+_xmknod
+_xstat
+abs
+access
+acos
+asctime
+asin
+atan
+atan2
+atexit
+atof
+atoi
+atol
+bsearch
+bzero
+calloc
+ceil
+cfgetospeed
+chmod
+close
+closedir
+cos
+cosh
+ctime
+div
+dup
+dup2
+environ
+errno
+execlp
+execvp
+exit
+exp
+fabs
+fclose
+fcntl
+fdopen
+feof
+fflush
+ffs
+fgetc
+fgetpos
+fgets
+floor
+fmod
+fopen
+fork
+fprintf
+fputc
+fputs
+fread
+free
+frexp
+fseek
+fsetpos
+fsync
+ftruncate
+fwrite
+getcwd
+getenv
+getlogin
+getnetbyname
+getpid
+getpwuid
+gettimeofday
+getuid
+gmtime
+hypot
+inet_network
+ioctl
+isalnum
+isalpha
+isatty
+iscntrl
+isdigit
+isgraph
+islower
+isprint
+ispunct
+isspace
+isupper
+isxdigit
+j0
+j1
+jn
+kill
+labs
+ldexp
+ldiv
+localtime
+log
+log10
+longjmp
+lseek
+malloc
+mblen
+memchr
+memcmp
+memcpy
+memmove
+memset
+mkdir
+mktime
+mmap
+modf
+mprotect
+msync
+munmap
+open
+opendir
+perror
+pipe
+poll
+pow
+printf
+putchar
+putenv
+puts
+qsort
+raise
+rand
+read
+readdir
+realloc
+remove
+rename
+rmdir
+select
+setbuf
+setlocale
+setsid
+settimeofday
+setvbuf
+shmat
+shmctl
+shmdt
+shmget
+sigaction
+sigaddset
+sigaltstack
+sigemptyset
+signal
+sigprocmask
+sin
+sin
+sinh
+sleep
+snprintf
+sprintf
+sqrt
+srand
+sscanf
+statfs
+strcasecmp
+strcat
+strchr
+strcmp
+strcoll
+strcpy
+strcspn
+strdup
+strerror
+strftime
+strlen
+strncasecmp
+strncat
+strncmp
+strncpy
+strpbrk
+strrchr
+strspn
+strstr
+strtod
+strtok
+strtol
+strtoul
+strxfrm
+sysi86
+system
+tan
+tanh
+tcflush
+tcgetattr
+tcsetattr
+tempnam
+time
+times
+tmpnam
+tolower
+toupper
+towlower
+towupper
+unlink
+usleep
+utime
+vfprintf
+vsprintf
+wait4
+write
+y0
+y1
+yn
diff --git a/tools/winapi_check/nativeapi.pm b/tools/winapi_check/nativeapi.pm
new file mode 100644
index 0000000..136689d
--- /dev/null
+++ b/tools/winapi_check/nativeapi.pm
@@ -0,0 +1,38 @@
+package nativeapi;
+
+use strict;
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = {};
+    bless ($self, $class);
+
+    my $functions = \%{$self->{FUNCTIONS}};
+
+    my $file = shift;
+
+    open(IN, "< $file");
+    $/ = "\n";
+    while(<IN>) {
+	s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
+	s/^(.*?)\s*#.*$/$1/;  # remove comments
+	/^$/ && next;         # skip empty lines   
+	
+	$$functions{$_} = 1;
+    }
+    close(IN);
+
+    return $self;
+}
+
+sub is_function {
+    my $self = shift;
+    my $functions = \%{$self->{FUNCTIONS}};
+
+    my $name = shift;
+
+    return $$functions{$name};
+}
+
+1;
diff --git a/tools/winapi_check/parser.pm b/tools/winapi_check/parser.pm
new file mode 100644
index 0000000..537ef70
--- /dev/null
+++ b/tools/winapi_check/parser.pm
@@ -0,0 +1,184 @@
+package parser;
+
+BEGIN {
+    use Exporter   ();
+    use vars       qw(@ISA @EXPORT);
+
+    @ISA         = qw(Exporter);
+    @EXPORT      = qw(&init
+		      &transact &commit &rollback &token
+		      &dump_state
+		      &either &filter &many &many1 &separate &separate1 &sequence);
+}
+
+my @stack;
+my $current;
+my $next;
+
+sub init {
+    @stack = ();
+    $current = [];
+    $next = shift;
+
+    @$next = grep {
+	$_->{type} !~ /^comment|preprocessor$/;
+    } @$next;
+}
+
+sub dump_state {
+    print "stack: [\n";
+    for my $tokens (@stack) {
+	print "  [\n";
+	for my $token (@$tokens) {
+	    print "    " . $token->{type} . ": " . $token->{data} . "\n";
+	}
+	print "  ]\n";
+    }
+    print "]\n";
+    print "current: [\n";
+    for my $token (@$current) {
+	print "  " . $token->{type} . ": " . $token->{data} . "\n";
+    }
+    print "]\n";
+    print "next: [\n";
+    for my $token (@$next) {
+	print "  " . $token->{type} . ": " . $token->{data} . "\n";
+    }
+    print "]\n";
+}
+
+sub token {
+    my $token = shift @$next;
+    push @$current, $token;
+    return $token;
+};
+
+sub transact {
+    push @stack, $current; 
+    $current = [];
+}
+
+sub commit {
+    my $oldcurrent = $current;
+    $current = pop @stack;
+    push @$current, @$oldcurrent;
+}
+
+sub rollback {
+    unshift @$next, @$current;
+    $current = pop @stack;
+}
+
+sub filter {
+    my $parser = shift;
+    my $filter = shift;
+
+    transact;
+    my $r1 = &$parser;
+    if(defined($r1)) {
+	my $r2 = &$filter($r1);
+	if($r2) {
+	    commit;
+	    return $r1;
+	} else {
+	    rollback;
+	    return undef;
+	}
+    } else {
+	rollback;
+	return undef;
+    }
+}
+
+sub either {
+    for my $parser (@_) {
+	transact;
+	my $r = &$parser;
+	if(defined($r)) {
+	    commit;
+	    return $r;
+	} else {
+	    rollback;
+	}
+    }
+    return undef;
+}
+
+sub sequence {
+    transact;
+    my $rs = [];
+    for my $parser (@_) {
+	my $r = &$parser;
+	if(defined($r)) {
+	    push @$rs, $r;
+	} else {
+	    rollback;
+	    return undef;
+	}	
+    }
+    commit;
+    return $rs;
+}
+
+sub separate {
+    my $parser = shift;
+    my $separator = shift;
+    my $rs = [];
+    while(1) {
+	my $r = &$parser;
+	if(defined($r)) {
+	    push @$rs, $r;
+	} else {
+	    last;
+	}
+	my $s = &$separator;
+	if(!defined($r)) {
+	    last;
+	}
+    
+    }
+    return $rs;
+}
+
+sub separate1 {
+    my $parser = shift;
+    my $separator = shift;
+    transact;
+    my $rs = separate($parser,$separator);
+    if($#$rs != -1) {
+	commit;
+	return $rs;
+    } else {
+	rollback;
+	return undef;
+    }
+}
+
+sub many {
+    my $parser = shift;
+    my $rs = [];
+    while(1) {
+	my $r = &$parser;
+	if(defined($r)) {
+	    push @$rs, $r;
+	} else {
+	    last;
+	}
+    }
+    return $rs;
+}
+
+sub many1 {
+    my $parser = shift;
+    transact;
+    my $rs = many($parser);
+    if($#$rs != -1) {
+	commit;
+	return $rs;
+    } else {
+	rollback;
+	return undef;
+    }
+}
+
+1;
diff --git a/tools/winapi_check/win16api.dat b/tools/winapi_check/win16api.dat
new file mode 100644
index 0000000..4a31782
--- /dev/null
+++ b/tools/winapi_check/win16api.dat
@@ -0,0 +1,348 @@
+%long
+
+COLORREF
+DWORD
+FOURCC
+HCONV
+HCONVLIST
+HDDEDATA
+HHOOK
+HKEY
+HRESULT
+HSZ
+LCID
+LCTYPE
+LHCLIENTDOC
+LHSERVER
+LHSERVERDOC
+LONG
+LPARAM
+LRESULT
+POINT16
+ULONG
+
+%longlong
+
+LARGE_INTEGER
+
+%ptr
+
+ACMDRIVERENUMCB16
+ACMFILTERENUMCB16
+ACMFILTERTAGENUMCB16
+ACMFORMATENUMCB16
+ACMFORMATTAGENUMCB16
+BITMAP16 *
+BITMAPINFO *
+BITMAPINFOHEADER *
+BOOL16 *
+BSTR16 *
+CLASSENTRY *
+CLSID *
+COLORREF *
+CONTEXT86 *
+CURSORICONINFO *
+DEVMODEA *
+DOCINFO16 *
+DWORD *
+FARPROC *
+FARPROC16 *
+FILETIME *
+GLOBALENTRY *
+GLOBALINFO *
+GUID *
+HANDLE *
+HANDLETABLE16 *
+HHOOK *
+HICON16 *
+HINSTANCE16 *
+HMIDIIN16 *
+HMIDIOUT16 *
+HMIDISTRM16 *
+HPCSTR
+HPSTR
+HTASK16 *
+HWAVEIN16 *
+HWAVEOUT16 *
+IID *
+IMalloc16 *
+INT16 *
+INTERFACEDATA *
+IStorage16 *
+IStorage16 **
+IStream16 *
+IStream16 **
+ITypeInfo **
+IUnknown *
+LHCLIENTDOC *
+LHSERVERDOC *
+LOCAL32ENTRY *
+LOCAL32INFO *
+LOCALENTRY *
+LOCALINFO *
+LOGBRUSH16 *
+LOGFONT16 *
+LOGPALETTE *
+LOGPEN16 *
+LPABC16
+LPACMDRIVERDETAILS16
+LPACMFILTERCHOOSE16
+LPACMFILTERDETAILS16
+LPACMFILTERTAGDETAILS16
+LPACMFORMATCHOOSE16
+LPACMFORMATDETAILS16
+LPACMFORMATTAGDETAILS16
+LPACMSTREAMHEADER16
+LPAUXCAPS16
+LPBSTR16
+LPBYTE
+LPCATCHBUF
+LPCHOOSECOLOR16
+LPCHOOSEFONT16
+LPCLSID
+LPCOMSTAT16
+LPCONVCONTEXT16
+LPCONVINFO16
+LPCURSORINFO
+LPCVOID
+LPDCB16
+LPDEVMODEA
+LPDRIVERINFOSTRUCT16
+LPDWORD
+LPENUMLOGFONT16
+LPFILETIME
+LPFONTINFO16
+LPGLYPHMETRICS16
+LPHACMDRIVER16
+LPHACMDRIVERID16
+LPHACMSTREAM16
+LPHANDLE
+LPHKEY
+LPHMIXER16
+LPICONINFO16
+LPINT16
+LPJOYCAPS16
+LPJOYINFO16
+LPKERNINGPAIR16
+LPLOGFONT16
+LPMALLOC16 *
+LPMEMORY_BASIC_INFORMATION
+LPMESSAGEFILTER
+LPMESSAGEFILTER *
+LPMIDIHDR16
+LPMIDIINCAPS16
+LPMIDIOUTCAPS16
+LPMIXERCAPS16
+LPMIXERCONTROLDETAILS16
+LPMIXERLINE16
+LPMIXERLINECONTROLS16
+LPMMCKINFO
+LPMMIOPROC16
+LPMMTIME16
+LPMONIKER *
+LPMSG16
+LPMSG16_32
+LPMSGBOXPARAMS16
+LPNEWTEXTMETRIC16
+LPOFSTRUCT
+LPOLECLIENT
+LPOLEOBJECT
+LPOLEOBJECT *
+LPOLESERVERDOC
+LPOLESTR16 *
+LPDROPTARGET
+LPOUTLINETEXTMETRIC16
+LPPAINTSTRUCT16
+LPPALETTEENTRY
+LPPDEVICE
+LPPOINT16
+LPQUEUESTRUCT16 *
+LPRASTERIZER_STATUS
+LPRECT16
+LPRGNDATA
+LPRUNNINGOBJECTTABLE *
+LPSCROLLINFO
+LPSIZE16
+LPSTORAGE16
+LPTEXTXFORM16
+LPTIMECAPS16
+LPUINT16
+LPUNKNOWN
+LPVOID
+LPVOID *
+LPWAVEFILTER
+LPWAVEFORMATEX
+LPWAVEINCAPS16
+LPWAVEOUTCAPS16
+LPWIN32SINFO
+LPWORD
+LPWSADATA
+MAT2 *
+MEMMANINFO *
+MENUITEMINFO16 *
+METARECORD *
+MIDIHDR16 *
+MMCKINFO *
+MMIOINFO16 *
+MODULEENTRY *
+MSG16 *
+MSG32_16 *
+OFSTRUCT *
+OSVERSIONINFO16 *
+PAINTSTRUCT16 *
+PALETTEENTRY *
+POINT16 *
+RECT16 *
+REFCLSID
+REFGUID
+REFIID
+RGBQUAD *
+SCROLLINFO *
+SECURITY_ATTRIBUTES *
+SEGINFO *
+SEGPTR *
+SNB16
+STACKTRACEENTRY *
+STATSTG16 *
+SYSHEAPINFO *
+SYSLEVEL *
+TASKENTRY *
+TEXTMETRIC16 *
+THUNKLET *
+TIMERINFO *
+UINT16 *
+ULARGE_INTEGER *
+ULONG *
+VOID *
+WAVEHDR *
+WIN32_FIND_DATAA *
+WINDEBUGINFO *
+WINDOWPLACEMENT16 *
+WNDCLASS16 *
+WNDCLASSEX16 *
+WORD *
+char *
+struct ThunkDataCommon *
+struct Win87EmInfoStruct *
+struct sockaddr *
+struct tagCURSORICONINFO *
+struct timeval *
+void *
+ws_fd_set16 *
+
+%s_word
+
+INT16
+
+%segptr
+
+DLGPROC16
+FARPROC16
+FONTENUMPROC16
+FONTENUMPROCEX16
+GOBJENUMPROC16
+GRAYSTRINGPROC16
+HOOKPROC16
+LINEDDAPROC16
+LPTIMECALLBACK16
+MFENUMPROC16
+PROPENUMPROC16
+SEGPTR
+TIMERPROC16
+WNDENUMPROC16
+WNDPROC16
+
+%segstr
+
+BSTR16
+
+%str
+
+LPCOLESTR16
+LPCSTR
+LPCWSTR
+LPSTR
+LPOLESTR16
+
+%unknown
+
+struct in_addr
+
+%void
+
+void
+VOID
+
+%word
+
+ATOM
+BOOL16
+BYTE
+CHAR
+HACCEL16
+HACMDRIVER16
+HACMDRIVERID16
+HACMOBJ16
+HACMSTREAM16
+HANDLE16
+HBITMAP16
+HBRUSH16
+HCURSOR16
+HDC16
+HDROP16
+HDRVR16
+HDWP16
+HFILE16
+HFONT16
+HGDIOBJ16
+HGLOBAL16
+HICON16
+HINSTANCE16
+HLOCAL16
+HMENU16
+HMETAFILE16
+HMIDIIN16
+HMIDIOUT16
+HMIDISTRM16
+HMIXER16
+HMIXEROBJ16
+HMMIO16
+HMODULE16
+HPALETTE16
+HPEN16
+HPJOB16
+HPQ16
+HQUEUE16
+HRGN16
+HRSRC16
+HTASK16
+HWAVEIN16
+HWAVEOUT16
+HWND16
+LANGID
+MMRESULT16
+OLESTATUS
+SOCKET16
+UINT16
+WING_DITHER_TYPE
+WORD
+WPARAM16
+
+%unknown --forbidden
+
+BOOL
+FARPROC
+HANDLE
+HINSTANCE
+HMODULE
+HWND
+INT
+LPOLESTR
+UINT
+YIELDPROC
+int
+long
+short
+u_long
+u_short
+unsigned
diff --git a/tools/winapi_check/win32api.dat b/tools/winapi_check/win32api.dat
new file mode 100644
index 0000000..f553d12
--- /dev/null
+++ b/tools/winapi_check/win32api.dat
@@ -0,0 +1,785 @@
+%double
+
+CY
+double
+
+%long
+
+ACCESS_MASK
+ATOM
+BOOL
+BOOLEAN
+BYTE
+CALID
+CALTYPE
+CHAR
+CLIPFORMAT
+COLORREF
+COORD
+DATE
+DIGEST_HANDLE
+DPAENUMPROC
+DWORD
+FILE_INFORMATION_CLASS
+FLOAT
+FOURCC
+FS_INFORMATION_CLASS
+GET_FILEEX_INFO_LEVELS
+HACCEL
+HACMDRIVER
+HACMDRIVERID
+HACMOBJ
+HACMSTREAM
+HANDLE
+HBITMAP
+HBRUSH
+HCALL
+HCOLORSPACE
+HCONV
+HCONVLIST
+HCURSOR
+HCRYPTKEY
+HDC
+HDDEDATA
+HDESK
+HDROP
+HDRVR
+HDSA
+HDWP
+HENHMETAFILE
+HFILE
+HFONT
+HGDIOBJ
+HGLOBAL
+HHOOK
+HIC
+HICON
+HIMC
+HINSTANCE
+HKEY
+HKL
+HLINE
+HLINEAPP
+HLOCAL
+HMENU
+HMETAFILE
+HMIDIIN
+HMIDIOUT
+HMIDISTRM
+HMIXER
+HMIXEROBJ
+HMMIO
+HMODULE
+HMONITOR
+HOLEMENU
+HPALETTE
+HPEN
+HPHONE
+HPHONEAPP
+HPROPSHEETPAGE
+HPROVIDER
+HRESULT
+HRGN
+HRSRC
+HSZ
+HTASK
+HWAVEIN
+HWAVEOUT
+HWINSTA
+HWND
+INT
+KEY_INFORMATION_CLASS
+KEY_VALUE_INFORMATION_CLASS
+LANGID
+LCID
+LCTYPE
+LHCLIENTDOC
+LHSERVER
+LHSERVERDOC
+LONG
+LPARAM
+LRESULT
+MMRESULT
+NTSTATUS
+OBJECT_INFORMATION_CLASS
+OLECLIPFORMAT
+OLEOPT_RENDER
+OLESTATUS
+OLE_SERVER_USE
+OUT
+PHANDLE
+PHPROVIDER
+PIO_APC_ROUTINE
+PLSA_HANDLE
+PLSA_OBJECT_ATTRIBUTES
+PLSA_UNICODE_STRING
+POBJDIR_INFORMATION
+PROCESSINFOCLASS
+PTIME_FIELDS
+PTOKEN_PRIVILEGES
+REGSAM
+SC_HANDLE
+SECTION_INHERIT
+SECURITY_IMPERSONATION_LEVEL
+SECURITY_INFORMATION
+SEGPTR
+SERVICE_STATUS_HANDLE
+SHORT
+SOCKET
+SYSKIND
+SYSTEM_INFORMATION_CLASS
+THREADINFOCLASS
+TIMER_TYPE
+TOKEN_INFORMATION_CLASS
+TOKEN_TYPE
+UINT
+ULONG
+ULONG_PTR
+USHORT
+VARIANT_BOOL
+VARTYPE
+WCHAR
+WORD
+WOW_HANDLE_TYPE
+WPARAM
+clock_t
+enum NOTIFYTYPE
+time_t
+
+%longlong
+
+LARGE_INTEGER
+POINT
+
+%ptr
+
+ABORTPROC
+ACMDRIVERENUMCB
+ACMFILTERENUMCBA
+ACMFILTERENUMCBW
+ACMFILTERTAGENUMCBA
+ACMFILTERTAGENUMCBW
+ACMFORMATENUMCBA
+ACMFORMATENUMCBW
+ACMFORMATTAGENUMCBA
+ACMFORMATTAGENUMCBW
+AVICOMPRESSOPTIONS *
+AVISTREAMINFOA *
+AVISTREAMINFOW *
+BITMAP *
+BITMAPINFO *
+BITMAPINFOHEADER *
+BOOL *
+BSTR *
+BYTE *
+BY_HANDLE_FILE_INFORMATION *
+CALINFO_ENUMPROCA
+CHAR *
+CLIPFORMAT *
+CLSID *
+CODEPAGE_ENUMPROCA
+CODEPAGE_ENUMPROCW
+COLORADJUSTMENT *
+COLORREF *
+CONST
+CONTEXT *
+COSERVERINFO *
+CRITICAL_SECTION *
+CRTDLL_FILE *
+CY *
+DATE *
+DATEFMT_ENUMPROCA
+DATEFMT_ENUMPROCW
+DEVMODEA *
+DEVMODEW *
+DIGEST_FUNCTION
+DLGPROC
+DLLVERSIONINFO *
+DOCINFOA *
+DOCINFOW *
+DPALOADPROC
+DRAWSTATEPROC
+DSAENUMPROC
+DWORD *
+ENHMETARECORD *
+ENHMFENUMPROC
+ENUMRESLANGPROCA
+ENUMRESLANGPROCW
+ENUMRESNAMEPROCA
+ENUMRESNAMEPROCW
+ENUMRESTYPEPROCA
+ENUMRESTYPEPROCW
+EXCEPTION_RECORD *
+FARPROC
+FARPROC *
+FILETIME *
+FLOAT *
+FONTENUMPROCA
+FONTENUMPROCEXA
+FONTENUMPROCEXW
+FONTENUMPROCW
+GCP_RESULTSA *
+GCP_RESULTSW *
+GOBJENUMPROC
+GRAYSTRINGPROC
+GUID *
+HANDLE *
+HANDLER_ROUTINE *
+HANDLETABLE *
+HCRYPTPROV *
+HDPA
+HDPA *
+HGLOBAL *
+HICON *
+HIMAGELIST
+HIMAGELIST *
+HKL *
+HMENU *
+HMIDIIN *
+HMIDIOUT *
+HMIDISTRM *
+HMRU
+HOOKPROC
+HPCSTR
+HPSTR
+HWAVEIN *
+HWAVEOUT *
+HWND *
+ICINFO *
+IDSTRUCT *
+IDataObject *
+IDataObject **
+IDropSource *
+IDropTarget *
+ILockBytes *
+IMAGEINFO *
+IMAGELISTDRAWPARAMS *
+INPUT_RECORD *
+INT *
+IPersistStream *
+IShellFolder **
+IStorage *
+IStorage **
+IStream *
+ITypeLib *
+ITypeLib **
+IUnknown *
+LHCLIENTDOC *
+LHSERVER *
+LHSERVERDOC *
+LINECALLBACK
+LINEDDAPROC
+LOCALE_ENUMPROCA
+LOCALE_ENUMPROCW
+LOGBRUSH *
+LOGFONTA *
+LOGFONTW *
+LOGPALETTE *
+LOGPEN *
+LONG *
+LPABC
+LPABCFLOAT
+LPACCEL
+LPAUTHDLGSTRUCTA
+LPAUXCAPSA
+LPAUXCAPSW
+LPAVIFILEINFOA
+LPAVIFILEINFOW
+LPBC *
+LPBITMAPINFOHEADER
+LPBOOL
+LPBROWSEINFOA
+LPBSTR
+LPBYTE
+LPCANDIDATEFORM
+LPCANDIDATELIST
+LPCHARSETINFO
+LPCHAR_INFO
+LPCHOOSECOLORA
+LPCHOOSECOLORW
+LPCHOOSEFONTA
+LPCHOOSEFONTW
+LPCITEMIDLIST
+LPCITEMIDLIST *
+LPCLSID
+LPCMENUINFO
+LPCOLDTBBUTTON
+LPCOLORADJUSTMENT
+LPCOLORMAP
+LPCOMMTIMEOUTS
+LPCOMPOSITIONFORM
+LPCOMSTAT
+LPCONNECTDLGSTRUCTA
+LPCONNECTDLGSTRUCTW
+LPCONSOLE_CURSOR_INFO
+LPCONSOLE_SCREEN_BUFFER_INFO
+LPCONVCONTEXT
+LPCONVINFO
+LPCPINFO
+LPCPROPSHEETHEADERA
+LPCPROPSHEETHEADERW
+LPCPROPSHEETPAGEA
+LPCPROPSHEETPAGEW
+LPCSTR *
+LPCTBBUTTON
+LPCVOID
+LPCWSTR *
+LPDATAADVISEHOLDER *
+LPDATAOBJECT
+LPDCB
+LPDDENUMCALLBACKA
+LPDDENUMCALLBACKEXA
+LPDDENUMCALLBACKEXW
+LPDDENUMCALLBACKW
+LPDEBUG_EVENT
+LPDEVMODEA
+LPDEVMODEW
+LPDIRECTDRAW *
+LPDIRECTDRAWCLIPPER *
+LPDIRECTPLAYLOBBY *
+LPDIRECTPLAYLOBBYA *
+LPDIRECTSOUND *
+LPDISCDLGSTRUCTA
+LPDISCDLGSTRUCTW
+LPDPENUMDPCALLBACKA
+LPDPENUMDPCALLBACKW
+LPDRAWITEMSTRUCT
+LPDRAWTEXTPARAMS
+LPDROPTARGET
+LPDSENUMCALLBACKA
+LPDWORD
+LPENHMETAHEADER
+LPENUMFORMATETC *
+LPENUMOLEVERB *
+LPENUM_SERVICE_STATUSA
+LPFILETIME
+LPFINDREPLACEA
+LPFINDREPLACEW
+LPFNCREATEINSTANCE
+LPFNFMCALLBACK
+LPFONTDESC
+LPFONTSIGNATURE
+LPFORMATETC
+LPGLYPHMETRICS
+LPGUID
+LPHANDLE
+LPHANDLER_FUNCTION
+LPHANDLETABLE
+LPHCALL
+LPHKEY
+LPHLINE
+LPHLINEAPP
+LPHMIXER
+LPHPHONE
+LPHPHONEAPP
+LPICONINFO
+LPINITCOMMONCONTROLSEX
+LPINPUT_RECORD
+LPINT
+LPITEMIDLIST *
+LPITEMIDLIST
+LPJOYCAPSA
+LPJOYCAPSW
+LPJOYINFO
+LPJOYINFOEX
+LPKERNINGPAIR
+LPLDT_ENTRY
+LPLINEADDRESSCAPS
+LPLINEADDRESSSTATUS
+LPLINECALLINFO
+LPLINECALLLIST
+LPLINECALLPARAMS
+LPLINECALLSTATUS
+LPLINECOUNTRYLIST
+LPLINEDEVCAPS
+LPLINEDEVSTATUS
+LPLINEDIALPARAMS
+LPLINEEXTENSIONID
+LPLINEFORWARDLIST
+LPLINEGENERATETONE
+LPLINEMEDIACONTROLCALLSTATE
+LPLINEMEDIACONTROLDIGIT
+LPLINEMEDIACONTROLMEDIA
+LPLINEMEDIACONTROLTONE
+LPLINEMONITORTONE
+LPLINEPROVIDERLIST
+LPLINETRANSLATECAPS
+LPLINETRANSLATEOUTPUT
+LPLOCKBYTES *
+LPLOGFONTA
+LPLOGFONTW
+LPLONG
+LPMALLOC *
+LPMEASUREITEMSTRUCT
+LPMEMORYSTATUS
+LPMEMORY_BASIC_INFORMATION
+LPMENUINFO
+LPMENUITEMINFOA
+LPMENUITEMINFOW
+LPMESSAGEFILTER
+LPMESSAGEFILTER *
+LPMIDIHDR
+LPMIDIINCAPSA
+LPMIDIINCAPSW
+LPMIDIOUTCAPSA
+LPMIDIOUTCAPSW
+LPMIXERCAPSA
+LPMIXERCAPSW
+LPMIXERCONTROLDETAILS
+LPMIXERLINEA
+LPMIXERLINECONTROLSA
+LPMIXERLINECONTROLSW
+LPMIXERLINEW
+LPMMCKINFO
+LPMMIOPROC
+LPMMTIME
+LPMODULEENTRY
+LPMONIKER
+LPMONIKER *
+LPMONITORINFO
+LPMRUINFO
+LPMSG
+LPMSGBOXPARAMSA
+LPMSGBOXPARAMSW
+LPNETCONNECTINFOSTRUCT
+LPNETINFOSTRUCT
+LPNETRESOURCEA
+LPNETRESOURCEW
+LPNMHDR
+LPOFSTRUCT
+LPOLEADVISEHOLDER *
+LPOLECLIENT
+LPOLECLIENTSITE
+LPOLEINPLACEACTIVEOBJECT
+LPOLEINPLACEFRAME
+LPOLEINPLACEFRAMEINFO
+LPOLEMENUGROUPWIDTHS
+LPOLEOBJECT
+LPOLEOBJECT *
+LPOLESERVER
+LPOLESERVERDOC
+LPOLESTR
+LPOLESTR *
+LPOLEUIBUSYA
+LPOLEUIBUSYW
+LPOLEUICHANGEICONA
+LPOLEUICHANGEICONW
+LPOLEUICHANGESOURCEA
+LPOLEUICHANGESOURCEW
+LPOLEUICONVERTA
+LPOLEUICONVERTW
+LPOLEUIEDITLINKSA
+LPOLEUIEDITLINKSW
+LPOLEUIINSERTOBJECTA
+LPOLEUIINSERTOBJECTW
+LPOLEUILINKCONTAINERA
+LPOLEUIOBJECTPROPSA
+LPOLEUIOBJECTPROPSW
+LPOLEUIPASTESPECIALA
+LPOLEUIPASTESPECIALW
+LPOPENFILENAMEA
+LPOPENFILENAMEW
+LPOUTLINETEXTMETRICA
+LPOUTLINETEXTMETRICW
+LPOVERLAPPED
+LPOVERLAPPED_COMPLETION_ROUTINE
+LPPAGESETUPDLGA
+LPPALETTEENTRY
+LPPERSISTSTORAGE
+LPPHONEBUTTONINFO
+LPPHONECAPS
+LPPHONEEXTENSIONID
+LPPHONESTATUS
+LPPIXELFORMATDESCRIPTOR
+LPPOINT
+LPPRINTDLGA
+LPPRINTDLGW
+LPPRINTER_DEFAULTSA
+LPPRINTER_DEFAULTSW
+LPPROCESSENTRY
+LPPROCESS_HEAP_ENTRY *
+LPPROCESS_INFORMATION
+LPPROGRESS_ROUTINE
+LPRASCONNA
+LPRASTERIZER_STATUS
+LPRECT
+LPRGNDATA
+LPRTL_RWLOCK
+LPRUNNINGOBJECTTABLE *
+LPSCROLLINFO
+LPSECURITY_ATTRIBUTES
+LPSERVICE_STATUS
+LPSERVICE_TABLE_ENTRYA
+LPSERVICE_TABLE_ENTRYW
+LPSHELLEXECUTEINFOA
+LPSHELLEXECUTEINFOW
+LPSHELLFLAGSTATE
+LPSHELLFOLDER
+LPSHELLVIEWDATA
+LPSHFILEOPSTRUCTA
+LPSHFILEOPSTRUCTW
+LPSIZE
+LPSMALL_RECT
+LPSRB
+LPSTARTUPINFOA
+LPSTARTUPINFOW
+LPSTORAGE
+LPSTR *
+LPSTR **
+LPSTREAM
+LPSTREAM *
+LPSTRRET
+LPSTYLEBUFA
+LPSTYLEBUFW
+LPSYSTEMTIME
+LPSYSTEM_INFO
+LPSYSTEM_POWER_STATUS
+LPTHREAD_START_ROUTINE
+LPTIMECALLBACK
+LPTIMECAPS
+LPTIME_ZONE_INFORMATION
+LPTOP_LEVEL_EXCEPTION_FILTER
+LPTPMPARAMS
+LPUINT
+LPUNKNOWN
+LPUNKNOWN *
+LPVARSTRING
+LPVOID
+LPVOID *
+LPWAVEFORMATEX
+LPWAVEINCAPSA
+LPWAVEINCAPSW
+LPWAVEOUTCAPSA
+LPWAVEOUTCAPSW
+LPWORD
+LPWSADATA
+LPWSTR *
+LPXFORM
+MAT2 *
+MENUITEMINFOA *
+MENUITEMINFOW *
+METARECORD *
+MFENUMPROC
+MIDIHDR *
+MMCKINFO *
+MMIOINFO *
+MONITORENUMPROC
+MSG *
+MULTI_QI *
+NOTIFYCALLBACK
+NUMBERFMTA *
+NUMBERFMTW *
+OFSTRUCT *
+OSVERSIONINFOA *
+OSVERSIONINFOW *
+PACE_HEADER
+PACE_HEADER *
+PACL
+PACL *
+PACMDRIVERDETAILSA
+PACMDRIVERDETAILSW
+PACMFILTERCHOOSEA
+PACMFILTERCHOOSEW
+PACMFILTERDETAILSA
+PACMFILTERDETAILSW
+PACMFILTERTAGDETAILSA
+PACMFILTERTAGDETAILSW
+PACMFORMATCHOOSEA
+PACMFORMATCHOOSEW
+PACMFORMATDETAILSA
+PACMFORMATDETAILSW
+PACMFORMATTAGDETAILSA
+PACMFORMATTAGDETAILSW
+PACMSTREAMHEADER
+PAINTSTRUCT *
+PALETTEENTRY *
+PANSI_STRING
+PAPCFUNC
+PAPI_VERSION
+PAPPBARDATA
+PAVIFILE
+PAVIFILE *
+PAVISTREAM
+PAVISTREAM *
+PBOOLEAN
+PBYTE
+PCHAR
+PCHAR *
+PCONTEXT
+PDWORD
+PENUMLOADED_MODULES_CALLBACK
+PEXCEPTION_FRAME
+PEXCEPTION_FRAME *
+PEXCEPTION_POINTERS
+PEXCEPTION_RECORD
+PFLOAT
+PFNCALLBACK
+PFNDPACOMPARE
+PFNDPAMERGE
+PFUNCTION_TABLE_ACCESS_ROUTINE
+PGENERIC_MAPPING
+PGETFRAME
+PGET_MODULE_BASE_ROUTINE
+PHACMDRIVER
+PHACMDRIVERID
+PHACMSTREAM
+PHONECALLBACK
+PIMAGEHLP_MODULE
+PIMAGEHLP_STATUS_ROUTINE
+PIMAGEHLP_SYMBOL
+PIMAGE_DEBUG_INFORMATION
+PIMAGE_LOAD_CONFIG_DIRECTORY
+PIMAGE_NT_HEADERS
+PIMAGE_SECTION_HEADER
+PIMAGE_SECTION_HEADER *
+PIO_STATUS_BLOCK
+PIXELFORMATDESCRIPTOR *
+PLARGE_INTEGER
+PLOADED_IMAGE
+PLONG
+PLUID
+PNOTIFYICONDATAA
+POBJECT_ATTRIBUTES
+POINT *
+PPRIVILEGE_SET
+PREAD_PROCESS_MEMORY_ROUTINE
+PRTL_HEAP_DEFINITION
+PROPENUMPROCA
+PROPENUMPROCEXA
+PROPENUMPROCEXW
+PROPENUMPROCW
+PSECURITY_DESCRIPTOR
+PSECURITY_DESCRIPTOR_CONTROL
+PSECURITY_QUALITY_OF_SERVICE
+PSID
+PSID *
+PSID_IDENTIFIER_AUTHORITY
+PSID_NAME_USE
+PSTACKFRAME
+PSTRING
+PSYMBOL_REGISTERED_CALLBACK
+PSYM_ENUMMODULES_CALLBACK
+PSYM_ENUMSYMBOLS_CALLBACK
+PTIMERAPCROUTINE
+PTRANSLATE_ADDRESS_ROUTINE
+PUCHAR
+PULARGE_INTEGER
+PULONG
+PUNICODE_STRING
+PVOID
+PVOID *
+PWAVEFILTER
+PWAVEFORMATEX
+PWIN_CERTIFICATE
+RECT *
+REFCLSID
+REFGUID
+REFIID
+REGISTERWORDENUMPROCA
+REGISTERWORDENUMPROCW
+RGBQUAD *
+RGNDATA *
+SAFEARRAY *
+SAFEARRAY **
+SAFEARRAYBOUND *
+SCROLLINFO *
+SECURITY_ATTRIBUTES *
+SECURITY_DESCRIPTOR *
+SECURITY_INFORMATION *
+SHFILEINFOA *
+SHFILEINFOW *
+SNB
+STGMEDIUM *
+SYSLEVEL *
+SYSLEVEL **
+SYSTEMTIME *
+TEXTMETRICA *
+TEXTMETRICW *
+TIMEFMT_ENUMPROCA
+TIMEFMT_ENUMPROCW
+TIMERPROC
+UINT *
+ULONG *
+USHORT *
+VARIANT *
+VARIANTARG *
+VARIANT_BOOL *
+VOID *
+VOID **
+WAVEHDR *
+WCHAR *
+WIN32_FIND_DATAA *
+WIN32_FIND_DATAW *
+WINDOWPLACEMENT *
+WNDCLASSA *
+WNDCLASSEXA *
+WNDCLASSEXW *
+WNDCLASSW *
+WNDENUMPROC
+WNDPROC
+WORD *
+XFORM *
+YIELDPROC
+_INITTERMFUN *
+char *
+double *
+jmp_buf
+short *
+struct _TEB *
+struct ThunkDataCommon *
+struct find_t *
+struct sockaddr *
+struct stat *
+struct timeval *
+struct win_stat *
+struct WIN_hostent *
+struct WIN_protoent *
+struct WIN_servent *
+time_t *
+va_list
+void *
+void **
+ws_fd_set32 *
+
+%str
+
+LPCSTR
+LPSTR
+OLECHAR *
+
+%unknown
+
+new_handler_type
+sig_handler_type
+struct in_addr
+
+%void
+
+void
+VOID
+
+%wstr
+
+BSTR
+LPCOLESTR
+LPCWSTR
+LPWSTR
+
+%long # --forbidden
+
+BOOL16
+FARPROC16
+HTASK16
+HGLOBAL16
+HINSTANCE16
+HMMIO16
+HMODULE16
+LPOLESTR16
+UINT16
+SOCKET16
+int
+long
+short
+u_long
+u_short
+unsigned
diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm
new file mode 100644
index 0000000..6b48905
--- /dev/null
+++ b/tools/winapi_check/winapi.pm
@@ -0,0 +1,318 @@
+package winapi;
+
+use strict;
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = {};
+    bless ($self, $class);
+
+    my $allowed_kind = \%{$self->{ALLOWED_KIND}};
+    my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
+    my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
+    my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
+
+    $self->{NAME} = shift;
+    my $file = shift;
+
+    my @modules;
+    my $kind;
+    my $forbidden = 0;
+
+    open(IN, "< $file") || die "$file: $!\n";
+    $/ = "\n";
+    while(<IN>) {
+	s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
+	s/^(.*?)\s*#.*$/$1/;  # remove comments
+	/^$/ && next;         # skip empty lines
+
+	if(s/^%(\S+)\s*//) {
+	    $kind = $1;
+	    @modules = ();
+	    $forbidden = 0;
+
+	    $$allowed_kind{$kind} = 1;
+	    if(/^--module=(\S*)/) {
+		@modules = split(/,/, $1);
+	    } elsif(/^--forbidden/) {
+		$forbidden = 1;
+	    }
+	} elsif(defined($kind)) {
+	    my $type = $_;
+	    if(!$forbidden) {
+		for my $module (@modules) {
+		    $$allowed_modules_limited{$type} = 1;
+		    $$allowed_modules{$type}{$module} = 1;
+		}
+	    } else {
+		$$allowed_modules_limited{$type} = 1;
+	    }
+	    $$translate_argument{$type} = $kind;
+	} else {
+	    print "$file: file must begin with %<type> statement\n";
+	    exit 1;
+	}
+    }
+    close(IN);
+
+    return $self;
+}
+
+sub get_spec_file_type {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+
+    my $file = shift;
+
+    my $type;
+
+    open(IN, "< $file") || die "$file: $!\n";
+    $/ = "\n";
+    while(<IN>) {
+	if(/^type\s*(\w+)/) {
+	    $type = $1;
+	    last;
+	}
+    }
+    close(IN);
+
+    return $type;
+}
+
+sub read_spec_files {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+
+    my $win16api = shift;
+    my $win32api = shift;
+
+    foreach my $file (split(/\n/, `find . -name \\*.spec`)) {
+	my $type = 'winapi'->get_spec_file_type($file);
+	if($type eq "win16") {
+	    $win16api->parse_spec_file($file);
+	} elsif($type eq "win32") {
+	    $win32api->parse_spec_file($file);
+	}
+    }
+}
+
+sub parse_spec_file {
+    my $self = shift;
+    my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}};
+    my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+    my $function_stub = \%{$self->{FUNCTION_STUB}};
+    my $function_module = \%{$self->{FUNCTION_MODULE}};
+
+    my $file = shift;
+    
+    my $type;
+    my $module;
+
+    open(IN, "< $file") || die "$file: $!\n";
+    $/ = "\n";
+    my $header = 1;
+    my $lookahead = 0;
+    while($lookahead || defined($_ = <IN>)) {
+	$lookahead = 0;
+	s/^\s*(.*?)\s*$/$1/;
+	s/^(.*?)\s*#.*$/$1/;
+	/^$/ && next;
+
+	if($header)  {
+	    if(/^name\s*(\S*)/) { $module = $1; }
+	    if(/^\d+/) { $header = 0 };
+	    next;
+	} 
+
+	if(/^\d+\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) {
+	    my $calling_convention = $1;
+	    my $external_name = $2;
+	    my $arguments = $3;
+	    my $internal_name = $4;
+
+	    # FIXME: Internal name existing more than once not handled properly
+	    $$function_arguments{$internal_name} = $arguments;
+	    $$function_calling_convention{$internal_name} = $calling_convention;
+	    $$function_module{$internal_name} = $module;
+	} elsif(/^\d+\s+stub\s+(\S+)$/) {
+	    my $external_name = $1;
+	    $$function_stub{$external_name} = 1;
+	    $$function_module{$external_name} = $module;
+	} elsif(/^\d+\s+(equate|long|word|extern|forward)/) {
+	    # ignore
+	} else {
+	    my $next_line = <IN>;
+	    if($next_line =~ /^\d/) {
+		die "$file: $.: syntax error: '$_'\n";
+	    } else {
+		$_ .= $next_line;
+		$lookahead = 1;
+	    }
+	}
+    }
+    close(IN);
+}
+
+sub name {
+    my $self = shift;
+    return $self->{NAME};
+}
+
+sub is_allowed_kind {
+    my $self = shift;
+    my $allowed_kind = \%{$self->{ALLOWED_KIND}};
+
+    my $kind = shift;
+    if(defined($kind)) {
+	return $$allowed_kind{$kind};
+    } else {
+	return 0;
+    }
+}
+
+sub allowed_type_in_module {
+    my $self = shift;
+    my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
+    my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
+
+    my $type = shift;
+    my $module = shift;
+
+    return !$$allowed_modules_limited{$type} || $$allowed_modules{$type}{$module};
+}
+
+sub translate_argument {
+    my $self = shift;
+    my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
+
+    my $argument = shift;
+
+    return $$translate_argument{$argument};
+}
+
+sub all_declared_types {
+    my $self = shift;
+    my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
+
+    return sort(keys(%$translate_argument));
+}
+
+sub found_type {
+    my $self = shift;
+    my $type_found = \%{$self->{TYPE_FOUND}};
+
+    my $name = shift;
+
+    $$type_found{$name}++;
+}
+
+sub type_found {
+    my $self = shift;
+    my $type_found= \%{$self->{TYPE_FOUND}};
+
+    my $name = shift;
+
+    return $$type_found{$name};
+}
+
+sub all_functions {
+    my $self = shift;
+    my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+
+    return sort(keys(%$function_calling_convention));
+}
+
+sub all_functions_found {
+    my $self = shift;
+    my $function_found = \$self->{FUNCTION_FOUND};
+
+    return sort(keys(%$function_found));
+}
+
+sub function_calling_convention {
+    my $self = shift;
+    my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+
+    my $name = shift;
+
+    return $$function_calling_convention{$name};
+}
+
+sub is_function {
+    my $self = shift;
+    my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+
+    my $name = shift;
+
+    return $$function_calling_convention{$name};
+}
+
+sub is_shared_function {
+    my $self = shift;
+    my $function_shared = \%{$self->{FUNCTION_SHARED}};
+
+    my $name = shift;
+
+    return $$function_shared{$name};
+}
+
+sub found_shared_function {
+    my $self = shift;
+    my $function_shared = \%{$self->{FUNCTION_SHARED}};
+
+    my $name = shift;
+
+    $$function_shared{$name} = 1;
+}
+
+sub function_arguments {
+    my $self = shift;
+    my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}};
+
+    my $name = shift;
+
+    return $$function_arguments{$name};
+}
+
+sub function_module {
+    my $self = shift;
+    my $function_module = \%{$self->{FUNCTION_MODULE}};
+
+    my $name = shift;
+
+    if($self->is_function($name)) { 
+	return $$function_module{$name};
+    } else {
+	return undef;
+    }
+}
+
+sub function_stub {
+    my $self = shift;
+    my $function_stub = \%{$self->{FUNCTION_STUB}};
+
+    my $name = shift;
+
+    return $$function_stub{$name};
+}
+
+sub found_function {
+    my $self = shift;
+    my $function_found = \%{$self->{FUNCTION_FOUND}};
+
+    my $name = shift;
+
+    $$function_found{$name}++;
+}
+
+sub function_found {
+    my $self = shift;
+    my $function_found = \%{$self->{FUNCTION_FOUND}};
+
+    my $name = shift;
+
+    return $$function_found{$name};
+}
+
+1;
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
new file mode 100755
index 0000000..1323685
--- /dev/null
+++ b/tools/winapi_check/winapi_check
@@ -0,0 +1,118 @@
+#!/usr/bin/perl -w
+
+# Copyright 1999 Patrik Stridvall
+
+use strict;
+
+BEGIN {
+    require "tools/winapi_check/winapi.pm";
+    require "tools/winapi_check/nativeapi.pm";
+    require "tools/winapi_check/winapi_local.pm";
+    require "tools/winapi_check/winapi_global.pm";
+    require "tools/winapi_check/winapi_options.pm";
+    require "tools/winapi_check/winapi_parser.pm";
+
+    import winapi;
+    import nativeapi;
+    import winapi_local;
+    import winapi_global;
+    import winapi_options;
+    import winapi_parser;
+}
+
+my $options = winapi_options->new(\@ARGV);
+if($options->help) {
+    $options->show_help;
+    exit;
+}
+
+my $win16api = 'winapi'->new("win16", "tools/winapi_check/win16api.dat");
+my $win32api = 'winapi'->new("win32", "tools/winapi_check/win32api.dat");
+'winapi'->read_spec_files($win16api, $win32api);
+
+my $nativeapi = 'nativeapi'->new("tools/winapi_check/nativeapi.dat");
+
+for my $name ($win32api->all_functions) {
+    my $module16 = $win16api->function_module($name);
+    my $module32 = $win32api->function_module($name);
+	
+    if(defined($module16)) {
+	$win16api->found_shared_function($name);
+	$win32api->found_shared_function($name);
+	
+	if($options->shared) {
+	    print "*.spec: $name: is shared between $module16 (Win16) and $module32 (Win32)\n";
+	}
+    }
+}
+
+foreach my $file ($options->files) {
+    my $found_function = sub {
+	my $return_type = shift;
+	my $calling_convention = shift;
+	my $name = shift;
+	my $refarguments = shift;
+	my @arguments = @$refarguments;
+
+	if($options->global) {
+	    $win16api->found_type($return_type) if $options->win16;
+	    $win32api->found_type($return_type) if $options->win32;
+	    for my $argument (@arguments) {
+		$win16api->found_type($argument) if $options->win16;
+		$win32api->found_type($argument) if $options->win32;
+	    }
+	    
+	    $win16api->found_function($name) if $options->win16;
+	    $win32api->found_function($name) if $options->win32;
+	}
+	
+	if($options->local) {
+	    my $module16 = $win16api->function_module($name);
+	    my $module32 = $win32api->function_module($name);
+	    my $output = sub { 
+		my $module = shift;
+		return sub {
+		    my $msg = shift;
+		    print "$file: $module: $return_type $calling_convention $name(" . join(",", @arguments) . "): $msg\n";
+		}
+	    };
+	    my $output16 = &$output($module16);
+	    my $output32 = &$output($module32);
+	    
+	    if($options->argument) {
+		if($options->win16 && $options->report_module($module16)) {
+		  winapi_local::check_arguments $options, $output16,
+		    $return_type, $calling_convention, $name, [@arguments], $win16api;
+		}	
+		if($options->win32 && $options->report_module($module32)) {
+		  winapi_local::check_arguments $options, $output32,
+		    $return_type, $calling_convention, $name, [@arguments], $win32api;
+		}
+	    }
+	    if($options->misplaced) {
+		my $module; 
+		if($file =~ m'^dlls/(.*)/') {
+		    $module = $1;
+		}
+
+		if($options->win16 && $options->report_module($module16)) {
+		    if(!defined($module) || $module ne $module16) {
+			&$output16("function misplaced");
+		    }
+		}
+		
+		if($options->win32 && $options->report_module($module32)) {
+		    if(!defined($module) || $module ne $module32) {
+			&$output32("function misplaced");
+		    }
+		}		
+	    }
+	}
+    };   
+  winapi_parser::parse_c_file $options, $file, $found_function;
+}
+
+if($options->global) {
+    winapi_global::check $options, $win16api, $nativeapi if $options->win16;
+    winapi_global::check $options, $win32api, $nativeapi if $options->win32;
+}
diff --git a/tools/winapi_check/winapi_global.pm b/tools/winapi_check/winapi_global.pm
new file mode 100644
index 0000000..0c4322d
--- /dev/null
+++ b/tools/winapi_check/winapi_global.pm
@@ -0,0 +1,41 @@
+package winapi_global;
+
+use strict;
+ 
+sub check {
+    my $options = shift;
+    my $winapi = shift;
+    my $nativeapi = shift;
+
+    my $winver = $winapi->name;
+
+    if($options->argument) {
+	foreach my $type ($winapi->all_declared_types) {
+	    if(!$winapi->type_found($type) && $type ne "CONTEXT86 *") {
+		print "*.c: $winver: $type: ";
+		print "type not used\n";
+	    }
+	}
+    }
+
+    if($options->declared) {
+	foreach my $name ($winapi->all_functions) {
+	    if(!$winapi->function_found($name) && !$nativeapi->is_function($name)) {
+		print "*.c: $winver: $name: ";
+		print "function declared but not implemented: " . $winapi->function_arguments($name) . "\n";
+	    }
+	}
+    }
+
+    if($options->implemented) {
+	foreach my $name ($winapi->all_functions_found) {
+	    if($winapi->function_stub($name)) {
+		print "*.c: $winver: $name: ";
+		print "function implemented but not declared\n";
+	    }
+	}
+    }
+}
+
+1;
+
diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm
new file mode 100644
index 0000000..88126bb
--- /dev/null
+++ b/tools/winapi_check/winapi_local.pm
@@ -0,0 +1,136 @@
+package winapi_local;
+
+use strict;
+
+sub check_arguments {
+    my $options = shift;
+    my $output = shift;
+    my $return_type = shift;
+    my $calling_convention = shift;
+    my $name = shift;
+    my $refargument_types = shift;
+    my @argument_types = @$refargument_types;
+    my $winapi = shift;
+
+    my $module = $winapi->function_module($name);
+
+    my $forbidden_return_type = 0;
+    my $implemented_return_kind;
+    if(!defined($implemented_return_kind = $winapi->translate_argument($return_type))) {
+	if($return_type ne "") {
+	    &$output("no translation defined: " . $return_type);
+	}
+    } elsif(!$winapi->is_allowed_kind($implemented_return_kind) || !$winapi->allowed_type_in_module($return_type,$module)) {
+	$forbidden_return_type = 1;
+	if($options->report_argument_forbidden($return_type)) {
+	    &$output("forbidden return type: $return_type ($implemented_return_kind)");
+	}
+    }
+    
+    my $segmented = 0;
+    if($implemented_return_kind =~ /^segptr|segstr$/) {
+	$segmented = 1;
+    }
+
+    my $implemented_calling_convention;
+    if($winapi->name eq "win16") {
+	if($calling_convention =~ /^__cdecl$/) {
+	    $implemented_calling_convention = "cdecl";
+	} elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) {
+	    if($implemented_return_kind =~ /^s_word|word|void$/) {
+		$implemented_calling_convention = "pascal16";
+	    } else {
+		$implemented_calling_convention = "pascal";
+	    }
+	}
+    } elsif($winapi->name eq "win32") {
+	if($calling_convention =~ /^__cdecl$/) {
+	    $implemented_calling_convention = "cdecl";
+	} elsif($calling_convention =~ /^VFWAPIV|WINAPIV$/) {
+	    $implemented_calling_convention = "varargs";
+	} elsif($calling_convention = ~ /^__stdcall|VFWAPI|WINAPI$/) {
+	    $implemented_calling_convention = "stdcall";
+	}
+    }
+
+    my $declared_calling_convention = $winapi->function_calling_convention($name);
+    my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($name));
+
+    if($declared_calling_convention =~ /^register|interrupt$/) {
+	push @declared_argument_kinds, "ptr";
+    }
+   
+    if($declared_calling_convention =~ /^register|interupt$/ && 
+         (($winapi->name eq "win32" && $implemented_calling_convention eq "stdcall") ||
+         (($winapi->name eq "win16" && $implemented_calling_convention =~ /^pascal/))))
+    {
+	# correct
+    } elsif($implemented_calling_convention ne $declared_calling_convention && 
+       !($declared_calling_convention =~ /^pascal/ && $forbidden_return_type)) 
+    {
+	if($options->calling_convention) {
+	    &$output("calling convention mismatch: $implemented_calling_convention != $declared_calling_convention");
+	}
+    }
+
+    if($declared_calling_convention eq "varargs") {
+	if($#argument_types != -1 && $argument_types[$#argument_types] eq "...") {
+	    pop @argument_types;
+	} else {
+	    &$output("function not implemented as vararg");
+	}
+    } elsif($#argument_types != -1 && $argument_types[$#argument_types] eq "...") {
+	&$output("function not declared as vararg");
+    }
+	
+    if($name =~ /^CRTDLL__ftol|CRTDLL__CIpow$/) {
+	# ignore
+    } elsif($#argument_types != $#declared_argument_kinds) {
+	if($options->argument_count) {
+	    &$output("argument count differs: " . ($#argument_types + 1) . " != " . ($#declared_argument_kinds + 1));
+	}
+    } else {
+	my $n = 0;
+	my @argument_kinds = map {
+	    my $type = $_;
+	    my $kind = "unknown";
+	    if(!defined($kind = $winapi->translate_argument($type))) {
+		&$output("no translation defined: " . $type);
+	    } elsif(!$winapi->is_allowed_kind($kind) ||
+		    !$winapi->allowed_type_in_module($type, $module)) {
+		if($options->report_argument_forbidden($type)) {
+		    &$output("forbidden argument " . ($n + 1) . " type (" . $type . ")");
+		}
+	    }
+	    $n++;
+	    $kind;
+	} @argument_types;
+
+	for my $n (0..$#argument_kinds) {
+	    if(!defined($argument_kinds[$n]) || !defined($declared_argument_kinds[$n])) { next; }
+
+	    if($argument_kinds[$n] =~ /^segptr|segstr$/ ||
+	       $declared_argument_kinds[$n] =~ /^segptr|segstr$/)
+	    {
+		$segmented = 1;
+	    }
+
+	    if($argument_kinds[$n] ne $declared_argument_kinds[$n]) {
+		if($options->report_argument_kind($argument_kinds[$n]) ||
+		   $options->report_argument_kind($declared_argument_kinds[$n]))
+		{
+		    &$output("argument " . ($n + 1) . " type mismatch: " .
+			     $argument_types[$n] . " ($argument_kinds[$n]) != " . $declared_argument_kinds[$n]);
+		}
+	    }
+
+	}
+    }
+
+    if($segmented && $options->shared_segmented && $winapi->is_shared_function($name)) {
+	&$output("function using segmented pointers shared between Win16 och Win32");
+    }
+}
+
+1;
+
diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm
new file mode 100644
index 0000000..efadd5b
--- /dev/null
+++ b/tools/winapi_check/winapi_options.pm
@@ -0,0 +1,272 @@
+package winapi_options;
+
+use strict;
+
+
+sub parser_comma_list {
+    my $prefix = shift;
+    my $value = shift;
+    if(defined($prefix) && $prefix eq "no") {
+	return { active => 0, filter => 0, hash => {} };
+    } elsif(defined($value)) {
+	my %names;
+	for my $name (split /,/, $value) {
+	    $names{$name} = 1;
+	}
+	return { active => 1, filter => 1, hash => \%names };
+    } else {
+	return { active => 1, filter => 0, hash => {} };
+    }
+}
+
+my %options = (
+    "debug" => { default => 0, description => "debug mode" },
+    "help" => { default => 0, description => "help mode" },
+    "verbose" => { default => 0, description => "verbose mode" },
+
+    "win16" => { default => 1, description => "Win16 checking" },
+    "win32" => { default => 1, description => "Win32 checking" },
+
+    "shared" =>  { default => 0, description => "show shared functions between Win16 and Win32" },
+    "shared-segmented" =>  { default => 0, description => "segmented shared functions between Win16 and Win32 checking" },
+
+    "local" =>  { default => 1, description => "local checking" },
+    "module" => { 
+	default => { active => 1, filter => 0, hash => {} },
+	parent => "local",
+	parser => \&parser_comma_list,
+	description => "module filter"
+    },
+
+    "argument" => { default => 1, parent => "local", description => "argument checking" },
+    "argument-count" => { default => 1, parent => "argument", description => "argument count checking" },
+    "argument-forbidden" => {
+	default => { active => 0, filter => 0, hash => {} },
+	parent => "argument",
+	parser => \&parser_comma_list,
+	description => "argument forbidden checking"
+    },
+    "argument-kind" => {
+	default => { active => 0, filter => 0, hash => {} },
+	parent => "argument",
+	parser => \&parser_comma_list,
+	description => "argument kind checking"
+    },
+    "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" },
+    "misplaced" => { default => 0, parent => "local", description => "checking for misplaced functions" },
+             
+    "global" => { default => 1, description => "global checking" }, 
+    "declared" => { default => 1, parent => "global", description => "declared checking" }, 
+    "implemented" => { default => 0, parent => "global", description => "implemented checking" }
+
+);
+
+my %short_options = (
+    "d" => "debug",
+    "?" => "help",
+    "v" => "verbose"
+);
+
+sub new {
+    my $proto = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = {};
+    bless ($self, $class);
+
+    my $refarguments = shift;
+    my @ARGV = @$refarguments;
+
+    for my $name (sort(keys(%options))) {
+        my $option = $options{$name};
+	my $key = uc($name);
+	$key =~ tr/-/_/;
+	$$option{key} = $key;
+	my $refvalue = \${$self->{$key}};
+	$$refvalue = $$option{default};
+    }
+
+    my $files = \@{$self->{FILES}};
+    my $module = \${$self->{MODULE}};
+    my $global = \${$self->{GLOBAL}};
+
+    while(defined($_ = shift @ARGV)) {
+	if(/^-([^=]*)(=(.*))?$/) {
+	    my $name;
+	    my $value;
+	    if(defined($2)) {
+		$name = $1;
+		$value = $3;
+            } else {
+		$name = $1;
+	    }
+	    
+	    if($name =~ /^([^-].*)$/) {
+		$name = $short_options{$1};
+	    } else {
+		$name =~ s/^-(.*)$/$1/;
+	    }
+	    	   
+	    my $prefix;
+	    if($name =~ /^no-(.*)$/) {
+		$name = $1;
+		$prefix = "no";
+		if(defined($value)) {
+		    print STDERR "<internal>: options with prefix 'no' can't take parameters\n";
+		    exit 1;
+		}
+	    }
+
+	    my $option = $options{$name};
+	    if(defined($option)) {
+		my $key = $$option{key};
+		my $parser = $$option{parser};
+		my $refvalue = \${$self->{$key}};
+	      	       
+		if(defined($parser)) { 
+		    $$refvalue = &$parser($prefix,$value);
+		} else {
+		    if(defined($value)) {
+			$$refvalue = $value;
+		    } elsif(!defined($prefix)) {
+			$$refvalue = 1;
+		    } else {
+			$$refvalue = 0;
+		    }
+		}
+		next;
+	    }	 
+	}
+	
+	if(/^--module-dlls$/) {
+	    my @dirs = `cd dlls && find ./ -type d ! -name CVS`;
+	    my %names;
+	    for my $dir (@dirs) {
+		chomp $dir;
+		$dir =~ s/^\.\/(.*)$/$1/;
+		next if $dir eq "";
+		$names{$dir} = 1;
+	    }
+	    $$module = { active => 1, filter => 1, hash => \%names };
+	}	
+	elsif(/^-(.*)$/) {
+	    print STDERR "<internal>: unknown option: $&\n"; 
+	    print STDERR "<internal>: usage: winapi-check [--help] [<files>]\n";
+	    exit 1;
+	} else {
+	    push @$files, $_;
+	}
+    }
+
+    if($#$files == -1) {
+	@$files = map {
+	    s/^.\/(.*)$/$1/;
+	    $_; 
+	} split(/\n/, `find . -name \\*.c`);
+    } else {
+	$$global = 0
+    }
+ 
+    return $self;
+}
+
+sub show_help {
+    my $self = shift;
+
+    my $maxname = 0;
+    for my $name (sort(keys(%options))) {
+	if(length($name) > $maxname) {
+	    $maxname = length($name);
+	}
+    }
+
+    print "usage: winapi-check [--help] [<files>]\n";
+    print "\n";
+    for my $name (sort(keys(%options))) {
+	my $option = $options{$name};
+        my $description = $$option{description};
+	my $default = $$option{default};
+	
+	my $output;
+	if(ref($default) ne "HASH") {
+	    if($default) {
+		$output = "--no-$name";
+	    } else {
+		$output = "--$name";
+	    }
+	} else {
+	    if($default->{active}) {
+		$output = "--[no-]$name\[=<value>]";
+	    } else {
+		$output = "--$name\[=<value>]";
+	    }
+	}
+
+	print "$output";
+	for (0..(($maxname - length($name) + 14) - (length($output) - length($name) + 1))) { print " "; }
+	if(ref($default) ne "HASH") {
+	    if($default) {
+		print "Disable $description\n";
+	    } else {
+		print "Enable $description\n";
+	    }    
+	} else {
+	    if($default->{active}) {
+		print "(Disable) $description\n";
+	    } else {
+		print "Enable $description\n";
+	    }
+
+
+	}
+    }
+}
+
+sub AUTOLOAD {
+    my $self = shift;
+
+    my $name = $winapi_options::AUTOLOAD;
+    $name =~ s/^.*::(.[^:]*)$/\U$1/;
+
+    my $refvalue = $self->{$name};
+    if(!defined($refvalue)) {
+	die "<internal>: winapi_options.pm: member $name does not exists\n"; 
+    }
+    return $$refvalue;
+}
+
+sub files { my $self = shift; return @{$self->{FILES}}; }
+
+sub report_module {
+    my $self = shift;
+    my $module = $self->module;
+    
+    my $name = shift;
+
+    if(defined($name)) {
+	return $module->{active} && (!$module->{filter} || $module->{hash}->{$name}); 
+    } else {
+	return 0;
+    } 
+}
+
+sub report_argument_forbidden {
+    my $self = shift;   
+    my $argument_forbidden = $self->argument_forbidden;
+
+    my $type = shift;
+
+    return $argument_forbidden->{active} && (!$argument_forbidden->{filter} || $argument_forbidden->{hash}->{$type}); 
+}
+
+sub report_argument_kind {
+    my $self = shift;
+    my $argument_kind = $self->argument_kind;
+
+    my $kind = shift;
+
+    return $argument_kind->{active} && (!$argument_kind->{filter} || $argument_kind->{hash}->{$kind}); 
+
+}
+
+1;
+
diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm
new file mode 100644
index 0000000..7e331a5
--- /dev/null
+++ b/tools/winapi_check/winapi_parser.pm
@@ -0,0 +1,161 @@
+package winapi_parser;
+
+use strict;
+
+sub parse_c_file {
+    my $options = shift;
+    my $file = shift;
+    my $function_found_callback = shift;
+
+    my $level = 0;
+    my $again = 0;
+    my $lookahead = 0;
+    my $lookahead_count = 0;
+
+    print STDERR "Processing file '$file' ... " if $options->verbose;
+    open(IN, "< $file") || die "<internal>: $file: $!\n";
+    $/ = "\n";
+    while($again || defined(my $line = <IN>)) {
+	if(!$again) {
+	    chomp $line;
+
+	    if($lookahead) {
+		$lookahead = 0;
+		$_ .= "\n" . $line;
+	    } else {
+		$_ = $line;
+		$lookahead_count = 0;
+	    }
+	    $lookahead_count++;
+	    print "$level: $line\n" if $options->debug >= 2;
+	} else {
+	    $lookahead_count = 0;
+	    $again = 0;
+	}
+       
+	# remove comments
+	if(s/^(.*?)\/\*.*?\*\/(.*)$/$1 $2/s) { $again = 1; next };
+	if(/^(.*?)\/\*/s) {
+	    $lookahead = 1;
+	    next;
+	}
+
+	# remove empty rows
+	if(/^\s*$/) { next; }
+
+	# remove preprocessor directives
+	if(s/^\s*\#.*$//m) { $again = 1; next; }
+
+	if($level > 0)
+	{
+	    s/^[^\{\}]*//s;
+	    if(/^\{/) {
+		$_ = $'; $again = 1;
+		print "+1: $_\n" if $options->debug >= 2;
+		$level++;
+	    } elsif(/^\}/) {
+		$_ = $'; $again = 1;
+		print "-1: $_\n" if $options->debug >= 2; 
+		$level--;
+	    }
+	    next;
+	} elsif(/((struct\s+|union\s+|enum\s+)?\w+((\s*\*)+\s*|\s+))(__cdecl|__stdcall|VFWAPIV|VFWAPI|WINAPIV|WINAPI)\s+(\w+(\(\w+\))?)\s*\(([^\)]*)\)\s*(\{|\;)/s) {
+	    $_ = $'; $again = 1;
+
+	    if($9 eq ";") {
+		next;
+	    } elsif($9 eq "{")  {		
+		$level++;
+	    }
+
+	    my $return_type = $1;
+	    my $calling_convention = $5;
+	    my $name = $6;
+	    my $arguments = $8;
+
+	    $return_type =~ s/\s*$//;
+	    $return_type =~ s/\s*\*\s*/*/g;
+	    $return_type =~ s/(\*+)/ $1/g;
+
+	    $name =~ s/^REGS_FUNC\((.*?)\)/$1/;
+
+	    $arguments =~ y/\t\n/  /;
+	    $arguments =~ s/^\s*(.*?)\s*$/$1/;
+	    if($arguments eq "") { $arguments = "void" }
+	    
+	    my @arguments = split(/,/, $arguments);
+	    foreach my $n (0..$#arguments) {
+		my $argument = $arguments[$n];
+		$argument =~ s/^\s*(.*?)\s*$/$1/;
+		#print "  " . ($n + 1) . ": '$argument'\n";
+		$argument =~ s/^(const(?=\s)|IN(?=\s)|OUT(?=\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";
+		    }
+		} else {
+		    die "$file: $.: syntax error: '$argument'\n";
+		}
+		$arguments[$n] = $argument;
+		#print "  " . ($n + 1) . ": '" . $arguments[$n] . "'\n";
+	    }
+	    if($#arguments == 0 && $arguments[0] =~ /^void$/i) { $#arguments = -1;  } 
+
+	    if($options->debug) {
+		print "$file: $return_type $calling_convention $name(" . join(",", @arguments) . ")\n";
+	    }
+	    &$function_found_callback($return_type,$calling_convention,$name,\@arguments);
+
+	} elsif(/DC_(GET_X_Y|GET_VAL_16)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
+	    $_ = $'; $again = 1;
+	    my @arguments = ("HDC16");
+	    &$function_found_callback($2, "WINAPI", $3, \@arguments);
+	} elsif(/DC_(GET_VAL_32)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,.*?\)/s) {
+	    $_ = $'; $again = 1;
+	    my @arguments = ("HDC");
+	    &$function_found_callback($2, "WINAPI", $3, \@arguments);
+	} elsif(/DC_(GET_VAL_EX)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
+	    $_ = $'; $again = 1;
+	    my @arguments16 = ("HDC16", "LP" . $5 . "16");
+	    my @arguments32 = ("HDC", "LP" . $5);
+	    &$function_found_callback("BOOL16", "WINAPI", $2 . "16", \@arguments16);
+	    &$function_found_callback("BOOL", "WINAPI", $2, \@arguments32);
+	} elsif(/DC_(SET_MODE)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
+	    $_ = $'; $again = 1;
+	    my @arguments16 = ("HDC16", "INT16");
+	    my @arguments32 = ("HDC", "INT");
+	    &$function_found_callback("INT16", "WINAPI", $2 . "16", \@arguments16);
+	    &$function_found_callback("INT", "WINAPI", $2, \@arguments32);
+	} elsif(/WAVEOUT_SHORTCUT_(1|2)\s*\(\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*\)/s) {
+	    $_ = $'; $again = 1;
+	    print "$_";
+	    if($1 eq "1") {
+		my @arguments16 = ("HWAVEOUT16", $4);
+		my @arguments32 = ("HWAVEOUT", $4);
+		&$function_found_callback("UINT16", "WINAPI", "waveOut" . $2 . "16", \@arguments16);
+		&$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32);
+	    } elsif($1 eq 2) {
+		my @arguments16 = ("UINT16", $4);
+		my @arguments32 = ("UINT", $4);
+		&$function_found_callback("UINT16", "WINAPI", "waveOut". $2 . "16", \@arguments16);
+		&$function_found_callback("UINT", "WINAPI", "waveOut" . $2, \@arguments32)
+	    }
+	} elsif(/;/s) {
+	    $_ = $'; $again = 1;
+	} elsif(/\{/s) {
+	    $_ = $'; $again = 1;
+	    print "+1: $_\n" if $options->debug >= 2;
+	    $level++;
+        } else {
+	    $lookahead = 1;
+	}
+    }
+    close(IN);
+    print STDERR "done\n" if $options->verbose;
+    print "$file: <>: not at toplevel at end of file\n" unless $level == 0;
+}
+
+1;