This commit was manufactured by cvs2svn to create branch 'captive'.
authorjankratochvil <>
Wed, 12 Feb 2003 22:32:56 +0000 (22:32 +0000)
committerjankratochvil <>
Wed, 12 Feb 2003 22:32:56 +0000 (22:32 +0000)
Cherrypick from master 2003-02-12 22:32:54 UTC short 'update for HEAD-2003021201':
    apps/tests/Makefile
    apps/tests/alive/.cvsignore
    apps/tests/apc/.cvsignore
    apps/tests/args/.cvsignore
    apps/tests/atomtest/.cvsignore
    apps/tests/bench/.cvsignore
    apps/tests/bitblt/.cvsignore
    apps/tests/consume/.cvsignore
    apps/tests/copymove/.cvsignore
    apps/tests/copymove/Makefile
    apps/tests/copymove/copymove.c
    apps/tests/count/.cvsignore
    apps/tests/dibtest/.cvsignore
    apps/tests/dump_shared_data/.cvsignore
    apps/tests/event/.cvsignore
    apps/tests/file/.cvsignore
    apps/tests/gditest/.cvsignore
    apps/tests/hello/.cvsignore
    apps/tests/hivetest/.cvsignore
    apps/tests/hivetest/hivetest.c
    apps/tests/hivetest/makefile
    apps/tests/isotest/.cvsignore
    apps/tests/lock/Makefile
    apps/tests/lock/lock.c
    apps/tests/lpc/.cvsignore
    apps/tests/mstest/.cvsignore
    apps/tests/mutex/.cvsignore
    apps/tests/nptest/.cvsignore
    apps/tests/pteb/.cvsignore
    apps/tests/regdump/main.c
    apps/tests/regdump/regcmds.c
    apps/tests/regdump/regdump.h
    apps/tests/regdump/regproc.c
    apps/tests/regdump/regproc.h
    apps/tests/regtest/.cvsignore
    apps/tests/sectest/.cvsignore
    apps/tests/sertest/.cvsignore
    apps/tests/shm/.cvsignore
    apps/tests/simple/.cvsignore
    apps/tests/tests/GetSysMetrics/.cvsignore
    apps/tests/tests/GetSystemInfo/.cvsignore
    apps/tests/tests/Mutex/.cvsignore
    apps/tests/tests/Parent_Child/.cvsignore
    apps/tests/tests/guitest/.cvsignore
    apps/tests/tests/hello/.cvsignore
    apps/tests/tests/hello2/.cvsignore
    apps/tests/tests/new/.cvsignore
    apps/tests/tests/rolex/.cvsignore
    apps/tests/tests/volinfo/.cvsignore
    apps/tests/thread/.cvsignore
    apps/tests/tokentest/.cvsignore
    apps/tests/vmtest/.cvsignore
    apps/tests/winhello/.cvsignore
    apps/tests/wm_paint/Listing1_1.cpp
    apps/tests/wm_paint/makefile
    apps/testsets/Makefile
    apps/testsets/loadlib/.cvsignore
    apps/testsets/loadlib/loadlib.c
    apps/testsets/loadlib/loadlib.h
    apps/testsets/loadlib/makefile
    apps/testsets/msvcrt/fileio/.cvsignore
    apps/testsets/msvcrt/fileio/_tfileio.c
    apps/testsets/msvcrt/fileio/fileio.c
    apps/testsets/msvcrt/fileio/main.c
    apps/testsets/msvcrt/fileio/main.h
    apps/testsets/msvcrt/fileio/makefile
    apps/testsets/msvcrt/fileio/wfileio.c
    apps/utils/Makefile
    apps/utils/cabman/.cvsignore
    apps/utils/cat/.cvsignore
    apps/utils/net/roshttpd/.cvsignore
    apps/utils/net/telnet/.cvsignore
    apps/utils/objdir/.cvsignore
    apps/utils/partinfo/.cvsignore
    apps/utils/pice/.cvsignore
    apps/utils/ps/.cvsignore
    apps/utils/ps/ps.c
    apps/utils/sc/.cvsignore
    apps/utils/sc/command.c
    apps/utils/sc/config.c
    apps/utils/sc/main.c
    apps/utils/sc/main.h
    apps/utils/sc/makefile
    apps/utils/sc/query.c
    apps/utils/sc/setup.c
    apps/utils/stats/.cvsignore
    apps/utils/tickcount/makefile
    apps/utils/tickcount/tickcount.c
    drivers/bus/acpi/ospm/busmgr/.cvsignore
    drivers/bus/acpi/resource/.cvsignore
    drivers/dd/vga/display/main/.cvsignore
    drivers/dd/vga/display/objects/.cvsignore
    drivers/dd/vga/display/vgavideo/.cvsignore
    drivers/fs/fs_rec/udfs.c
    drivers/fs/vfat/flush.c
    drivers/lib/bzip2/.cvsignore
    drivers/net/afd/afd/.cvsignore
    drivers/net/dd/ne2000/ne2000/.cvsignore
    drivers/net/ndis/ndis/.cvsignore
    drivers/net/npf/.cvsignore
    drivers/net/npf/Makefile
    drivers/net/npf/bucket_lookup.c
    drivers/net/npf/bucket_lookup.h
    drivers/net/npf/count_packets.c
    drivers/net/npf/count_packets.h
    drivers/net/npf/debug.h
    drivers/net/npf/dump.c
    drivers/net/npf/functions.c
    drivers/net/npf/functions.h
    drivers/net/npf/jitter.c
    drivers/net/npf/jitter.h
    drivers/net/npf/memory_t.c
    drivers/net/npf/memory_t.h
    drivers/net/npf/normal_lookup.c
    drivers/net/npf/normal_lookup.h
    drivers/net/npf/npf.def
    drivers/net/npf/npf.edf
    drivers/net/npf/npf.rc
    drivers/net/npf/ntddpack.h
    drivers/net/npf/openclos.c
    drivers/net/npf/packet.c
    drivers/net/npf/packet.h
    drivers/net/npf/read.c
    drivers/net/npf/resource.h
    drivers/net/npf/tcp_session.c
    drivers/net/npf/tcp_session.h
    drivers/net/npf/time_calls.c
    drivers/net/npf/time_calls.h
    drivers/net/npf/tme.c
    drivers/net/npf/tme.h
    drivers/net/npf/valid_insns.h
    drivers/net/npf/win_bpf.h
    drivers/net/npf/win_bpf_filter.c
    drivers/net/npf/win_bpf_filter_init.c
    drivers/net/npf/win_bpf_filter_init.h
    drivers/net/npf/write.c
    drivers/net/tcpip/datalink/.cvsignore
    drivers/net/tcpip/include/linux.h
    drivers/net/tcpip/include/tcpcore.h
    drivers/net/tcpip/include/tcpdef.h
    drivers/net/tcpip/network/.cvsignore
    drivers/net/tcpip/tcpip/.cvsignore
    drivers/net/tcpip/transport/datagram/.cvsignore
    drivers/net/tcpip/transport/rawip/.cvsignore
    drivers/net/tcpip/transport/tcp/.cvsignore
    drivers/net/tcpip/transport/tcp/tcp_input.c
    drivers/net/tcpip/transport/tcp/tcp_ipv4.c
    drivers/net/tcpip/transport/tcp/tcp_output.c
    drivers/net/tcpip/transport/tcp/tcp_timer.c
    drivers/net/tcpip/transport/tcp/tcpcore.c
    drivers/net/tcpip/transport/udp/.cvsignore
    drivers/net/tdi/.cvsignore
    drivers/net/tdi/cte/.cvsignore
    drivers/net/tdi/tdi/.cvsignore
    include/basetsd.h
    include/ddk/af_irda.h
    include/msvcrt/crttypes.h
    include/ntos/ldrtypes.h
    include/ntos/rtl.h
    include/ntos/rtltypes.h
    include/ntos/zw.h
    include/ntos/zwtypes.h
    include/wine/commctrl.h
    lib/advapi32/misc/.cvsignore
    lib/advapi32/reg/.cvsignore
    lib/advapi32/sec/.cvsignore
    lib/advapi32/service/.cvsignore
    lib/advapi32/token/.cvsignore
    lib/crtdll/ctype/ctype.c
    lib/crtdll/misc/assert.c
    lib/crtdll/misc/debug.c
    lib/crtdll/stdio/fgetws.c
    lib/crtdll/stdio/fputws.c
    lib/crtdll/stdlib/alloca.c
    lib/crtdll/time/tz_vars.c
    lib/gdi32/main/.cvsignore
    lib/gdi32/objects/.cvsignore
    lib/kernel32/MSG00409.bin
    lib/kernel32/errcodes.rc
    lib/kernel32/errormsg.mak
    lib/kernel32/k32.h
    lib/kernel32/kernel32.mc
    lib/kernel32/misc/errormsg.c
    lib/kernel32/misc/getname.c
    lib/kernel32/misc/mbchars.c
    lib/kernel32/misc/muldiv.c
    lib/kernel32/misc/perfcnt.c
    lib/kernel32/misc/toolhelp.c
    lib/msafd/misc/.cvsignore
    lib/msvcrt/ctype/ctype.c
    lib/msvcrt/direct/wchdir.c
    lib/msvcrt/direct/wgetcwd.c
    lib/msvcrt/direct/wgetdcwd.c
    lib/msvcrt/direct/wmkdir.c
    lib/msvcrt/direct/wrmdir.c
    lib/msvcrt/io/fileleni.c
    lib/msvcrt/io/lseeki64.c
    lib/msvcrt/io/telli64.c
    lib/msvcrt/io/waccess.c
    lib/msvcrt/io/wchmod.c
    lib/msvcrt/io/wcreate.c
    lib/msvcrt/io/wfind.c
    lib/msvcrt/io/wmktemp.c
    lib/msvcrt/io/wopen.c
    lib/msvcrt/io/wunlink.c
    lib/msvcrt/io/wutime.c
    lib/msvcrt/math/math.c
    lib/msvcrt/misc/crtmain.c
    lib/msvcrt/misc/environ.c
    lib/msvcrt/process/threadx.c
    lib/msvcrt/stdio/fgetws.c
    lib/msvcrt/stdio/wfdopen.c
    lib/msvcrt/stdio/wrename.c
    lib/msvcrt/stdio/wtempnam.c
    lib/msvcrt/stdio/wtmpnam.c
    lib/msvcrt/stdlib/mbtowc.c
    lib/msvcrt/stdlib/wctomb.c
    lib/msvcrt/stdlib/wfulpath.c
    lib/msvcrt/stdlib/witoa.c
    lib/msvcrt/stdlib/witow.c
    lib/msvcrt/stdlib/wmakpath.c
    lib/msvcrt/stdlib/wputenv.c
    lib/msvcrt/stdlib/wsenv.c
    lib/msvcrt/stdlib/wsplitp.c
    lib/msvcrt/string/strncoll.c
    lib/msvcrt/sys_stat/fstati64.c
    lib/msvcrt/sys_stat/wstat.c
    lib/msvcrt/time/tz_vars.c
    lib/msvcrt/time/wctime.c
    lib/msvcrt/time/wstrdate.c
    lib/msvcrt/time/wstrtime.c
    lib/ntdll/ldr/res.c
    lib/ntdll/rtl/i386/.cvsignore
    lib/shell32/control/.cvsignore
    lib/shell32/control/makefile
    lib/version/misc/.cvsignore
    lib/winedbgc/.cvsignore
    lib/winedbgc/Makefile
    lib/winedbgc/debug.c
    lib/winedbgc/libmain.c
    lib/winedbgc/porting.c
    lib/winedbgc/porting.h
    lib/winedbgc/winedbgc.c
    lib/winedbgc/winedbgc.def
    lib/winedbgc/winedbgc.dll.dbg.c
    lib/winedbgc/winedbgc.edf
    lib/winedbgc/winedbgc.rc
    lib/winmm/misc/.cvsignore
    lib/ws2_32/misc/.cvsignore
    loaders/dos/.cvsignore
    ntoskrnl/dbg/profile.c
    ntoskrnl/rtl/math.c
    subsys/csrss/csrss.def
    subsys/csrss/csrss.edf
    subsys/system/usetup/bootsup.c
    subsys/system/usetup/bootsup.h
    subsys/system/usetup/filequeue.c
    subsys/system/usetup/filequeue.h
    subsys/system/usetup/filesup.c
    subsys/system/usetup/filesup.h
    subsys/system/usetup/inicache.c
    subsys/system/usetup/inicache.h
    subsys/system/usetup/progress.c
    subsys/system/usetup/progress.h
    subsys/win32k/ntuser/scrollbar.c
    tools/rtouch.c
    txtsetup.sif

267 files changed:
apps/tests/Makefile [new file with mode: 0644]
apps/tests/alive/.cvsignore [new file with mode: 0644]
apps/tests/apc/.cvsignore [new file with mode: 0644]
apps/tests/args/.cvsignore [new file with mode: 0644]
apps/tests/atomtest/.cvsignore [new file with mode: 0644]
apps/tests/bench/.cvsignore [new file with mode: 0644]
apps/tests/bitblt/.cvsignore [new file with mode: 0644]
apps/tests/consume/.cvsignore [new file with mode: 0644]
apps/tests/copymove/.cvsignore [new file with mode: 0644]
apps/tests/copymove/Makefile [new file with mode: 0644]
apps/tests/copymove/copymove.c [new file with mode: 0644]
apps/tests/count/.cvsignore [new file with mode: 0644]
apps/tests/dibtest/.cvsignore [new file with mode: 0644]
apps/tests/dump_shared_data/.cvsignore [new file with mode: 0644]
apps/tests/event/.cvsignore [new file with mode: 0644]
apps/tests/file/.cvsignore [new file with mode: 0644]
apps/tests/gditest/.cvsignore [new file with mode: 0644]
apps/tests/hello/.cvsignore [new file with mode: 0644]
apps/tests/hivetest/.cvsignore [new file with mode: 0644]
apps/tests/hivetest/hivetest.c [new file with mode: 0644]
apps/tests/hivetest/makefile [new file with mode: 0644]
apps/tests/isotest/.cvsignore [new file with mode: 0644]
apps/tests/lock/Makefile [new file with mode: 0644]
apps/tests/lock/lock.c [new file with mode: 0644]
apps/tests/lpc/.cvsignore [new file with mode: 0644]
apps/tests/mstest/.cvsignore [new file with mode: 0644]
apps/tests/mutex/.cvsignore [new file with mode: 0644]
apps/tests/nptest/.cvsignore [new file with mode: 0644]
apps/tests/pteb/.cvsignore [new file with mode: 0644]
apps/tests/regdump/main.c [new file with mode: 0644]
apps/tests/regdump/regcmds.c [new file with mode: 0644]
apps/tests/regdump/regdump.h [new file with mode: 0644]
apps/tests/regdump/regproc.c [new file with mode: 0644]
apps/tests/regdump/regproc.h [new file with mode: 0644]
apps/tests/regtest/.cvsignore [new file with mode: 0644]
apps/tests/sectest/.cvsignore [new file with mode: 0644]
apps/tests/sertest/.cvsignore [new file with mode: 0644]
apps/tests/shm/.cvsignore [new file with mode: 0644]
apps/tests/simple/.cvsignore [new file with mode: 0644]
apps/tests/tests/GetSysMetrics/.cvsignore [new file with mode: 0644]
apps/tests/tests/GetSystemInfo/.cvsignore [new file with mode: 0644]
apps/tests/tests/Mutex/.cvsignore [new file with mode: 0644]
apps/tests/tests/Parent_Child/.cvsignore [new file with mode: 0644]
apps/tests/tests/guitest/.cvsignore [new file with mode: 0644]
apps/tests/tests/hello/.cvsignore [new file with mode: 0644]
apps/tests/tests/hello2/.cvsignore [new file with mode: 0644]
apps/tests/tests/new/.cvsignore [new file with mode: 0644]
apps/tests/tests/rolex/.cvsignore [new file with mode: 0644]
apps/tests/tests/volinfo/.cvsignore [new file with mode: 0644]
apps/tests/thread/.cvsignore [new file with mode: 0644]
apps/tests/tokentest/.cvsignore [new file with mode: 0644]
apps/tests/vmtest/.cvsignore [new file with mode: 0644]
apps/tests/winhello/.cvsignore [new file with mode: 0644]
apps/tests/wm_paint/Listing1_1.cpp [new file with mode: 0644]
apps/tests/wm_paint/makefile [new file with mode: 0644]
apps/testsets/Makefile [new file with mode: 0644]
apps/testsets/loadlib/.cvsignore [new file with mode: 0644]
apps/testsets/loadlib/loadlib.c [new file with mode: 0644]
apps/testsets/loadlib/loadlib.h [new file with mode: 0644]
apps/testsets/loadlib/makefile [new file with mode: 0644]
apps/testsets/msvcrt/fileio/.cvsignore [new file with mode: 0644]
apps/testsets/msvcrt/fileio/_tfileio.c [new file with mode: 0644]
apps/testsets/msvcrt/fileio/fileio.c [new file with mode: 0644]
apps/testsets/msvcrt/fileio/main.c [new file with mode: 0644]
apps/testsets/msvcrt/fileio/main.h [new file with mode: 0644]
apps/testsets/msvcrt/fileio/makefile [new file with mode: 0644]
apps/testsets/msvcrt/fileio/wfileio.c [new file with mode: 0644]
apps/utils/Makefile [new file with mode: 0644]
apps/utils/cabman/.cvsignore [new file with mode: 0644]
apps/utils/cat/.cvsignore [new file with mode: 0644]
apps/utils/net/roshttpd/.cvsignore [new file with mode: 0644]
apps/utils/net/telnet/.cvsignore [new file with mode: 0644]
apps/utils/objdir/.cvsignore [new file with mode: 0644]
apps/utils/partinfo/.cvsignore [new file with mode: 0644]
apps/utils/pice/.cvsignore [new file with mode: 0644]
apps/utils/ps/.cvsignore [new file with mode: 0644]
apps/utils/ps/ps.c [new file with mode: 0644]
apps/utils/sc/.cvsignore [new file with mode: 0644]
apps/utils/sc/command.c [new file with mode: 0644]
apps/utils/sc/config.c [new file with mode: 0644]
apps/utils/sc/main.c [new file with mode: 0644]
apps/utils/sc/main.h [new file with mode: 0644]
apps/utils/sc/makefile [new file with mode: 0644]
apps/utils/sc/query.c [new file with mode: 0644]
apps/utils/sc/setup.c [new file with mode: 0644]
apps/utils/stats/.cvsignore [new file with mode: 0644]
apps/utils/tickcount/makefile [new file with mode: 0644]
apps/utils/tickcount/tickcount.c [new file with mode: 0644]
drivers/bus/acpi/ospm/busmgr/.cvsignore [new file with mode: 0644]
drivers/bus/acpi/resource/.cvsignore [new file with mode: 0644]
drivers/dd/vga/display/main/.cvsignore [new file with mode: 0644]
drivers/dd/vga/display/objects/.cvsignore [new file with mode: 0644]
drivers/dd/vga/display/vgavideo/.cvsignore [new file with mode: 0644]
drivers/fs/fs_rec/udfs.c [new file with mode: 0644]
drivers/fs/vfat/flush.c [new file with mode: 0644]
drivers/lib/bzip2/.cvsignore [new file with mode: 0644]
drivers/net/afd/afd/.cvsignore [new file with mode: 0644]
drivers/net/dd/ne2000/ne2000/.cvsignore [new file with mode: 0644]
drivers/net/ndis/ndis/.cvsignore [new file with mode: 0644]
drivers/net/npf/.cvsignore [new file with mode: 0644]
drivers/net/npf/Makefile [new file with mode: 0644]
drivers/net/npf/bucket_lookup.c [new file with mode: 0644]
drivers/net/npf/bucket_lookup.h [new file with mode: 0644]
drivers/net/npf/count_packets.c [new file with mode: 0644]
drivers/net/npf/count_packets.h [new file with mode: 0644]
drivers/net/npf/debug.h [new file with mode: 0644]
drivers/net/npf/dump.c [new file with mode: 0644]
drivers/net/npf/functions.c [new file with mode: 0644]
drivers/net/npf/functions.h [new file with mode: 0644]
drivers/net/npf/jitter.c [new file with mode: 0644]
drivers/net/npf/jitter.h [new file with mode: 0644]
drivers/net/npf/memory_t.c [new file with mode: 0644]
drivers/net/npf/memory_t.h [new file with mode: 0644]
drivers/net/npf/normal_lookup.c [new file with mode: 0644]
drivers/net/npf/normal_lookup.h [new file with mode: 0644]
drivers/net/npf/npf.def [new file with mode: 0644]
drivers/net/npf/npf.edf [new file with mode: 0644]
drivers/net/npf/npf.rc [new file with mode: 0644]
drivers/net/npf/ntddpack.h [new file with mode: 0644]
drivers/net/npf/openclos.c [new file with mode: 0644]
drivers/net/npf/packet.c [new file with mode: 0644]
drivers/net/npf/packet.h [new file with mode: 0644]
drivers/net/npf/read.c [new file with mode: 0644]
drivers/net/npf/resource.h [new file with mode: 0644]
drivers/net/npf/tcp_session.c [new file with mode: 0644]
drivers/net/npf/tcp_session.h [new file with mode: 0644]
drivers/net/npf/time_calls.c [new file with mode: 0644]
drivers/net/npf/time_calls.h [new file with mode: 0644]
drivers/net/npf/tme.c [new file with mode: 0644]
drivers/net/npf/tme.h [new file with mode: 0644]
drivers/net/npf/valid_insns.h [new file with mode: 0644]
drivers/net/npf/win_bpf.h [new file with mode: 0644]
drivers/net/npf/win_bpf_filter.c [new file with mode: 0644]
drivers/net/npf/win_bpf_filter_init.c [new file with mode: 0644]
drivers/net/npf/win_bpf_filter_init.h [new file with mode: 0644]
drivers/net/npf/write.c [new file with mode: 0644]
drivers/net/tcpip/datalink/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/include/linux.h [new file with mode: 0755]
drivers/net/tcpip/include/tcpcore.h [new file with mode: 0755]
drivers/net/tcpip/include/tcpdef.h [new file with mode: 0755]
drivers/net/tcpip/network/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/tcpip/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/transport/datagram/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/transport/rawip/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/transport/tcp/.cvsignore [new file with mode: 0644]
drivers/net/tcpip/transport/tcp/tcp_input.c [new file with mode: 0755]
drivers/net/tcpip/transport/tcp/tcp_ipv4.c [new file with mode: 0755]
drivers/net/tcpip/transport/tcp/tcp_output.c [new file with mode: 0755]
drivers/net/tcpip/transport/tcp/tcp_timer.c [new file with mode: 0755]
drivers/net/tcpip/transport/tcp/tcpcore.c [new file with mode: 0755]
drivers/net/tcpip/transport/udp/.cvsignore [new file with mode: 0644]
drivers/net/tdi/.cvsignore [new file with mode: 0644]
drivers/net/tdi/cte/.cvsignore [new file with mode: 0644]
drivers/net/tdi/tdi/.cvsignore [new file with mode: 0644]
include/basetsd.h [new file with mode: 0644]
include/ddk/af_irda.h [new file with mode: 0644]
include/msvcrt/crttypes.h [new file with mode: 0644]
include/ntos/ldrtypes.h [new file with mode: 0755]
include/ntos/rtl.h [new file with mode: 0755]
include/ntos/rtltypes.h [new file with mode: 0755]
include/ntos/zw.h [new file with mode: 0755]
include/ntos/zwtypes.h [new file with mode: 0755]
include/wine/commctrl.h [new file with mode: 0644]
lib/advapi32/misc/.cvsignore [new file with mode: 0644]
lib/advapi32/reg/.cvsignore [new file with mode: 0644]
lib/advapi32/sec/.cvsignore [new file with mode: 0644]
lib/advapi32/service/.cvsignore [new file with mode: 0644]
lib/advapi32/token/.cvsignore [new file with mode: 0644]
lib/crtdll/ctype/ctype.c [new file with mode: 0644]
lib/crtdll/misc/assert.c [new file with mode: 0644]
lib/crtdll/misc/debug.c [new file with mode: 0644]
lib/crtdll/stdio/fgetws.c [new file with mode: 0644]
lib/crtdll/stdio/fputws.c [new file with mode: 0644]
lib/crtdll/stdlib/alloca.c [new file with mode: 0644]
lib/crtdll/time/tz_vars.c [new file with mode: 0644]
lib/gdi32/main/.cvsignore [new file with mode: 0644]
lib/gdi32/objects/.cvsignore [new file with mode: 0644]
lib/kernel32/MSG00409.bin [new file with mode: 0644]
lib/kernel32/errcodes.rc [new file with mode: 0644]
lib/kernel32/errormsg.mak [new file with mode: 0644]
lib/kernel32/k32.h [new file with mode: 0755]
lib/kernel32/kernel32.mc [new file with mode: 0644]
lib/kernel32/misc/errormsg.c [new file with mode: 0644]
lib/kernel32/misc/getname.c [new file with mode: 0644]
lib/kernel32/misc/mbchars.c [new file with mode: 0644]
lib/kernel32/misc/muldiv.c [new file with mode: 0644]
lib/kernel32/misc/perfcnt.c [new file with mode: 0644]
lib/kernel32/misc/toolhelp.c [new file with mode: 0644]
lib/msafd/misc/.cvsignore [new file with mode: 0644]
lib/msvcrt/ctype/ctype.c [new file with mode: 0644]
lib/msvcrt/direct/wchdir.c [new file with mode: 0644]
lib/msvcrt/direct/wgetcwd.c [new file with mode: 0644]
lib/msvcrt/direct/wgetdcwd.c [new file with mode: 0644]
lib/msvcrt/direct/wmkdir.c [new file with mode: 0644]
lib/msvcrt/direct/wrmdir.c [new file with mode: 0644]
lib/msvcrt/io/fileleni.c [new file with mode: 0644]
lib/msvcrt/io/lseeki64.c [new file with mode: 0644]
lib/msvcrt/io/telli64.c [new file with mode: 0644]
lib/msvcrt/io/waccess.c [new file with mode: 0644]
lib/msvcrt/io/wchmod.c [new file with mode: 0644]
lib/msvcrt/io/wcreate.c [new file with mode: 0644]
lib/msvcrt/io/wfind.c [new file with mode: 0644]
lib/msvcrt/io/wmktemp.c [new file with mode: 0644]
lib/msvcrt/io/wopen.c [new file with mode: 0644]
lib/msvcrt/io/wunlink.c [new file with mode: 0644]
lib/msvcrt/io/wutime.c [new file with mode: 0644]
lib/msvcrt/math/math.c [new file with mode: 0644]
lib/msvcrt/misc/crtmain.c [new file with mode: 0644]
lib/msvcrt/misc/environ.c [new file with mode: 0644]
lib/msvcrt/process/threadx.c [new file with mode: 0644]
lib/msvcrt/stdio/fgetws.c [new file with mode: 0644]
lib/msvcrt/stdio/wfdopen.c [new file with mode: 0644]
lib/msvcrt/stdio/wrename.c [new file with mode: 0644]
lib/msvcrt/stdio/wtempnam.c [new file with mode: 0644]
lib/msvcrt/stdio/wtmpnam.c [new file with mode: 0644]
lib/msvcrt/stdlib/mbtowc.c [new file with mode: 0644]
lib/msvcrt/stdlib/wctomb.c [new file with mode: 0644]
lib/msvcrt/stdlib/wfulpath.c [new file with mode: 0644]
lib/msvcrt/stdlib/witoa.c [new file with mode: 0644]
lib/msvcrt/stdlib/witow.c [new file with mode: 0644]
lib/msvcrt/stdlib/wmakpath.c [new file with mode: 0644]
lib/msvcrt/stdlib/wputenv.c [new file with mode: 0644]
lib/msvcrt/stdlib/wsenv.c [new file with mode: 0644]
lib/msvcrt/stdlib/wsplitp.c [new file with mode: 0644]
lib/msvcrt/string/strncoll.c [new file with mode: 0644]
lib/msvcrt/sys_stat/fstati64.c [new file with mode: 0644]
lib/msvcrt/sys_stat/wstat.c [new file with mode: 0644]
lib/msvcrt/time/tz_vars.c [new file with mode: 0644]
lib/msvcrt/time/wctime.c [new file with mode: 0644]
lib/msvcrt/time/wstrdate.c [new file with mode: 0644]
lib/msvcrt/time/wstrtime.c [new file with mode: 0644]
lib/ntdll/ldr/res.c [new file with mode: 0644]
lib/ntdll/rtl/i386/.cvsignore [new file with mode: 0644]
lib/shell32/control/.cvsignore [new file with mode: 0644]
lib/shell32/control/makefile [new file with mode: 0644]
lib/version/misc/.cvsignore [new file with mode: 0644]
lib/winedbgc/.cvsignore [new file with mode: 0644]
lib/winedbgc/Makefile [new file with mode: 0644]
lib/winedbgc/debug.c [new file with mode: 0644]
lib/winedbgc/libmain.c [new file with mode: 0644]
lib/winedbgc/porting.c [new file with mode: 0644]
lib/winedbgc/porting.h [new file with mode: 0644]
lib/winedbgc/winedbgc.c [new file with mode: 0644]
lib/winedbgc/winedbgc.def [new file with mode: 0644]
lib/winedbgc/winedbgc.dll.dbg.c [new file with mode: 0644]
lib/winedbgc/winedbgc.edf [new file with mode: 0644]
lib/winedbgc/winedbgc.rc [new file with mode: 0644]
lib/winmm/misc/.cvsignore [new file with mode: 0644]
lib/ws2_32/misc/.cvsignore [new file with mode: 0644]
loaders/dos/.cvsignore [new file with mode: 0644]
ntoskrnl/dbg/profile.c [new file with mode: 0755]
ntoskrnl/rtl/math.c [new file with mode: 0644]
subsys/csrss/csrss.def [new file with mode: 0644]
subsys/csrss/csrss.edf [new file with mode: 0644]
subsys/system/usetup/bootsup.c [new file with mode: 0644]
subsys/system/usetup/bootsup.h [new file with mode: 0644]
subsys/system/usetup/filequeue.c [new file with mode: 0644]
subsys/system/usetup/filequeue.h [new file with mode: 0644]
subsys/system/usetup/filesup.c [new file with mode: 0644]
subsys/system/usetup/filesup.h [new file with mode: 0644]
subsys/system/usetup/inicache.c [new file with mode: 0644]
subsys/system/usetup/inicache.h [new file with mode: 0644]
subsys/system/usetup/progress.c [new file with mode: 0644]
subsys/system/usetup/progress.h [new file with mode: 0644]
subsys/win32k/ntuser/scrollbar.c [new file with mode: 0644]
tools/rtouch.c [new file with mode: 0755]
txtsetup.sif [new file with mode: 0644]

diff --git a/apps/tests/Makefile b/apps/tests/Makefile
new file mode 100644 (file)
index 0000000..f65539f
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# ReactOS test applications makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Test applications
+# alive apc args atomtest bench consume copymove count dump_shared_data
+# event file gditest hello isotest lpc mstest mutex nptest
+# pteb regtest sectest shm simple thread vmtest winhello
+TEST_APPS = alive apc args atomtest bench consume copymove count dump_shared_data \
+            event file gditest hello isotest lpc mstest mutex nptest \
+            pteb regtest sectest shm simple thread tokentest vmtest winhello dibtest \
+            lock hivetest
+
+TEST_MISC = 
+
+all: $(TEST_APPS) $(TEST_MISC)
+
+depends: 
+
+implib: $(TEST_APPS:%=%_implib) \
+       $(TEST_MISC:%=%_implib)
+
+clean:         $(TEST_APPS:%=%_clean) \
+       $(TEST_MISC:%=%_clean)
+
+install: $(TEST_APPS:%=%_install) \
+        $(TEST_MISC:%=%_install)
+
+dist:  $(TEST_APPS:%=%_dist) \
+       $(TEST_MISC:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Test Applications
+#
+$(TEST_APPS): %:
+       $(MAKE) -C $*
+
+$(TEST_APPS:%=%_implib): %_implib:
+       $(MAKE) -C $* implib
+
+$(TEST_APPS:%=%_clean): %_clean:
+       $(MAKE) -C $* clean
+
+$(TEST_APPS:%=%_dist): %_dist:
+       $(MAKE) -C $* dist
+
+$(TEST_APPS:%=%_install): %_install:
+       $(MAKE) -C $* install
+
+.PHONY: $(TEST_APPS) $(TEST_APPS:%=%_implib) $(TEST_APPS:%=%_clean) $(TEST_APPS:%=%_install) $(TEST_APPS:%=%_dist)
+
+
+#
+# Misc Test Applications
+#
+$(TEST_MISC): %:
+       $(MAKE) -C tests/$*
+
+$(TEST_MISC:%=%_implib): %_implib:
+       $(MAKE) -C tests/$* implib
+
+$(TEST_MISC:%=%_clean): %_clean:
+       $(MAKE) -C tests/$* clean
+
+$(TEST_MISC:%=%_dist): %_dist:
+       $(MAKE) -C tests/$* dist
+
+$(TEST_MISC:%=%_install): %_install:
+       $(MAKE) -C tests/$* install
+
+.PHONY: $(TEST_MISC) $(TEST_MISC:%=%_implib) $(TEST_MISC:%=%_clean) $(TEST_MISC:%=%_install) $(TEST_MISC:%=%_dist)
+
+
+etags:
+       find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
diff --git a/apps/tests/alive/.cvsignore b/apps/tests/alive/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/apc/.cvsignore b/apps/tests/apc/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/args/.cvsignore b/apps/tests/args/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/atomtest/.cvsignore b/apps/tests/atomtest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/bench/.cvsignore b/apps/tests/bench/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/bitblt/.cvsignore b/apps/tests/bitblt/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/consume/.cvsignore b/apps/tests/consume/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/copymove/.cvsignore b/apps/tests/copymove/.cvsignore
new file mode 100644 (file)
index 0000000..343a060
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.exe
+*.sym
diff --git a/apps/tests/copymove/Makefile b/apps/tests/copymove/Makefile
new file mode 100644 (file)
index 0000000..e8d825f
--- /dev/null
@@ -0,0 +1,19 @@
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = copymove
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/tests/copymove/copymove.c b/apps/tests/copymove/copymove.c
new file mode 100644 (file)
index 0000000..81c4a2e
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * CopyFile, MoveFile and related routines test
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+static TCHAR
+FindOtherDrive()
+{
+       DWORD drives = GetLogicalDrives();
+       BOOL found = FALSE;
+       TCHAR drive;
+       TCHAR rootdir[] = _T( "?:\\" );
+       TCHAR currentdir[MAX_PATH + 1];
+
+       if (0 != GetCurrentDirectory(MAX_PATH + 1, currentdir)) {
+               for (drive = _T('A'); ! found && drive <= _T('Z'); drive++) {
+                       if (0 != (drives & (1 << (drive - _T('A'))))&&
+                           drive != _totupper(currentdir[0])) {
+                               rootdir[0] = drive;
+                               found = (DRIVE_FIXED == GetDriveType(rootdir));
+                       }
+               }
+       }
+
+       return found ? drive - 1 : _T( ' ' );
+}
+
+static void
+DeleteTestFile(LPCTSTR filename)
+{
+       SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL);
+       DeleteFile(filename);
+}
+
+static void
+CreateTestFile(LPCTSTR filename, DWORD attributes)
+{
+       HANDLE file;
+       char buffer[4096];
+       DWORD wrote;
+       int c;
+
+       DeleteTestFile(filename);   
+       file = CreateFile(filename, 
+                         GENERIC_READ | GENERIC_WRITE, 
+                         0, 
+                         NULL, 
+                         CREATE_ALWAYS, 
+                         0, 
+                         0);
+   
+       if (INVALID_HANDLE_VALUE == file) {
+               fprintf(stderr, "CreateFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       for(c = 0; c < sizeof(buffer); c++) {
+               buffer[c] = (char) c;
+       }
+       if (! WriteFile(file, buffer, sizeof(buffer), &wrote, NULL)) {
+               fprintf(stderr, "WriteFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       CloseHandle(file);
+
+       if (! SetFileAttributes(filename, attributes)) {
+               fprintf(stderr, "SetFileAttributes failed with code %d\n", GetLastError());
+               exit(1);
+       }
+}
+
+static void
+DeleteTestDir(LPCTSTR dirname)
+{
+       RemoveDirectory(dirname);
+}
+
+static void
+CreateTestDir(LPCTSTR dirname)
+{
+       if (! CreateDirectory(dirname, NULL)) {
+               fprintf(stderr, "CreateDirectory failed with code %d\n", GetLastError());
+               exit(1);
+       }
+}
+
+static void
+CheckTestFile(LPCTSTR filename, DWORD attributes)
+{
+       HANDLE file;
+       char buffer[4096];
+       DWORD read;
+       int c;
+       DWORD diskattr;
+
+       file = CreateFile(filename,
+                         GENERIC_READ,
+                         0,
+                         NULL,
+                         OPEN_EXISTING,
+                         0,
+                         0);
+
+       if (INVALID_HANDLE_VALUE == file) {
+               fprintf(stderr, "CreateFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+
+       if (! ReadFile(file, buffer, sizeof(buffer), &read, NULL)) {
+               fprintf(stderr, "ReadFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       if (read != sizeof(buffer)) {
+               fprintf(stderr, "Trying to read %d bytes but got %d bytes\n", sizeof(buffer), read);
+               exit(1);
+       }
+       for(c = 0; c < sizeof(buffer); c++) {
+               if (buffer[c] != (char) c) {
+                       fprintf(stderr, "File contents changed at position %d\n", c);
+                       exit(1);
+               }
+       }
+
+       CloseHandle(file);
+       
+       diskattr = GetFileAttributes(filename);
+       if (INVALID_FILE_ATTRIBUTES == diskattr) {
+               fprintf(stderr, "GetFileAttributes failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       if (diskattr != attributes) {
+               fprintf(stderr, "Attribute mismatch, expected 0x%08x found 0x%08x\n", attributes, diskattr);
+               exit(1);
+       }
+}
+
+int
+main(int argc, char *argv[])
+{
+       TCHAR otherdrive;
+       TCHAR otherfile[ ] = _T("?:\\other.dat");
+
+       otherdrive = FindOtherDrive();
+
+       printf("Testing simple move\n");
+       CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       DeleteTestFile(_T("end.dat"));
+       if (! MoveFile(_T("begin.dat"), _T("end.dat"))) {
+               fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       CheckTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       DeleteTestFile(_T("end.dat"));
+
+       printf("Testing move of non-existing file\n");
+       DeleteTestFile(_T("begin.dat"));
+       DeleteTestFile(_T("end.dat"));
+       if (MoveFile(_T("begin.dat"), _T("end.dat"))) {
+               fprintf(stderr, "MoveFile succeeded but shouldn't have\n");
+               exit(1);
+       } else if (ERROR_FILE_NOT_FOUND != GetLastError()) {
+               fprintf(stderr, "MoveFile failed with unexpected code %d\n", GetLastError());
+               exit(1);
+       }
+       DeleteTestFile(_T("end.dat"));
+
+/* Not correctly implemented in ros, destination file is kept open after this */
+#if 0
+       printf("Testing move to existing file\n");
+       CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       if (MoveFile(_T("begin.dat"), _T("end.dat"))) {
+               fprintf(stderr, "MoveFile succeeded but shouldn't have\n");
+               exit(1);
+       } else if (ERROR_ALREADY_EXISTS != GetLastError()) {
+               fprintf(stderr, "MoveFile failed with unexpected code %d\n", GetLastError());
+               exit(1);
+       }
+       DeleteTestFile(_T("begin.dat"));
+       DeleteTestFile(_T("end.dat"));
+#endif
+
+/* Not implemented yet in ros */
+#if 0
+       printf("Testing directory move\n");
+       CreateTestDir(_T("begin"));
+       CreateTestFile(_T("begin\\file.dat"), FILE_ATTRIBUTE_NORMAL);
+       DeleteTestDir(_T("end"));
+       if (! MoveFile(_T("begin"), _T("end"))) {
+               fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       CheckTestFile(_T("end\\file.dat"), FILE_ATTRIBUTE_NORMAL);
+       DeleteTestFile(_T("end\\file.dat"));
+       DeleteTestDir(_T("end"));
+#endif
+
+       printf("Testing file move to different directory\n");
+       CreateTestFile(_T("file.dat"), FILE_ATTRIBUTE_NORMAL);
+       CreateTestDir(_T("end"));
+       if (! MoveFile(_T("file.dat"), _T("end\\file.dat"))) {
+               fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       CheckTestFile(_T("end\\file.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       DeleteTestFile(_T("end\\file.dat"));
+       DeleteTestDir(_T("end"));
+
+       printf("Testing move of read-only file\n");
+       CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_READONLY);
+       DeleteTestFile(_T("end.dat"));
+       if (! MoveFile(_T("begin.dat"), _T("end.dat"))) {
+               fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       CheckTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY);
+       DeleteTestFile(_T("end.dat"));
+
+       printf("Testing move to different drive\n");
+       if (_T(' ') != otherdrive) {
+               otherfile[0] = otherdrive;
+               CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+               DeleteTestFile(otherfile);
+               if (! MoveFile(_T("begin.dat"), otherfile)) {
+                       fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+                       exit(1);
+               }
+               CheckTestFile(otherfile, FILE_ATTRIBUTE_ARCHIVE);
+               DeleteTestFile(otherfile);
+       } else {
+               printf("  Test skipped, no other drive available\n");
+       }
+
+       printf("Testing move/overwrite of existing file\n");
+       CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       if (! MoveFileEx(_T("begin.dat"), _T("end.dat"), MOVEFILE_REPLACE_EXISTING)) {
+               fprintf(stderr, "MoveFileEx failed with code %d\n", GetLastError());
+               exit(1);
+       }
+       DeleteTestFile(_T("begin.dat"));
+       DeleteTestFile(_T("end.dat"));
+
+/* Not (correctly) implemented in ros yet */
+#if 0
+       printf("Testing move/overwrite of existing readonly file\n");
+       CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+       CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_READONLY);
+       if (MoveFileEx(_T("begin.dat"), _T("end.dat"), MOVEFILE_REPLACE_EXISTING)) {
+               fprintf(stderr, "MoveFileEx succeeded but shouldn't have\n");
+               exit(1);
+       } else if (ERROR_ALREADY_EXISTS != GetLastError() &&
+                  ERROR_ACCESS_DENIED != GetLastError()) {
+               fprintf(stderr, "MoveFileEx failed with unexpected code %d\n", GetLastError());
+               exit(1);
+       }
+       DeleteTestFile(_T("begin.dat"));
+       DeleteTestFile(_T("end.dat"));
+#endif
+
+/* Not implemented in ros yet */
+#if 0
+       printf("Testing move to different drive without COPY_ALLOWED\n");
+       if (_T(' ') != otherdrive) {
+               otherfile[0] = otherdrive;
+               CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+               DeleteTestFile(otherfile);
+               if (MoveFileEx(_T("begin.dat"), otherfile, 0)) {
+                       fprintf(stderr, "MoveFileEx succeeded but shouldn't have\n");
+                       exit(1);
+               } else if (ERROR_NOT_SAME_DEVICE != GetLastError()) {
+                       fprintf(stderr, "MoveFileEx failed with unexpected code %d\n", GetLastError());
+                       exit(1);
+               }
+               DeleteTestFile(otherfile);
+       } else {
+               printf("  Test skipped, no other drive available\n");
+       }
+#endif
+
+       printf("Testing move to different drive with COPY_ALLOWED\n");
+       if (_T(' ') != otherdrive) {
+               otherfile[0] = otherdrive;
+               CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+               DeleteTestFile(otherfile);
+               if (! MoveFileEx(_T("begin.dat"), otherfile, MOVEFILE_COPY_ALLOWED)) {
+                       fprintf(stderr, "MoveFileEx failed with code %d\n", GetLastError());
+                       exit(1);
+               }
+               CheckTestFile(otherfile, FILE_ATTRIBUTE_ARCHIVE);
+               DeleteTestFile(otherfile);
+       } else {
+               printf("  Test skipped, no other drive available\n");
+       }
+
+       printf("All tests successfully completed\n");
+
+       return 0;
+}
diff --git a/apps/tests/count/.cvsignore b/apps/tests/count/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/dibtest/.cvsignore b/apps/tests/dibtest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/dump_shared_data/.cvsignore b/apps/tests/dump_shared_data/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/event/.cvsignore b/apps/tests/event/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/file/.cvsignore b/apps/tests/file/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/gditest/.cvsignore b/apps/tests/gditest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/hello/.cvsignore b/apps/tests/hello/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/hivetest/.cvsignore b/apps/tests/hivetest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/hivetest/hivetest.c b/apps/tests/hivetest/hivetest.c
new file mode 100644 (file)
index 0000000..587526c
--- /dev/null
@@ -0,0 +1,1205 @@
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <windows.h>
+#include <ddk/ntddk.h>
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+void dprintf(char* fmt, ...)
+{
+   va_list args;
+   char buffer[255];
+
+   va_start(args,fmt);
+   vsprintf(buffer,fmt,args);
+   WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
+   va_end(args);
+}
+
+void do_enumeratekey(PWSTR Name)
+{
+ ULONG Index,Length,i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hKey1;
+ UNICODE_STRING KeyName;
+
+  RtlInitUnicodeString(&KeyName, Name);
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+    dprintf("NtEnumerateKey : \n");
+    Index=0;
+    while(Status == STATUS_SUCCESS)
+    {
+      Status=NtEnumerateKey(hKey1,Index++,KeyBasicInformation
+               ,&KeyInformation[0], sizeof(KeyInformation)
+               ,&Length);
+      if(Status== STATUS_SUCCESS)
+       {
+        dprintf("\tSubKey Name = ");
+         for (i=0;i<KeyInformation[0].NameLength/2;i++)
+               dprintf("%C",KeyInformation[0].Name[i]);
+        dprintf("\n");
+       }
+    }
+  NtClose(hKey1);
+}
+
+
+void CreateKeyTest(void)
+{
+  HKEY hKey;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  NTSTATUS Status;
+
+  dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  dprintf("NtCreateKey: ");
+  Status = NtCreateKey(&hKey,
+                      KEY_ALL_ACCESS,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_NON_VOLATILE,
+                      NULL);
+  dprintf("Status = %lx\n",Status);
+  if (NT_SUCCESS(Status))
+    {
+      NtClose(hKey);
+    }
+}
+
+
+void DeleteKeyTest(void)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  HKEY hKey;
+  NTSTATUS Status;
+
+  dprintf("Delete key '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  dprintf("NtOpenKey: ");
+  Status = NtOpenKey(&hKey,
+                    KEY_ALL_ACCESS,
+                    &ObjectAttributes);
+  dprintf("Status = %lx\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("NtDeleteKey: ");
+  Status = NtDeleteKey(hKey);
+  dprintf("Status = %lx\n",Status);
+  NtClose(hKey);
+}
+
+
+void EnumerateKeyTest(void)
+{
+  HKEY hKey = NULL, hKey1;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  NTSTATUS Status;
+  UNICODE_STRING KeyName;
+  ULONG Index;
+  ULONG Length;
+  ULONG i;
+  KEY_BASIC_INFORMATION KeyInformation[5];
+
+  dprintf("Enumerate key '\\Registry\\Machine\\Software':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  dprintf("NtOpenKey: ");
+  Status = NtOpenKey(&hKey,
+                    KEY_ALL_ACCESS,
+                    &ObjectAttributes);
+  dprintf("Status = %lx\n", Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("NtQueryKey: ");
+  Status = NtQueryKey(hKey,
+                     KeyBasicInformation,
+                     &KeyInformation[0],
+                     sizeof(KeyInformation),
+                     &Length);
+  dprintf("Status = %lx\n", Status);
+  if (NT_SUCCESS(Status))
+    {
+      dprintf("\tKey Name = ");
+      for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+       dprintf("%C", KeyInformation[0].Name[i]);
+      dprintf("\n");
+    }
+
+  dprintf("NtEnumerateKey: \n");
+  Index=0;
+  while(NT_SUCCESS(Status))
+    {
+      Status = NtEnumerateKey(hKey,
+                             Index,
+                             KeyBasicInformation,
+                             &KeyInformation[0],
+                             sizeof(KeyInformation),
+                             &Length);
+      if (NT_SUCCESS(Status))
+       {
+         dprintf("\tSubKey Name = ");
+         for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+           dprintf("%C", KeyInformation[0].Name[i]);
+         dprintf("\n");
+       }
+      Index++;
+    }
+
+  dprintf("NtClose: ");
+  Status = NtClose(hKey);
+  dprintf("Status = %lx\n", Status);
+}
+
+
+void SetValueTest1(void)
+{
+  HKEY hKey;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  UNICODE_STRING ValueName;
+  NTSTATUS Status;
+
+  dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            NULL,
+                            NULL);
+  dprintf("NtCreateKey: ");
+  Status = NtCreateKey(&hKey,
+                      KEY_ALL_ACCESS,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_NON_VOLATILE,
+                      NULL);
+  dprintf("Status = %lx\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  RtlInitUnicodeStringFromLiteral(&ValueName,
+                                 L"TestValue");
+  dprintf("NtSetValueKey: ");
+  Status = NtSetValueKey(hKey,
+                        &ValueName,
+                        0,
+                        REG_SZ,
+                        (PVOID)L"TestString",
+                        24);
+  dprintf("Status = %lx\n",Status);
+
+  NtClose(hKey);
+}
+
+
+void SetValueTest2(void)
+{
+  HKEY hKey;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  UNICODE_STRING ValueName;
+  NTSTATUS Status;
+
+  dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            NULL,
+                            NULL);
+  dprintf("NtCreateKey: ");
+  Status = NtCreateKey(&hKey,
+                      KEY_ALL_ACCESS,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_NON_VOLATILE,
+                      NULL);
+  dprintf("  Status = %lx\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  RtlInitUnicodeStringFromLiteral(&ValueName,
+                                 L"TestValue");
+  dprintf("NtSetValueKey:\n");
+  Status = NtSetValueKey(hKey,
+                        &ValueName,
+                        0,
+                        REG_DWORD,
+                        (PVOID)"reac",
+                        4);
+  dprintf("  Status = %lx\n",Status);
+
+  NtClose(hKey);
+}
+
+
+void DeleteValueTest(void)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  UNICODE_STRING ValueName;
+  HKEY KeyHandle;
+  NTSTATUS Status;
+
+  dprintf("Open key: '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  Status=NtOpenKey(&KeyHandle,
+                  MAXIMUM_ALLOWED,
+                  &ObjectAttributes);
+  dprintf("  Status = %lx\n", Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Delete value:\n");
+  RtlInitUnicodeStringFromLiteral(&ValueName,
+                                 L"TestValue");
+  Status = NtDeleteValueKey(KeyHandle,
+                           &ValueName);
+  dprintf("  Status = %lx\n", Status);
+
+  dprintf("Close key:\n");
+  Status = NtClose(KeyHandle);
+  dprintf("  Status = %lx\n", Status);
+}
+
+
+void EnumerateValueTest(void)
+{
+  KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+  KEY_BASIC_INFORMATION KeyInformation[5];
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  ULONG Index,Length,i;
+  HKEY hKey = NULL;
+  NTSTATUS Status;
+
+  dprintf("Open key: '\\Registry\\Machine\\Software\\testkey':\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName,
+                                 L"\\Registry\\Machine\\Software\\testkey");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  Status=NtOpenKey(&hKey,
+                  MAXIMUM_ALLOWED,
+                  &ObjectAttributes);
+  dprintf("  Status = %lx\n", Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Enumerate values: \n");
+  Index = 0;
+  while (Status == STATUS_SUCCESS)
+    {
+      Status = NtEnumerateValueKey(hKey,
+                                  Index++,
+                                  KeyValueFullInformation,
+                                  &KeyValueInformation[0],
+                                  sizeof(KeyValueInformation),
+                                  &Length);
+      if (Status == STATUS_SUCCESS)
+       {
+         dprintf("    Value:DO=%d, DL=%d, NL=%d, Name = ",
+                 KeyValueInformation[0].DataOffset,
+                 KeyValueInformation[0].DataLength,
+                 KeyValueInformation[0].NameLength);
+         for (i = 0; i < KeyValueInformation[0].NameLength / 2; i++)
+           dprintf("%C", KeyValueInformation[0].Name[i]);
+         dprintf(", Type = %d\n", KeyValueInformation[0].Type);
+
+         if (KeyValueInformation[0].Type == REG_SZ)
+           dprintf("    Value = %S\n",
+                   ((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset));
+
+         if (KeyValueInformation[0].Type == REG_DWORD)
+           dprintf("    Value = %X\n",
+                   *((DWORD*)((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset)));
+       }
+    }
+
+  dprintf("NtClose:\n");
+  Status = NtClose(hKey);
+  dprintf("  Status = %lx\n", Status);
+}
+
+
+
+
+void test1(void)
+{
+ HKEY hKey = NULL, hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes; 
+ NTSTATUS Status; 
+#if 0
+ UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry");
+#endif
+ UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software");
+ ULONG Index,Length,i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+
+#if 0
+  dprintf("NtOpenKey \\Registry : ");
+#endif
+  dprintf("NtOpenKey \\Registry\\Machine\\Software : ");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  if(Status==0)
+  {
+    dprintf("NtQueryKey : ");
+    Status=NtQueryKey(hKey1,KeyBasicInformation
+               ,&KeyInformation[0], sizeof(KeyInformation)
+               ,&Length);
+    dprintf("\t\t\t\t\tStatus =%x\n",Status);
+    if (Status == STATUS_SUCCESS)
+    {
+        dprintf("\tKey Name = ");
+         for (i=0;i<KeyInformation[0].NameLength/2;i++)
+               dprintf("%C",KeyInformation[0].Name[i]);
+        dprintf("\n");
+    }
+    dprintf("NtEnumerateKey : \n");
+    Index=0;
+    while(Status == STATUS_SUCCESS)
+    {
+      Status=NtEnumerateKey(hKey1,Index++,KeyBasicInformation
+               ,&KeyInformation[0], sizeof(KeyInformation)
+               ,&Length);
+      if(Status== STATUS_SUCCESS)
+       {
+        dprintf("\tSubKey Name = ");
+         for (i=0;i<KeyInformation[0].NameLength/2;i++)
+               dprintf("%C",KeyInformation[0].Name[i]);
+        dprintf("\n");
+       }
+    }
+    dprintf("NtClose : ");
+    Status = NtClose( hKey1 );
+    dprintf("\t\t\t\t\tStatus =%x\n",Status);
+  }
+  NtClose(hKey);
+
+#if 0
+  dprintf("NtOpenKey \\Registry\\Machine : ");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\t\tStatus =%x\n",Status);
+
+  dprintf("NtOpenKey System\\Setup : ");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\Setup");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , hKey1 , NULL);
+  Status = NtOpenKey ( &hKey, KEY_READ , &ObjectAttributes);
+  dprintf("\t\t\tStatus =%x\n",Status);
+  if(Status==0)
+  {
+    dprintf("NtQueryValueKey : ");
+    RtlInitUnicodeStringFromLiteral(&KeyName, L"CmdLine");
+    Status=NtQueryValueKey(hKey,&KeyName,KeyValueFullInformation
+               ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+               ,&Length);
+    dprintf("\t\t\t\tStatus =%x\n",Status);
+    if (Status == STATUS_SUCCESS)
+    {
+      dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+             ,KeyValueInformation[0].DataOffset
+             ,KeyValueInformation[0].DataLength
+             ,KeyValueInformation[0].NameLength);
+      for (i=0;i<10 && i<KeyValueInformation[0].NameLength/2;i++)
+       dprintf("%C",KeyValueInformation[0].Name[i]);
+      dprintf("\n");
+      dprintf("\t\tType = %d\n",KeyValueInformation[0].Type);
+      if (KeyValueInformation[0].Type == REG_SZ)
+       dprintf("\t\tValue = %S\n",
+               (PWCHAR)((PCHAR)&KeyValueInformation[0] + KeyValueInformation[0].DataOffset));
+    }
+    dprintf("NtEnumerateValueKey : \n");
+    Index=0;
+    while(Status == STATUS_SUCCESS)
+    {
+      Status=NtEnumerateValueKey(hKey,Index++,KeyValueFullInformation
+               ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+               ,&Length);
+      if(Status== STATUS_SUCCESS)
+       {
+        dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+               ,KeyValueInformation[0].DataOffset
+               ,KeyValueInformation[0].DataLength
+               ,KeyValueInformation[0].NameLength);
+         for (i=0;i<KeyValueInformation[0].NameLength/2;i++)
+               dprintf("%C",KeyValueInformation[0].Name[i]);
+        dprintf(", Type = %d\n",KeyValueInformation[0].Type);
+         if (KeyValueInformation[0].Type == REG_SZ)
+          dprintf("\t\tValue = %S\n",((char*)&KeyValueInformation[0]
+                                       +KeyValueInformation[0].DataOffset));
+       }
+    }
+    dprintf("NtClose : ");
+    Status = NtClose( hKey );
+    dprintf("\t\t\t\t\tStatus =%x\n",Status);
+  }
+  NtClose( hKey1 );
+#endif
+}
+
+
+void test3(void)
+{
+ HKEY hKey,hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes; 
+ UNICODE_STRING KeyName,ValueName;
+ NTSTATUS Status; 
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+ ULONG Index,Length,i;
+ char Buffer[10];
+ DWORD Result;
+  dprintf("NtCreateKey non volatile: \n");
+  dprintf("  \\Registry\\Machine\\Software\\test3reactos: ");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+               ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+  dprintf("\t\tStatus=%x\n",Status);
+  NtClose(hKey);
+#if 0
+  do_enumeratekey(L"\\Registry\\Machine\\Software");
+  dprintf("NtOpenKey: ");
+  Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\tStatus=%x\n",Status);
+  NtClose(hKey);
+  dprintf("  ...\\test3 :");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+               ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+  dprintf("\t\t\t\t\tStatus=%x\n",Status);
+  dprintf("NtOpenKey: ");
+  Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\tStatus=%x\n",Status);
+  NtClose(hKey);
+  dprintf("  ...\\testNonVolatile :");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"TestNonVolatile");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , hKey1, NULL);
+  Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+               ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+  dprintf("\t\t\t\tStatus=%x\n",Status);
+  NtClose(hKey1);
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"TestREG_SZ");
+  dprintf("NtSetValueKey reg_sz: ");
+  Status=NtSetValueKey(hKey,&ValueName,0,REG_SZ,(PVOID)L"Test Reg_sz",24);
+  dprintf("\t\t\t\tStatus=%x\n",Status);
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"TestDWORD");
+  dprintf("NtSetValueKey reg_dword: ");
+  Status=NtSetValueKey(hKey,&ValueName,0,REG_DWORD,(PVOID)"reac",4);
+  dprintf("\t\t\tStatus=%x\n",Status);
+  NtClose(hKey);
+  dprintf("NtOpenKey \\Registry\\Machine\\Software\\test3reactos\\test3\\testNonVolatile : ");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3\\testNonVolatile");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  if(Status==0)
+  {
+    dprintf("NtEnumerateValueKey : \n");
+    Index=0;
+    while(Status == STATUS_SUCCESS)
+    {
+      Status=NtEnumerateValueKey(hKey,Index++,KeyValueFullInformation
+               ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+               ,&Length);
+      if(Status== STATUS_SUCCESS)
+       {
+        dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+               ,KeyValueInformation[0].DataOffset
+               ,KeyValueInformation[0].DataLength
+               ,KeyValueInformation[0].NameLength);
+         for (i=0;i<KeyValueInformation[0].NameLength/2;i++)
+               dprintf("%C",KeyValueInformation[0].Name[i]);
+        dprintf(", Type = %d\n",KeyValueInformation[0].Type);
+         if (KeyValueInformation[0].Type == REG_SZ)
+          dprintf("\t\tValue = %S\n",((char*)&KeyValueInformation[0]
+                                       +KeyValueInformation[0].DataOffset));
+       }
+    }
+  }
+  NtClose(hKey);
+#endif
+
+  dprintf("delete \\Registry\\Machine\\software\\test3reactos ?");
+  ReadConsoleA(InputHandle, Buffer, 3, &Result, NULL) ;
+  if (Buffer[0] != 'y' && Buffer[0] != 'Y') return;
+#if 0
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3\\testNonvolatile");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  dprintf("NtOpenKey : ");
+  Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  dprintf("NtDeleteKey : ");
+  Status=NtDeleteKey(hKey);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  dprintf("NtOpenKey : ");
+  Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  dprintf("NtDeleteKey : ");
+  Status=NtDeleteKey(hKey);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  NtClose(hKey);
+#endif
+  dprintf("delete \\Registry\\Machine\\software\\test3reactos ?");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  dprintf("NtOpenKey : ");
+  Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  dprintf("NtDeleteKey : ");
+  Status=NtDeleteKey(hKey);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  NtClose(hKey);
+}
+
+void test4(void)
+{
+  HKEY hKey = NULL,hKey1;
+  DWORD dwDisposition;
+  DWORD dwError;
+  DWORD  RegDataType, RegDataSize;
+  BOOL GlobalFifoEnable;
+  HKEY hPortKey;
+  DWORD RegDisposition;
+  WCHAR szClass[260];
+  DWORD cchClass;
+  DWORD cSubKeys;
+  DWORD cchMaxSubkey;
+  DWORD cchMaxClass;
+  DWORD cValues;
+  DWORD cchMaxValueName;
+  DWORD cbMaxValueData;
+  DWORD cbSecurityDescriptor;
+  FILETIME ftLastWriteTime;
+  SYSTEMTIME LastWriteTime;
+
+  dprintf ("RegOpenKeyExW HKLM\\System\\Setup: ");
+  dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                           L"System\\Setup",
+                           0,
+                           KEY_ALL_ACCESS,
+                           &hKey1); 
+  dprintf("\t\tdwError =%x\n",dwError);
+  if (dwError == ERROR_SUCCESS)
+    {
+      dprintf("RegQueryInfoKeyW: ");
+      cchClass=260;
+      dwError = RegQueryInfoKeyW(hKey1
+       , szClass, &cchClass, NULL, &cSubKeys
+       , &cchMaxSubkey, &cchMaxClass, &cValues, &cchMaxValueName
+       , &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
+      dprintf ("\t\t\t\tdwError %x\n", dwError);
+      FileTimeToSystemTime(&ftLastWriteTime,&LastWriteTime);
+      dprintf ("\tnb of subkeys=%d,last write : %d/%d/%d %d:%02.2d'%02.2d''%03.3d\n",cSubKeys
+               ,LastWriteTime.wMonth
+               ,LastWriteTime.wDay
+               ,LastWriteTime.wYear
+               ,LastWriteTime.wHour
+               ,LastWriteTime.wMinute
+               ,LastWriteTime.wSecond
+               ,LastWriteTime.wMilliseconds
+               );
+    }
+
+
+   dprintf ("RegOpenKeyExW: ");
+   dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                           L"System\\ControlSet001\\Services\\Serial",
+                           0,
+                           KEY_ALL_ACCESS,
+                           &hKey); 
+   dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+   RegDataSize = sizeof(GlobalFifoEnable);
+   if (dwError == ERROR_SUCCESS)
+   {
+     dprintf ("RegQueryValueExW: ");
+     dwError = RegQueryValueExW(hKey,
+                        L"ForceFifoEnable",
+                        NULL,
+                        &RegDataType,
+                        (PBYTE)&GlobalFifoEnable,
+                        &RegDataSize);
+    dprintf("\t\t\t\tdwError =%x\n",dwError);
+    if (dwError == 0)
+    {
+        dprintf("\tValue:DT=%d, DS=%d, Value=%d\n"
+               ,RegDataType
+               ,RegDataSize
+               ,GlobalFifoEnable);
+    }
+   }
+   dprintf ("RegCreateKeyExW: ");
+   dwError = RegCreateKeyExW(hKey,
+                         L"Parameters\\Serial001",
+                         0,
+                         NULL,
+                         0,
+                         KEY_ALL_ACCESS,
+                         NULL,
+                         &hPortKey,
+                         &RegDisposition
+                        );
+   dprintf ("\t\t\t\tdwError %x\n", dwError);
+
+   dprintf ("RegCreateKeyExW: ");
+   dwError = RegCreateKeyExW (HKEY_LOCAL_MACHINE,
+                              L"Software\\test4reactos\\test",
+                              0,
+                              NULL,
+                              REG_OPTION_NON_VOLATILE,
+                              KEY_ALL_ACCESS,
+                              NULL,
+                              &hKey,
+                              &dwDisposition);
+
+   dprintf ("\t\t\t\tdwError %x ", dwError);
+   dprintf ("dwDisposition %x\n", dwDisposition);
+   if (dwError == ERROR_SUCCESS)
+   {
+     dprintf ("RegSetValueExW: ");
+     dwError = RegSetValueExW (hKey,
+                             L"TestValue",
+                             0,
+                             REG_SZ,
+                             (BYTE*)L"TestString",
+                             20);
+
+     dprintf ("\t\t\t\tdwError %x\n", dwError);
+     dprintf ("RegCloseKey: ");
+     dwError = RegCloseKey (hKey);
+     dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+   }
+   dprintf ("\n\n");
+
+   hKey = NULL;
+
+   dprintf ("RegCreateKeyExW: ");
+   dwError = RegCreateKeyExW (HKEY_LOCAL_MACHINE,
+                              L"software\\Test",
+                              0,
+                              NULL,
+                              REG_OPTION_VOLATILE,
+                              KEY_ALL_ACCESS,
+                              NULL,
+                              &hKey,
+                              &dwDisposition);
+
+   dprintf ("\t\t\t\tdwError %x ", dwError);
+   dprintf ("dwDisposition %x\n", dwDisposition);
+
+
+   if (dwError == ERROR_SUCCESS)
+   {
+     dprintf("RegQueryInfoKeyW: ");
+     cchClass=260;
+     dwError = RegQueryInfoKeyW(hKey
+       , szClass, &cchClass, NULL, &cSubKeys
+       , &cchMaxSubkey, &cchMaxClass, &cValues, &cchMaxValueName
+       , &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
+     dprintf ("\t\t\t\tdwError %x\n", dwError);
+     FileTimeToSystemTime(&ftLastWriteTime,&LastWriteTime);
+     dprintf ("\tnb of subkeys=%d,last write : %d/%d/%d %d:%02.2d'%02.2d''%03.3d\n",cSubKeys
+               ,LastWriteTime.wMonth
+               ,LastWriteTime.wDay
+               ,LastWriteTime.wYear
+               ,LastWriteTime.wHour
+               ,LastWriteTime.wMinute
+               ,LastWriteTime.wSecond
+               ,LastWriteTime.wMilliseconds
+               );
+     dprintf ("RegCloseKey: ");
+     dwError = RegCloseKey (hKey);
+     dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+   }
+   dprintf ("\nTests done...\n");
+}
+
+void test5(void)
+{
+  HKEY hKey,hKey1;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName,ValueName;
+  NTSTATUS Status;
+  KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+  ULONG Index,Length,i;
+  char Buffer[10];
+  DWORD Result;
+
+  dprintf("NtOpenKey : \n");
+  dprintf("  \\Registry\\Machine\\Software\\reactos : ");
+  RtlInitUnicodeStringFromLiteral(&KeyName,L"\\Registry\\Machine\\Software\\reactos");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+  dprintf("\t\tStatus=%x\n",Status);
+  dprintf("NtFlushKey : \n");
+  Status = NtFlushKey(hKey);
+  dprintf("\t\tStatus=%x\n",Status);
+  dprintf("NtCloseKey : \n");
+  Status=NtClose(hKey);
+  dprintf("\t\tStatus=%x\n",Status);
+}
+
+/* registry link create test */
+void test6(void)
+{
+  HKEY hKey;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName,ValueName;
+  NTSTATUS Status; 
+  KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+  ULONG Index,Length,i;
+  char Buffer[10];
+  DWORD Result;
+
+  dprintf("Create target key\n");
+  dprintf("  Key: \\Registry\\Machine\\SOFTWARE\\Reactos\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Reactos");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status = NtCreateKey(&hKey, KEY_ALL_ACCESS , &ObjectAttributes
+               ,0,NULL, REG_OPTION_VOLATILE,NULL);
+  dprintf("  NtCreateKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Create target value\n");
+  dprintf("  Value: TestValue = 'Test String'\n");
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"TestValue");
+  Status=NtSetValueKey(hKey,&ValueName,0,REG_SZ,(PVOID)L"TestString",22);
+  dprintf("  NtSetValueKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Close target key\n");
+  NtClose(hKey);
+
+
+  dprintf("Create link key\n");
+  dprintf("  Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
+                            NULL,
+                            NULL);
+  Status = NtCreateKey(&hKey,
+                      KEY_ALL_ACCESS | KEY_CREATE_LINK,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+                      NULL);
+  dprintf("  NtCreateKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Create link value\n");
+  dprintf("  Value: SymbolicLinkValue = '\\Registry\\Machine\\SOFTWARE\\Reactos'\n");
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"SymbolicLinkValue");
+  Status=NtSetValueKey(hKey,&ValueName,0,REG_LINK,(PVOID)L"\\Registry\\Machine\\SOFTWARE\\Reactos",68);
+  dprintf("  NtSetValueKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    {
+      dprintf("Creating link value failed! Test failed!\n");
+      NtClose(hKey);
+      return;
+    }
+
+  dprintf("Close link key\n");
+  NtClose(hKey);
+
+  dprintf("Open link key\n");
+  dprintf("  Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF
+                               , NULL, NULL);
+  Status = NtCreateKey(&hKey, KEY_ALL_ACCESS , &ObjectAttributes
+               ,0,NULL, REG_OPTION_VOLATILE, NULL);
+  dprintf("  NtCreateKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    return;
+
+  dprintf("Query value\n");
+  dprintf("  Value: TestValue\n");
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"TestValue");
+  Status=NtQueryValueKey(hKey,
+                        &ValueName,
+                        KeyValueFullInformation,
+                        &KeyValueInformation[0],
+                        sizeof(KeyValueInformation),
+                        &Length);
+  dprintf("  NtQueryValueKey() called (Status %lx)\n",Status);
+  if (Status == STATUS_SUCCESS)
+    {
+      dprintf("  Value: Type %d  DataLength %d NameLength %d  Name '",
+             KeyValueInformation[0].Type,
+             KeyValueInformation[0].DataLength,
+             KeyValueInformation[0].NameLength);
+      for (i=0; i < KeyValueInformation[0].NameLength / sizeof(WCHAR); i++)
+       dprintf("%C",KeyValueInformation[0].Name[i]);
+      dprintf("'\n");
+      if (KeyValueInformation[0].Type == REG_SZ)
+       dprintf("  Value '%S'\n",
+               KeyValueInformation[0].Name+1
+               +KeyValueInformation[0].NameLength/2);
+    }
+
+  dprintf("Close link key\n");
+  NtClose(hKey);
+
+  dprintf("Test successful!\n");
+}
+
+/* registry link delete test */
+void test7(void)
+{
+  HKEY hKey;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName,ValueName;
+  NTSTATUS Status; 
+
+  dprintf("Open link key\n");
+  dprintf("  Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
+                            NULL,
+                            NULL);
+  Status = NtCreateKey(&hKey,
+                      KEY_ALL_ACCESS,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK,
+                      NULL);
+  dprintf("  NtCreateKey() called (Status %lx)\n",Status);
+  if (!NT_SUCCESS(Status))
+    {
+      dprintf("Could not open the link key. Please run the link create test first!\n");
+      return;
+    }
+
+  dprintf("Delete link value\n");
+  RtlInitUnicodeStringFromLiteral(&ValueName, L"SymbolicLinkValue");
+  Status = NtDeleteValueKey(hKey,
+                           &ValueName);
+  dprintf("  NtDeleteValueKey() called (Status %lx)\n",Status);
+
+  dprintf("Delete link key\n");
+  Status=NtDeleteKey(hKey);
+  dprintf("  NtDeleteKey() called (Status %lx)\n",Status);
+
+  dprintf("Close link key\n");
+  NtClose(hKey);
+}
+
+
+void test8(void)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ NTSTATUS Status;
+ LONG dwError;
+ TOKEN_PRIVILEGES NewPrivileges; 
+ HANDLE Token,hKey;
+ LUID Luid; 
+ BOOLEAN bRes;
+  Status=NtOpenProcessToken(GetCurrentProcess()
+       ,TOKEN_ADJUST_PRIVILEGES,&Token);
+//     ,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&Token);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+//  bRes=LookupPrivilegeValueA(NULL,SE_RESTORE_NAME,&Luid);
+//  dprintf("\t\t\t\tbRes =%x\n",bRes);
+  NewPrivileges.PrivilegeCount = 1; 
+  NewPrivileges.Privileges[0].Luid = Luid; 
+//  NewPrivileges.Privileges[0].Luid.u.LowPart=18;
+//  NewPrivileges.Privileges[0].Luid.u.HighPart=0;
+  NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
+//  Status = NtAdjustPrivilegesToken( 
+  bRes = AdjustTokenPrivileges( 
+            Token, 
+            FALSE, 
+            &NewPrivileges, 
+            0, 
+            NULL, 
+            NULL 
+            ); 
+  dprintf("\t\t\t\tbRes =%x\n",bRes);
+//  Status=NtClose(Token); 
+//  dprintf("\t\t\t\tStatus =%x\n",Status);
+
+
+  RtlInitUnicodeStringFromLiteral(&KeyName,L"test5");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status = NtLoadKey(HKEY_LOCAL_MACHINE,&ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+  dwError=RegLoadKey(HKEY_LOCAL_MACHINE,"def"
+               ,"test5");
+  dprintf("\t\t\t\tdwError =%x\n",dwError);
+
+  dprintf("NtOpenKey \\Registry\\Machine : ");
+  RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+  InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+  Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+  dprintf("\t\t\tStatus =%x\n",Status);
+  RtlInitUnicodeStringFromLiteral(&KeyName,L"test5");
+  InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+                               , NULL, NULL);
+  Status = NtLoadKey(hKey,&ObjectAttributes);
+  dprintf("\t\t\t\tStatus =%x\n",Status);
+}
+
+void test9(void)
+{
+    HKEY hKey = NULL, hKey1;
+    OBJECT_ATTRIBUTES ObjectAttributes; 
+    NTSTATUS Status; 
+    UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry");
+    ULONG Index,Length,i;
+    KEY_BASIC_INFORMATION KeyInformation[5];
+    KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+
+    dprintf("NtOpenKey \\Registry : ");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+    dprintf("\t\t\t\tStatus =%x\n",Status);
+    if (Status == 0) {
+        dprintf("NtQueryKey : ");
+        Status = NtQueryKey(hKey1, KeyBasicInformation, &KeyInformation[0], sizeof(KeyInformation), &Length);
+        dprintf("\t\t\t\t\tStatus =%x\n",Status);
+        if (Status == STATUS_SUCCESS) {
+            dprintf("\tKey Name = ");
+               for (i=0;i<KeyInformation[0].NameLength/2;i++)
+                       dprintf("%C",KeyInformation[0].Name[i]);
+            dprintf("\n");
+               }
+
+        dprintf("NtEnumerateKey : \n");
+        Index = 0;
+        while (Status == STATUS_SUCCESS) {
+            Status = NtEnumerateKey(hKey1,Index++,KeyBasicInformation,&KeyInformation[0], sizeof(KeyInformation),&Length);
+            if (Status == STATUS_SUCCESS) {
+                dprintf("\tSubKey Name = ");
+                for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+                    dprintf("%C",KeyInformation[0].Name[i]);
+                dprintf("\n");
+                       }
+               }
+        dprintf("NtClose : ");
+        Status = NtClose( hKey1 );
+        dprintf("\t\t\t\t\tStatus =%x\n",Status);
+       }
+    NtClose(hKey); // RobD - hKey unused so-far, should this have been hKey1 ???
+
+    dprintf("NtOpenKey \\Registry\\Machine : ");
+    RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+    dprintf("\t\t\tStatus =%x\n",Status);
+
+//Status of c0000001 opening \Registry\Machine\System\CurrentControlSet\Services\Tcpip\Linkage
+
+//    dprintf("NtOpenKey System\\CurrentControlSet\\Services\\Tcpip : ");
+//    RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\CurrentControlSet\\Services\\Tcpip");
+#if 1
+    dprintf("NtOpenKey System\\ControlSet001\\Services\\Tcpip\\Parameters : ");
+    RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\ControlSet001\\Services\\Tcpip\\Parameters");
+#else
+    dprintf("NtOpenKey System\\CurrentControlSet\\Services\\Tcpip : ");
+    RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\CurrentControlSet\\Services\\Tcpip");
+#endif
+    InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, hKey1 , NULL);
+    Status = NtOpenKey(&hKey, KEY_READ , &ObjectAttributes);
+    dprintf("\t\t\tStatus =%x\n",Status);
+    if (Status == 0) {
+        dprintf("NtQueryValueKey : ");
+        RtlInitUnicodeStringFromLiteral(&KeyName, L"NameServer");
+        Status = NtQueryValueKey(hKey, &KeyName, KeyValueFullInformation, &KeyValueInformation[0], sizeof(KeyValueInformation), &Length);
+        dprintf("\t\t\t\tStatus =%x\n",Status);
+        if (Status == STATUS_SUCCESS) {
+            dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+                ,KeyValueInformation[0].DataOffset
+                ,KeyValueInformation[0].DataLength
+                ,KeyValueInformation[0].NameLength);
+            for (i = 0; i < 10 && i < KeyValueInformation[0].NameLength / 2; i++)
+                dprintf("%C", KeyValueInformation[0].Name[i]);
+            dprintf("\n");
+            dprintf("\t\tType = %d\n", KeyValueInformation[0].Type);
+            if (KeyValueInformation[0].Type == REG_SZ)
+                //dprintf("\t\tValue = %S\n", KeyValueInformation[0].Name + 1 + KeyValueInformation[0].NameLength / 2);
+                dprintf("\t\tValue = %S\n", KeyValueInformation[0].Name + KeyValueInformation[0].NameLength / 2);
+        }
+        dprintf("NtEnumerateValueKey : \n");
+        Index = 0;
+        while (Status == STATUS_SUCCESS) {
+            Status = NtEnumerateValueKey(hKey, Index++, KeyValueFullInformation, &KeyValueInformation[0], sizeof(KeyValueInformation), &Length);
+            if (Status == STATUS_SUCCESS) {
+                dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+                    ,KeyValueInformation[0].DataOffset
+                    ,KeyValueInformation[0].DataLength
+                    ,KeyValueInformation[0].NameLength);
+                for (i = 0; i < KeyValueInformation[0].NameLength / 2; i++)
+                    dprintf("%C", KeyValueInformation[0].Name[i]);
+                dprintf(", Type = %d\n", KeyValueInformation[0].Type);
+                if (KeyValueInformation[0].Type == REG_SZ)
+                    dprintf("\t\tValue = %S\n", ((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset));
+                if (KeyValueInformation[0].Type == REG_DWORD)
+                    dprintf("\t\tValue = %X\n", *((DWORD*)((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset)));
+            }
+        }
+        dprintf("NtClose : ");
+        Status = NtClose(hKey);
+        dprintf("\t\t\t\t\tStatus =%x\n", Status);
+    }
+    NtClose(hKey1);
+}
+
+
+int main(int argc, char* argv[])
+{
+  char Buffer[10];
+  DWORD Result;
+
+  AllocConsole();
+  InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+  OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+  while(1)
+  {
+    dprintf("choose test :\n");
+    dprintf("  0 = Exit\n");
+    dprintf("  1 = Create key\n");
+    dprintf("  2 = Delete key\n");
+    dprintf("  3 = Enumerate key\n");
+    dprintf("  4 = Set value (REG_SZ)\n");
+    dprintf("  5 = Set value (REG_DWORD)\n");
+    dprintf("  6 = Delete value\n");
+    dprintf("  7 = Enumerate value\n");
+    ReadConsoleA(InputHandle, Buffer, 3, &Result, NULL) ;
+    switch (Buffer[0])
+    {
+     case '0':
+      return(0);
+
+     case '1':
+      CreateKeyTest();
+      break;
+
+     case '2':
+      DeleteKeyTest();
+      break;
+
+     case '3':
+      EnumerateKeyTest();
+      break;
+
+     case '4':
+      SetValueTest1();
+      break;
+
+     case '5':
+      SetValueTest2();
+      break;
+
+     case '6':
+      DeleteValueTest();
+      break;
+
+     case '7':
+      EnumerateValueTest();
+      break;
+    }
+  }
+  return(0);
+}
diff --git a/apps/tests/hivetest/makefile b/apps/tests/hivetest/makefile
new file mode 100644 (file)
index 0000000..27a6bc7
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = hivetest
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/tests/isotest/.cvsignore b/apps/tests/isotest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/lock/Makefile b/apps/tests/lock/Makefile
new file mode 100644 (file)
index 0000000..daa54c8
--- /dev/null
@@ -0,0 +1,21 @@
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = lock
+
+TARGET_SDKLIBS = kernel32.a user32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/tests/lock/lock.c b/apps/tests/lock/lock.c
new file mode 100644 (file)
index 0000000..b5e8ba7
--- /dev/null
@@ -0,0 +1,112 @@
+
+#include <windows.h>
+#include <stdio.h>
+
+HANDLE hFile;
+
+BOOL Slock(DWORD start,DWORD len)
+{
+
+  OVERLAPPED   overl;
+  BOOL stat;
+  overl.Offset = start;
+  overl.OffsetHigh     = 0;
+  overl.hEvent = 0;
+
+
+  stat = LockFileEx(hFile,LOCKFILE_FAIL_IMMEDIATELY,0,len,0,&overl) ;
+  printf("Slock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+               return stat;
+
+}
+
+BOOL Xlock(DWORD start,DWORD len)
+{
+
+  OVERLAPPED   overl;
+  BOOL stat;
+
+  overl.Offset = start;
+  overl.OffsetHigh     = 0;
+  overl.hEvent = 0;
+
+  stat =  LockFileEx(hFile,LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,0,len,0,&overl);
+
+  printf("Xlock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+  return stat;
+
+
+}
+
+BOOL unlock(DWORD start,DWORD len)
+{
+
+  OVERLAPPED   overl;
+  BOOL stat;
+  overl.Offset = start;
+  overl.OffsetHigh     = 0;
+  overl.hEvent = 0;
+
+  stat = UnlockFileEx(hFile,0,len,0,&overl) ;
+  printf("unlock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+  return stat;
+
+}
+
+
+BOOL mkfile()
+{
+   hFile = CreateFile("C:\\lock.test",
+                      GENERIC_READ|GENERIC_WRITE,
+                     FILE_SHARE_READ|FILE_SHARE_WRITE,
+                     NULL,
+                     OPEN_ALWAYS,
+                     FILE_ATTRIBUTE_NORMAL,
+                     NULL);
+
+   printf("mkfile %s\n",(hFile == INVALID_HANDLE_VALUE) ? "FAILED" : "OK");
+   return !(hFile == INVALID_HANDLE_VALUE);
+
+
+}
+
+void main(void)
+{
+  DWORD ass;
+
+  printf("enter main\n");
+
+  mkfile();
+
+  Slock(8,10);
+  Slock(10,5);
+  Slock(10,5);
+  Slock(15,5);
+  Slock(5,10);
+  Slock(0,100);
+  Xlock(30,10);
+  Xlock(30,1);
+  unlock(30,1);
+  unlock(30,10);
+  Xlock(30,5);
+  Slock(35,5);
+  unlock(50,5);
+  unlock(0,100);
+  unlock(10,5);
+
+  if (WriteFile(hFile,"ass",4,&ass,NULL) == 0) printf("write 1 failed\n");
+  else printf("write 1 success\n");
+       
+  CloseHandle(hFile);
+  mkfile();
+  Slock(0,100);
+
+  if (WriteFile(hFile,"ass",4,&ass,NULL) == 0) printf("write 2 failed\n");
+  else printf("write 2 success\n");
+
+
+  CloseHandle(hFile);
+  Sleep(10000);
+
+
+}
\ No newline at end of file
diff --git a/apps/tests/lpc/.cvsignore b/apps/tests/lpc/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/mstest/.cvsignore b/apps/tests/mstest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/mutex/.cvsignore b/apps/tests/mutex/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/nptest/.cvsignore b/apps/tests/nptest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/pteb/.cvsignore b/apps/tests/pteb/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/regdump/main.c b/apps/tests/regdump/main.c
new file mode 100644 (file)
index 0000000..dd474c3
--- /dev/null
@@ -0,0 +1,45 @@
+// main.c :
+//
+#include <windows.h>
+#include <stdio.h>
+#include "regdump.h"
+
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+DWORD GetInput(char* Buffer, int buflen)
+{
+    DWORD Result;
+
+    ReadConsoleA(InputHandle, Buffer, buflen, &Result, NULL);
+    return Result;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+    //AllocConsole();
+    InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+    OutputHandle =  GetStdHandle(STD_OUTPUT_HANDLE);
+    //return regmain(argc, argv);
+    return regdump(argc, argv);
+}
+
+
+#ifndef __GNUC__
+
+//__declspec(dllimport) int __stdcall DllMain(void* hinstDll, unsigned long dwReason, void* reserved);
+
+char* args[] = { "regdump.exe", "0", "ansi", "verbose"};
+
+int __cdecl mainCRTStartup(void)
+{
+
+    //DllMain(NULL, DLL_PROCESS_ATTACH, NULL);
+
+    main(1, args);
+    return 0;
+}
+
+#endif /*__GNUC__*/
diff --git a/apps/tests/regdump/regcmds.c b/apps/tests/regdump/regcmds.c
new file mode 100644 (file)
index 0000000..13ea7a1
--- /dev/null
@@ -0,0 +1,224 @@
+/* $Id$
+ *
+ *  ReactOS regedit
+ *
+ *  regcmds.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  Original Work Copyright 2002 Andriy Palamarchuk
+ *
+ * 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
+ */
+
+#define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+
+#ifdef WIN32_REGDBG
+#else
+#include <ctype.h>
+#endif
+
+#include "regproc.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Global Variables:
+//
+
+static char *usage =
+"Usage:\n"
+"    regedit filename\n"
+"    regedit /E filename [regpath]\n"
+"    regedit /D regpath\n"
+"\n"
+"filename - registry file name\n"
+"regpath - name of the registry key\n"
+"\n"
+"When is called without any switches adds contents of the specified\n"
+"registry file to the registry\n"
+"\n"
+"Switches:\n"
+"    /E - exports contents of the specified registry key to the specified\n"
+"      file. Exports the whole registry if no key is specified.\n"
+"    /D - deletes specified registry key\n"
+"    /S - silent execution, can be used with any other switch.\n"
+"      The only existing mode, exists for compatibility with Windows regedit.\n"
+"    /V - advanced mode, can be used with any other switch.\n"
+"      Ignored, exists for compatibility with Windows regedit.\n"
+"    /L - location of system.dat file. Can be used with any other switch.\n"
+"      Ignored. Exists for compatibility with Windows regedit.\n"
+"    /R - location of user.dat file. Can be used with any other switch.\n"
+"      Ignored. Exists for compatibility with Windows regedit.\n"
+"    /? - print this help. Any other switches are ignored.\n"
+"    /C - create registry from. Not implemented.\n"
+"\n"
+"The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
+"This program is command-line compatible with Microsoft Windows\n"
+"regedit. The difference with Windows regedit - this application has\n"
+"command-line interface only.\n";
+
+typedef enum {
+    ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE, ACTION_VIEW
+} REGEDIT_ACTION;
+
+/**
+ * Process unknown switch.
+ *
+ * Params:
+ *   chu - the switch character in upper-case.
+ *   s - the command line string where s points to the switch character.
+ */
+void error_unknown_switch(char chu, char *s)
+{
+    if (isalpha(chu)) {
+        printf("Undefined switch /%c!\n", chu);
+    } else {
+        printf("Alphabetic character is expected after '%c' "
+               "in switch specification\n", *(s - 1));
+    }
+    //exit(1);
+}
+
+BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
+{
+    TCHAR filename[MAX_PATH];
+    TCHAR reg_key_name[KEY_MAX_LEN];
+
+    switch (action) {
+    case ACTION_ADD:
+        get_file_name(&s, filename, MAX_PATH);
+        if (!filename[0]) {
+            printf("No file name is specified\n%s", usage);
+            return FALSE;
+            //exit(1);
+        }
+        while (filename[0]) {
+            if (!import_registry_file(filename)) {
+                perror("");
+                printf("Can't open file \"%s\"\n", filename);
+                return FALSE;
+                //exit(1);
+            }
+            get_file_name(&s, filename, MAX_PATH);
+        }
+        break;
+    case ACTION_DELETE:
+        get_file_name(&s, reg_key_name, KEY_MAX_LEN);
+        if (!reg_key_name[0]) {
+            printf("No registry key is specified for removal\n%s", usage);
+            return FALSE;
+            //exit(1);
+        }
+        delete_registry_key(reg_key_name);
+        break;
+    case ACTION_EXPORT:
+        filename[0] = '\0';
+        get_file_name(&s, filename, MAX_PATH);
+        if (!filename[0]) {
+            printf("No file name is specified\n%s", usage);
+            return FALSE;
+            //exit(1);
+        }
+        if (s[0]) {
+            get_file_name(&s, reg_key_name, KEY_MAX_LEN);
+            export_registry_key(filename, reg_key_name);
+        } else {
+            export_registry_key(filename, NULL);
+        }
+        break;
+    default:
+        printf("Unhandled action!\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+BOOL ProcessCmdLine(LPSTR lpCmdLine)
+{
+    REGEDIT_ACTION action = ACTION_UNDEF;
+    LPSTR s = lpCmdLine;        /* command line pointer */
+    CHAR ch = *s;               /* current character */
+
+    while (ch && ((ch == '-') || (ch == '/'))) {
+        char chu;
+        char ch2;
+
+        s++;
+        ch = *s;
+        ch2 = *(s+1);
+        chu = toupper(ch);
+        if (!ch2 || isspace(ch2)) {
+            if (chu == 'S' || chu == 'V') {
+                /* ignore these switches */
+            } else {
+                switch (chu) {
+                case 'D':
+                    action = ACTION_DELETE;
+                    break;
+                case 'E':
+                    action = ACTION_EXPORT;
+                    break;
+                case 'V':
+                    action = ACTION_VIEW;
+                    break;
+                case '?':
+                    printf(usage);
+                    return FALSE;
+                    //exit(0);
+                    break;
+                default:
+                    error_unknown_switch(chu, s);
+                    return FALSE;
+                    break;
+                }
+            }
+            s++;
+        } else {
+            if (ch2 == ':') {
+                switch (chu) {
+                case 'L':
+                    /* fall through */
+                case 'R':
+                    s += 2;
+                    while (*s && !isspace(*s)) {
+                        s++;
+                    }
+                    break;
+                default:
+                    error_unknown_switch(chu, s);
+                    return FALSE;
+                    break;
+                }
+            } else {
+                /* this is a file name, starting from '/' */
+                s--;
+                break;
+            }
+        }
+        /* skip spaces to the next parameter */
+        ch = *s;
+        while (ch && isspace(ch)) {
+            s++;
+            ch = *s;
+        }
+    }
+    if (action == ACTION_UNDEF) {
+        action = ACTION_ADD;
+    }
+    return PerformRegAction(action, s);
+}
diff --git a/apps/tests/regdump/regdump.h b/apps/tests/regdump/regdump.h
new file mode 100644 (file)
index 0000000..be2c895
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  ReactOS
+ *
+ *  regdump.h
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __REGDUMP_H__
+#define __REGDUMP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern HANDLE OutputHandle;
+extern HANDLE InputHandle;
+
+DWORD GetInput(char* Buffer, int buflen);
+//void dprintf(char* fmt, ...);
+int regdump(int argc, char* argv[]);
+BOOL ProcessCmdLine(LPSTR lpCmdLine);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __REGDUMP_H__
diff --git a/apps/tests/regdump/regproc.c b/apps/tests/regdump/regproc.c
new file mode 100644 (file)
index 0000000..6fb0a2d
--- /dev/null
@@ -0,0 +1,1491 @@
+/*
+ * Registry processing routines. Routines, common for registry
+ * processing frontends.
+ *
+ * Copyright 1999 Sylvain St-Germain
+ * Copyright 2002 Andriy Palamarchuk
+ *
+ * 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
+ */
+
+#ifdef WIN32_REGDBG
+#include <windows.h>
+#include <tchar.h>
+#ifndef __GNUC__
+#include <ntsecapi.h>
+#else
+#include <ctype.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+//#include <winreg.h>
+#include "regdump.h"
+#else
+
+#define WIN32_LEAN_AND_MEAN     // Exclude rarely-used stuff from Windows headers
+#include <windows.h>
+#include <commctrl.h>
+#include <stdlib.h>
+#include <tchar.h>
+#include <process.h>
+#include <stdio.h>
+#include <wchar.h>
+    
+#include <ctype.h>
+#include <limits.h>
+#include <winnt.h>
+#include <winreg.h>
+#include <assert.h>
+
+#endif
+
+#include "regproc.h"
+
+
+#define REG_VAL_BUF_SIZE        4096
+
+/* Delimiters used to parse the "value" to query queryValue*/
+#define QUERY_VALUE_MAX_ARGS  1
+
+/* maximal number of characters in hexadecimal data line,
+   not including '\' character */
+#define REG_FILE_HEX_LINE_LEN   76
+
+/* Globals used by the api setValue, queryValue */
+static LPTSTR currentKeyName   = NULL;
+static HKEY  currentKeyClass  = 0;
+static HKEY  currentKeyHandle = 0;
+static BOOL  bTheKeyIsOpen    = FALSE;
+
+static TCHAR *reg_class_names[] = {
+    _T("HKEY_LOCAL_MACHINE"),
+    _T("HKEY_USERS"),
+    _T("HKEY_CLASSES_ROOT"),
+    _T("HKEY_CURRENT_CONFIG"),
+    _T("HKEY_CURRENT_USER")
+};
+
+#define REG_CLASS_NUMBER (sizeof(reg_class_names) / sizeof(reg_class_names[0]))
+
+static HKEY reg_class_keys[REG_CLASS_NUMBER] = {
+    HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT,
+    HKEY_CURRENT_CONFIG, HKEY_CURRENT_USER
+};
+
+/* return values */
+#define NOT_ENOUGH_MEMORY     1
+#define IO_ERROR              2
+
+/* processing macros */
+
+/* common check of memory allocation results */
+#ifdef UNICODE
+#define CHECK_ENOUGH_MEMORY(p) \
+    if (!(p)) \
+    { \
+        _tprintf(_T("file %S, line %d: Not enough memory"), __FILE__, __LINE__); \
+        assert(0);\
+        exit(NOT_ENOUGH_MEMORY); \
+    }
+#else
+#define CHECK_ENOUGH_MEMORY(p) \
+    if (!(p)) \
+    { \
+        _tprintf(_T("file %s, line %d: Not enough memory"), __FILE__, __LINE__); \
+        assert(0);\
+        exit(NOT_ENOUGH_MEMORY); \
+    }
+#endif
+
+#ifdef UNICODE
+#define _TEOF WEOF 
+#else
+#define _TEOF EOF 
+#endif
+
+/******************************************************************************
+ * This is a replacement for strsep which is not portable (missing on Solaris).
+ */
+#if 0
+/* DISABLED */
+char* getToken(char** str, const char* delims)
+{
+    char* token;
+
+    if (*str==NULL) {
+        /* No more tokens */
+        return NULL;
+    }
+
+    token=*str;
+    while (**str!='\0') {
+        if (strchr(delims,**str)!=NULL) {
+            **str='\0';
+            (*str)++;
+            return token;
+        }
+        (*str)++;
+    }
+    /* There is no other token */
+    *str=NULL;
+    return token;
+}
+#endif
+
+/******************************************************************************
+ * Copies file name from command line string to the buffer.
+ * Rewinds the command line string pointer to the next non-spece character
+ * after the file name.
+ * Buffer contains an empty string if no filename was found;
+ *
+ * params:
+ * command_line - command line current position pointer
+ *      where *s[0] is the first symbol of the file name.
+ * file_name - buffer to write the file name to.
+ */
+void get_file_nameA(CHAR **command_line, CHAR *file_name, int max_filename)
+{
+    CHAR *s = *command_line;
+    int pos = 0;                /* position of pointer "s" in *command_line */
+    file_name[0] = 0;
+
+    if (!s[0]) {
+        return;
+    }
+    if (s[0] == '"') {
+        s++;
+        (*command_line)++;
+        while (s[0] != '"') {
+            if (!s[0]) {
+                _tprintf(_T("Unexpected end of file name!\n"));
+                assert(0);
+                //exit(1);
+            }
+            s++;
+            pos++;
+        }
+    } else {
+        while (s[0] && !isspace(s[0])) {
+            s++;
+            pos++;
+        }
+    }
+    memcpy(file_name, *command_line, pos * sizeof((*command_line)[0]));
+    /* remove the last backslash */
+    if (file_name[pos - 1] == '\\') {
+        file_name[pos - 1] = '\0';
+    } else {
+        file_name[pos] = '\0';
+    }
+    if (s[0]) {
+        s++;
+        pos++;
+    }
+    while (s[0] && isspace(s[0])) {
+        s++;
+        pos++;
+    }
+    (*command_line) += pos;
+}
+
+void get_file_nameW(CHAR** command_line, WCHAR* filename, int max_filename)
+{
+    CHAR filenameA[_MAX_PATH];
+    int len;
+
+    get_file_nameA(command_line, filenameA, _MAX_PATH);
+    len = strlen(filenameA);
+    OemToCharBuffW(filenameA, filename, max_filename);
+    filename[len] = _T('\0');
+/*
+    UNICODE_STRING UnicodeString;
+    ANSI_STRING AnsiString;
+    CHAR filenameA[_MAX_PATH];
+
+    get_file_nameA(command_line, filenameA, _MAX_PATH);
+
+    //RtlInitAnsiString(&AnsiString, filenameA);
+    UnicodeString.Buffer = filename;
+    UnicodeString.MaximumLength = max_filename;//MAX_PATH;
+    RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
+ */
+}
+
+/******************************************************************************
+ * Converts a hex representation of a DWORD into a DWORD.
+ */
+DWORD convertHexToDWord(TCHAR* str, BYTE* buf)
+{
+    DWORD dw;
+    TCHAR xbuf[9];
+
+    memcpy(xbuf, str, 8 * sizeof(TCHAR));
+    xbuf[88 * sizeof(TCHAR)] = '\0';
+    _stscanf(xbuf, _T("%08lx"), &dw);
+    memcpy(buf, &dw, sizeof(DWORD));
+    return sizeof(DWORD);
+}
+
+/******************************************************************************
+ * Converts a hex buffer into a hex comma separated values
+ */
+TCHAR* convertHexToHexCSV(BYTE* buf, ULONG bufLen)
+{
+    TCHAR* str;
+    TCHAR* ptrStr;
+    BYTE* ptrBuf;
+
+    ULONG current = 0;
+    str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2*sizeof(TCHAR));
+    memset(str, 0, (bufLen+1)*2);
+    ptrStr = str;  /* Pointer to result  */
+    ptrBuf = buf;  /* Pointer to current */
+    while (current < bufLen) {
+        BYTE bCur = ptrBuf[current++];
+        TCHAR res[3];
+        _stprintf(res, _T("%02x"), (unsigned int)*&bCur);
+        _tcscat(str, res);
+        _tcscat(str, _T(","));
+    }
+    /* Get rid of the last comma */
+    str[_tcslen(str)-1] = _T('\0');
+    return str;
+}
+
+/******************************************************************************
+ * Converts a hex buffer into a DWORD string
+ */
+TCHAR* convertHexToDWORDStr(BYTE* buf, ULONG bufLen)
+{
+    TCHAR* str;
+    DWORD dw;
+
+    if (bufLen != sizeof(DWORD)) return NULL;
+    str = HeapAlloc(GetProcessHeap(), 0, ((bufLen*2)+1)*sizeof(TCHAR));
+    memcpy(&dw, buf, sizeof(DWORD));
+    _stprintf(str, _T("%08lx"), dw);
+    /* Get rid of the last comma */
+    return str;
+}
+
+/******************************************************************************
+ * Converts a hex comma separated values list into a hex list.
+ * The Hex input string must be in exactly the correct form.
+ */
+DWORD convertHexCSVToHex(TCHAR* str, BYTE* buf, ULONG bufLen)
+{
+    TCHAR* s = str;  /* Pointer to current */
+    CHAR* b = buf;  /* Pointer to result  */
+    ULONG strLen    = _tcslen(str);
+    ULONG strPos    = 0;
+    DWORD byteCount = 0;
+
+    memset(buf, 0, bufLen);
+    /*
+     * warn the user if we are here with a string longer than 2 bytes that does
+     * not contains ",".  It is more likely because the data is invalid.
+     */
+    if ((strLen > 2) && (_tcschr(str, _T(',')) == NULL)) {
+        _tprintf(_T("WARNING converting CSV hex stream with no comma, ") \
+                 _T("input data seems invalid.\n"));
+    }
+    if (strLen > 3*bufLen) {
+        _tprintf(_T("ERROR converting CSV hex stream.  Too long\n"));
+    }
+    while (strPos < strLen) {
+        TCHAR xbuf[3];
+        TCHAR wc;
+        memcpy(xbuf, s, 2);
+        xbuf[3] = _T('\0');
+        _stscanf(xbuf, _T("%02x"), (UINT*)&wc);
+        if (byteCount < bufLen)
+            *b++ = (unsigned char)wc;
+        s += 3;
+        strPos += 3;
+        ++byteCount;
+    }
+    return byteCount;
+}
+
+/******************************************************************************
+ * This function returns the HKEY associated with the data type encoded in the
+ * value.  It modifies the input parameter (key value) in order to skip this
+ * "now useless" data type information.
+ *
+ * Note: Updated based on the algorithm used in 'server/registry.c'
+ */
+DWORD getDataType(LPTSTR* lpValue, DWORD* parse_type)
+{
+    struct data_type { const TCHAR *tag; int len; int type; int parse_type; };
+
+    static const struct data_type data_types[] =
+    {                   /* actual type */  /* type to assume for parsing */
+        { _T("\""),        1,   REG_SZ,              REG_SZ },
+        { _T("str:\""),    5,   REG_SZ,              REG_SZ },
+//        { _T("str(2):\""), 8,   REG_EXPAND_SZ,       REG_SZ },
+        { _T("expand:\""), 8,   REG_EXPAND_SZ,       REG_EXPAND_SZ },
+        { _T("hex:"),      4,   REG_BINARY,          REG_BINARY },
+        { _T("dword:"),    6,   REG_DWORD,           REG_DWORD },
+        { _T("hex("),      4,   -1,                  REG_BINARY },
+        { NULL,            0,    0,                  0 }
+    };
+
+    const struct data_type *ptr;
+    int type;
+
+    for (ptr = data_types; ptr->tag; ptr++) {
+        if (memcmp(ptr->tag, *lpValue, ptr->len))
+            continue;
+
+        /* Found! */
+        *parse_type = ptr->parse_type;
+        type = ptr->type;
+        *lpValue += ptr->len;
+        if (type == -1) {
+            TCHAR* end;
+            /* "hex(xx):" is special */
+            type = (int)_tcstoul(*lpValue , &end, 16);
+            if (**lpValue == _T('\0') || *end != _T(')') || *(end+1) != _T(':')) {
+                type = REG_NONE;
+            } else {
+                *lpValue = end + 2;
+            }
+        }
+        return type;
+    }
+    return (**lpValue == _T('\0') ? REG_SZ : REG_NONE);
+}
+
+/******************************************************************************
+ * Returns an allocated buffer with a cleaned copy (removed the surrounding
+ * dbl quotes) of the passed value.
+ */
+LPTSTR getArg(LPTSTR arg)
+{
+  LPTSTR tmp = NULL;
+  ULONG len;
+
+  if (arg == NULL) return NULL;
+
+  // Get rid of surrounding quotes
+  len = _tcslen(arg);
+  if (arg[len-1] == _T('\"')) arg[len-1] = _T('\0');
+  if (arg[0]     == _T('\"')) arg++;
+  tmp = HeapAlloc(GetProcessHeap(), 0, (_tcslen(arg)+1) * sizeof(TCHAR));
+  _tcscpy(tmp, arg);
+  return tmp;
+}
+
+/******************************************************************************
+ * Replaces escape sequences with the characters.
+ */
+void REGPROC_unescape_string(LPTSTR str)
+{
+    int str_idx = 0;            /* current character under analysis */
+    int val_idx = 0;            /* the last character of the unescaped string */
+    int len = _tcslen(str);
+    for (str_idx = 0; str_idx < len; str_idx++, val_idx++) {
+        if (str[str_idx] == _T('\\')) {
+            str_idx++;
+            switch (str[str_idx]) {
+            case _T('n'):
+                str[val_idx] = _T('\n');
+                break;
+            case _T('\\'):
+            case _T('"'):
+                str[val_idx] = str[str_idx];
+                break;
+            default:
+                _tprintf(_T("Warning! Unrecognized escape sequence: \\%c'\n"), str[str_idx]);
+                str[val_idx] = str[str_idx];
+                break;
+            }
+        } else {
+            str[val_idx] = str[str_idx];
+        }
+    }
+    str[val_idx] = _T('\0');
+}
+
+/******************************************************************************
+ * Sets the value with name val_name to the data in val_data for the currently
+ * opened key.
+ *
+ * Parameters:
+ * val_name - name of the registry value
+ * val_data - registry value data
+ */
+HRESULT setValue(LPTSTR val_name, LPTSTR val_data)
+{
+  HRESULT hRes;
+  DWORD   dwDataType, dwParseType;
+  LPBYTE lpbData;
+  BYTE   convert[KEY_MAX_LEN];
+  BYTE *bBigBuffer = 0;
+  DWORD  dwLen;
+
+  if ((val_name == NULL) || (val_data == NULL))
+    return ERROR_INVALID_PARAMETER;
+
+  /* Get the data type stored into the value field */
+  dwDataType = getDataType(&val_data, &dwParseType);
+
+//  if (dwParseType == REG_EXPAND_SZ) {
+//  }
+//  if (dwParseType == REG_SZ || dwParseType == REG_EXPAND_SZ) { /* no conversion for string */
+
+  if (dwParseType == REG_SZ) {       /* no conversion for string */
+    dwLen = _tcslen(val_data);
+    if (dwLen > 0 && val_data[dwLen-1] == _T('"')) {
+      dwLen--;
+      val_data[dwLen] = _T('\0');
+    }
+    dwLen++;
+    dwLen *= sizeof(TCHAR);
+    REGPROC_unescape_string(val_data);
+    lpbData = val_data;
+  } else if (dwParseType == REG_DWORD) { /* Convert the dword types */
+    dwLen   = convertHexToDWord(val_data, convert);
+    lpbData = convert;
+  } else {                               /* Convert the hexadecimal types */
+    int b_len = _tcslen(val_data)+2/3;
+    if (b_len > KEY_MAX_LEN) {
+      bBigBuffer = HeapAlloc (GetProcessHeap(), 0, b_len * sizeof(TCHAR));
+      if (bBigBuffer == NULL) {
+          return ERROR_REGISTRY_IO_FAILED;
+      }
+      CHECK_ENOUGH_MEMORY(bBigBuffer);
+      dwLen = convertHexCSVToHex(val_data, bBigBuffer, b_len);
+      lpbData = bBigBuffer;
+    } else {
+      dwLen   = convertHexCSVToHex(val_data, convert, KEY_MAX_LEN);
+      lpbData = convert;
+    }
+  }
+  hRes = RegSetValueEx(currentKeyHandle, val_name,
+          0, /* Reserved */dwDataType, lpbData, dwLen);
+
+    _tprintf(_T("  Value: %s, Data: %s\n"), val_name, lpbData);
+
+
+  if (bBigBuffer)
+      HeapFree(GetProcessHeap(), 0, bBigBuffer);
+  return hRes;
+}
+
+
+/******************************************************************************
+ * Open the key
+ */
+HRESULT openKey(LPTSTR stdInput)
+{
+  DWORD   dwDisp;
+  HRESULT hRes;
+
+  /* Sanity checks */
+  if (stdInput == NULL)
+    return ERROR_INVALID_PARAMETER;
+
+  /* Get the registry class */
+  currentKeyClass = getRegClass(stdInput); /* Sets global variable */
+  if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
+    return (HRESULT)ERROR_INVALID_PARAMETER;
+
+  /* Get the key name */
+  currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
+  if (currentKeyName == NULL)
+    return ERROR_INVALID_PARAMETER;
+
+  hRes = RegCreateKeyEx(
+          currentKeyClass,          /* Class     */
+          currentKeyName,           /* Sub Key   */
+          0,                        /* MUST BE 0 */
+          NULL,                     /* object type */
+          REG_OPTION_NON_VOLATILE,  /* option, REG_OPTION_NON_VOLATILE ... */
+          KEY_ALL_ACCESS,           /* access mask, KEY_ALL_ACCESS */
+          NULL,                     /* security attribute */
+          &currentKeyHandle,        /* result */
+          &dwDisp);                 /* disposition, REG_CREATED_NEW_KEY or
+                                                    REG_OPENED_EXISTING_KEY */
+
+  if (hRes == ERROR_SUCCESS)
+    bTheKeyIsOpen = TRUE;
+
+  return hRes;
+
+}
+
+/******************************************************************************
+ * Extracts from [HKEY\some\key\path] or HKEY\some\key\path types of line
+ * the key name (what starts after the first '\')
+ */
+LPTSTR getRegKeyName(LPTSTR lpLine)
+{
+  LPTSTR keyNameBeg;
+  TCHAR  lpLineCopy[KEY_MAX_LEN];
+
+  if (lpLine == NULL)
+    return NULL;
+
+  _tcscpy(lpLineCopy, lpLine);
+  keyNameBeg = _tcschr(lpLineCopy, _T('\\'));    /* The key name start by '\' */
+  if (keyNameBeg) {
+      LPTSTR keyNameEnd;
+
+      keyNameBeg++;                             /* is not part of the name */
+      keyNameEnd = _tcschr(lpLineCopy, _T(']'));
+      if (keyNameEnd) {
+          *keyNameEnd = _T('\0');               /* remove ']' from the key name */
+      }
+  } else {
+      keyNameBeg = lpLineCopy + _tcslen(lpLineCopy); /* branch - empty string */
+  }
+  currentKeyName = HeapAlloc(GetProcessHeap(), 0, (_tcslen(keyNameBeg)+1)*sizeof(TCHAR));
+  CHECK_ENOUGH_MEMORY(currentKeyName);
+  _tcscpy(currentKeyName, keyNameBeg);
+  return currentKeyName;
+}
+
+/******************************************************************************
+ * Extracts from [HKEY\some\key\path] or HKEY\some\key\path types of line
+ * the key class (what ends before the first '\')
+ */
+HKEY getRegClass(LPTSTR lpClass)
+{
+  LPTSTR classNameEnd;
+  LPTSTR classNameBeg;
+  int i;
+
+  TCHAR lpClassCopy[KEY_MAX_LEN];
+
+  if (lpClass == NULL)
+    return (HKEY)ERROR_INVALID_PARAMETER;
+
+  _tcsncpy(lpClassCopy, lpClass, KEY_MAX_LEN);
+
+  classNameEnd  = _tcschr(lpClassCopy, _T('\\'));    /* The class name ends by '\' */
+  if (!classNameEnd) {                          /* or the whole string */
+      classNameEnd = lpClassCopy + _tcslen(lpClassCopy);
+      if (classNameEnd[-1] == _T(']')) {
+          classNameEnd--;
+      }
+  }
+  *classNameEnd = _T('\0');                       /* Isolate the class name */
+  if (lpClassCopy[0] == _T('[')) {
+      classNameBeg = lpClassCopy + 1;
+  } else {
+      classNameBeg = lpClassCopy;
+  }
+  for (i = 0; i < REG_CLASS_NUMBER; i++) {
+      if (!_tcscmp(classNameBeg, reg_class_names[i])) {
+          return reg_class_keys[i];
+      }
+  }
+  return (HKEY)ERROR_INVALID_PARAMETER;
+}
+
+/******************************************************************************
+ * Close the currently opened key.
+ */
+void closeKey(VOID)
+{
+    RegCloseKey(currentKeyHandle);
+    HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
+    bTheKeyIsOpen    = FALSE;
+    currentKeyName   = NULL;
+    currentKeyClass  = 0;
+    currentKeyHandle = 0;
+}
+
+/******************************************************************************
+ * This function is the main entry point to the setValue type of action.  It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doSetValue(LPTSTR stdInput)
+{
+  /*
+   * We encountered the end of the file, make sure we
+   * close the opened key and exit
+   */
+  if (stdInput == NULL) {
+    if (bTheKeyIsOpen != FALSE)
+      closeKey();
+    return;
+  }
+
+  if (stdInput[0] == _T('[')) {     /* We are reading a new key */
+      if (bTheKeyIsOpen != FALSE) {
+          closeKey();                    /* Close the previous key before */
+      }
+      if (openKey(stdInput) != ERROR_SUCCESS) {
+          _tprintf(_T("doSetValue failed to open key %s\n"), stdInput);
+      }
+  } else if ((bTheKeyIsOpen) &&
+            ((stdInput[0] == _T('@')) || /* reading a default @=data pair */
+             (stdInput[0] == _T('\"')))) { /* reading a new value=data pair */
+    processSetValue(stdInput);
+  } else {             /* since we are assuming that the file format is */
+    if (bTheKeyIsOpen) /* valid we must be reading a blank line which  */
+      closeKey();      /* indicate end of this key processing */
+  }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the queryValue type of action.  It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doQueryValue(LPTSTR stdInput) {
+  /*
+   * We encoutered the end of the file, make sure we
+   * close the opened key and exit
+   */
+  if (stdInput == NULL) {
+    if (bTheKeyIsOpen != FALSE)
+      closeKey();
+    return;
+  }
+
+  if (stdInput[0] == _T('[')) {     /* We are reading a new key */
+    if (bTheKeyIsOpen != FALSE)
+      closeKey();                    /* Close the previous key before */
+    if (openKey(stdInput) != ERROR_SUCCESS ) {
+      _tprintf(_T("doQueryValue failed to open key %s\n"), stdInput);
+    }
+  }
+  else if( (bTheKeyIsOpen) &&
+           ((stdInput[0] == _T('@')) || /* reading a default @=data pair */
+           (stdInput[0] == _T('\"')))) { /* reading a new value=data pair */
+    processQueryValue(stdInput);
+  } else {                /* since we are assuming that the file format is */
+    if (bTheKeyIsOpen)    /* valid we must be reading a blank line which  */
+      closeKey();         /* indicate end of this key processing */
+  }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the deletetValue type of action.  It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doDeleteValue(LPTSTR line) {
+  _tprintf(_T("deleteValue not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the deleteKey type of action.  It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doDeleteKey(LPTSTR line)   {
+  _tprintf(_T("deleteKey not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the createKey type of action.  It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doCreateKey(LPTSTR line)   {
+  _tprintf(_T("createKey not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This function is a wrapper for the setValue function.  It prepares the
+ * land and clean the area once completed.
+ * Note: this function modifies the line parameter.
+ *
+ * line - registry file unwrapped line. Should have the registry value name and
+ *      complete registry value data.
+ */
+void processSetValue(LPTSTR line)
+{
+  LPTSTR val_name;                   /* registry value name   */
+  LPTSTR val_data;                   /* registry value data   */
+
+  int line_idx = 0;                 /* current character under analysis */
+  HRESULT hRes = 0;
+
+  /* get value name */
+  if (line[line_idx] == _T('@') && line[line_idx + 1] == _T('=')) {
+      line[line_idx] = _T('\0');
+      val_name = line;
+      line_idx++;
+  } else if (line[line_idx] == _T('\"')) {
+      line_idx++;
+      val_name = line + line_idx;
+      while (TRUE) {
+          if (line[line_idx] == _T('\\')) {  /* skip escaped character */
+              line_idx += 2;
+          } else {
+              if (line[line_idx] == _T('\"')) {
+                  line[line_idx] = _T('\0');
+                  line_idx++;
+                  break;
+              } else {
+                  line_idx++;
+              }
+          }
+      }
+      if (line[line_idx] != _T('=')) {
+          line[line_idx] = _T('\"');
+          _tprintf(_T("Warning! uncrecognized line:\n%s\n"), line);
+          return;
+      }
+  } else {
+      _tprintf(_T("Warning! unrecognized line:\n%s\n"), line);
+      return;
+  }
+  line_idx++;                   /* skip the '=' character */
+  val_data = line + line_idx;
+  REGPROC_unescape_string(val_name);
+
+    _tprintf(_T("Key: %s, Value: %s, Data: %s\n"), currentKeyName, val_name, val_data);
+
+  hRes = setValue(val_name, val_data);
+  if (hRes != ERROR_SUCCESS) {
+    _tprintf(_T("ERROR Key %s not created. Value: %s, Data: %s\n"), currentKeyName, val_name, val_data);
+  }
+}
+
+/******************************************************************************
+ * This function is a wrapper for the queryValue function.  It prepares the
+ * land and clean the area once completed.
+ */
+void processQueryValue(LPTSTR cmdline)
+{
+  _tprintf(_T("ERROR!!! - temporary disabled"));
+  //exit(1);
+  return;
+#if 0
+  LPSTR   argv[QUERY_VALUE_MAX_ARGS];/* args storage    */
+  LPSTR   token      = NULL;         /* current token analized */
+  ULONG   argCounter = 0;            /* counter of args */
+  INT     counter;
+  HRESULT hRes       = 0;
+  LPSTR   keyValue   = NULL;
+  LPSTR   lpsRes     = NULL;
+
+  /*
+   * Init storage and parse the line
+   */
+  for (counter = 0; counter < QUERY_VALUE_MAX_ARGS; counter++)
+    argv[counter] = NULL;
+
+  while ((token = getToken(&cmdline, queryValueDelim[argCounter])) != NULL) {
+    argv[argCounter++] = getArg(token);
+    if (argCounter == QUERY_VALUE_MAX_ARGS)
+      break;  /* Stop processing args no matter what */
+  }
+
+  /* The value we look for is the first token on the line */
+  if (argv[0] == NULL)
+    return; /* SHOULD NOT HAPPEN */
+  else
+    keyValue = argv[0];
+
+  if ((keyValue[0] == '@') && (_tcslen(keyValue) == 1)) {
+    LONG lLen = KEY_MAX_LEN;
+    TCHAR* lpsData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
+    /*
+     * We need to query the key default value
+     */
+    hRes = RegQueryValue(currentKeyHandle, currentKeyName, (LPBYTE)lpsData, &lLen);
+    if (hRes == ERROR_MORE_DATA) {
+        lpsData = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpsData, lLen);
+        hRes = RegQueryValue(currentKeyHandle, currentKeyName, (LPBYTE)lpsData, &lLen);
+    }
+    if (hRes == ERROR_SUCCESS) {
+      lpsRes = HeapAlloc(GetProcessHeap(), 0, lLen);
+      strncpy(lpsRes, lpsData, lLen);
+      lpsRes[lLen-1]='\0';
+    }
+  } else {
+    DWORD dwLen = KEY_MAX_LEN;
+    BYTE* lpbData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KEY_MAX_LEN);
+    DWORD dwType;
+    /*
+     * We need to query a specific value for the key
+     */
+    hRes = RegQueryValueEx(
+             currentKeyHandle,
+             keyValue,
+             0,
+             &dwType,
+             (LPBYTE)lpbData,
+             &dwLen);
+
+    if (hRes == ERROR_MORE_DATA) {
+        lpbData = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpbData, dwLen * sizeof(TCHAR));
+        hRes = RegQueryValueEx(currentKeyHandle, keyValue, NULL, &dwType, (LPBYTE)lpbData, &dwLen);
+    }
+
+    if (hRes == ERROR_SUCCESS) {
+      /*
+       * Convert the returned data to a displayable format
+       */
+      switch (dwType) {
+        case REG_SZ:
+        case REG_EXPAND_SZ:
+          lpsRes = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(TCHAR));
+          strncpy(lpsRes, lpbData, dwLen);
+          lpsRes[dwLen-1] = '\0';
+          break;
+        case REG_DWORD:
+          lpsRes = convertHexToDWORDStr(lpbData, dwLen);
+          break;
+        default:
+          lpsRes = convertHexToHexCSV(lpbData, dwLen);
+          break;
+      }
+    }
+
+    HeapFree(GetProcessHeap(), 0, lpbData);
+  }
+  if (hRes == ERROR_SUCCESS) {
+    _tprintf(_T("Value \"%s\" = \"%s\" in key [%s]\n"), keyValue, lpsRes, currentKeyName);
+
+  } else {
+    _tprintf(_T("ERROR Value \"%s\" not found. for key \"%s\"\n"), keyValue, currentKeyName);
+  }
+
+  /*
+   * Do some cleanup
+   */
+  for (counter=0; counter<argCounter; counter++)
+    if (argv[counter] != NULL)
+      HeapFree(GetProcessHeap(), 0, argv[counter]);
+
+  if (lpsRes != NULL)
+    HeapFree(GetProcessHeap(), 0, lpsRes);
+#endif
+}
+
+/******************************************************************************
+ * Calls command for each line of a registry file.
+ * Correctly processes comments (in # form), line continuation.
+ *
+ * Parameters:
+ *   in - input stream to read from
+ *   command - command to be called for each line
+ */
+void processRegLines(FILE *in, CommandAPI command)
+{
+    LPTSTR line     = NULL;  /* line read from input stream */
+    ULONG lineSize = REG_VAL_BUF_SIZE;
+
+    line = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(TCHAR));
+    CHECK_ENOUGH_MEMORY(line);
+
+    while (!feof(in)) {
+        LPTSTR s; /* The pointer into line for where the current fgets should read */
+        s = line;
+        for (;;) {
+            size_t size_remaining;
+            int size_to_get;
+            TCHAR *s_eol; /* various local uses */
+
+            /* Do we need to expand the buffer ? */
+            assert (s >= line && s <= line + lineSize);
+            size_remaining = lineSize - (s-line);
+            if (size_remaining < 2) { /* room for 1 character and the \0 */
+                TCHAR *new_buffer;
+                size_t new_size = lineSize + REG_VAL_BUF_SIZE;
+                if (new_size > lineSize) /* no arithmetic overflow */
+                    new_buffer = HeapReAlloc (GetProcessHeap(), 0, line, new_size * sizeof(TCHAR));
+                else
+                    new_buffer = NULL;
+                CHECK_ENOUGH_MEMORY(new_buffer);
+                line = new_buffer;
+                s = line + lineSize - size_remaining;
+                lineSize = new_size;
+                size_remaining = lineSize - (s-line);
+            }
+
+            /* Get as much as possible into the buffer, terminated either by
+             * eof, error, eol or getting the maximum amount.  Abort on error.
+             */
+//
+// This line is surely foobar, don't want to read INT_MAX in buffer at s, it's never going to be that big...
+//            size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
+//
+// Looks as if 'lineSize' contains the number of characters of buffer size
+//
+            size_to_get = (size_remaining > lineSize ? lineSize : size_remaining);
+
+            if (NULL == _fgetts(s, size_to_get, in)) {
+                if (ferror(in)) {
+                    //_tperror(_T("While reading input"));
+                    perror ("While reading input");
+                    //exit(IO_ERROR);
+                    return;
+                } else {
+                    assert (feof(in));
+                    *s = _T('\0');
+                    /* It is not clear to me from the definition that the
+                     * contents of the buffer are well defined on detecting
+                     * an eof without managing to read anything.
+                     */
+                }
+            }
+
+            /* If we didn't read the eol nor the eof go around for the rest */
+            s_eol = _tcschr (s, _T('\n'));
+            if (!feof (in) && !s_eol) {
+                s = _tcschr (s, _T('\0'));
+                /* It should be s + size_to_get - 1 but this is safer */
+                continue;
+            }
+
+            /* If it is a comment line then discard it and go around again */
+            if (line [0] == _T('#')) {
+                s = line;
+                continue;
+            }
+
+            /* Remove any line feed.  Leave s_eol on the \0 */
+            if (s_eol) {
+                *s_eol = _T('\0');
+                if (s_eol > line && *(s_eol-1) == _T('\r'))
+                    *--s_eol = _T('\0');
+            } else {
+                s_eol = _tcschr (s, _T('\0'));
+            }
+            /* If there is a concatenating \\ then go around again */
+            if (s_eol > line && *(s_eol-1) == _T('\\')) {
+                int c;
+                s = s_eol-1;
+                /* The following error protection could be made more self-
+                 * correcting but I thought it not worth trying.
+                 */
+
+                if ((c = _fgettc(in)) == _TEOF || c != _T(' ') ||
+                    (c = _fgettc(in)) == _TEOF || c != _T(' '))
+                    _tprintf(_T("ERROR - invalid continuation.\n"));
+                continue;
+            }
+            break; /* That is the full virtual line */
+        }
+        command(line);
+    }
+    command(NULL);
+    HeapFree(GetProcessHeap(), 0, line);
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the registerDLL action.  It
+ * receives the currently read line, then loads and registers the requested DLLs
+ */
+void doRegisterDLL(LPTSTR stdInput)
+{
+    HMODULE theLib = 0;
+    UINT retVal = 0;
+
+    /* Check for valid input */
+    if (stdInput == NULL) return;
+
+    /* Load and register the library, then free it */
+    theLib = LoadLibrary(stdInput);
+    if (theLib) {
+        FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
+        if (lpfnDLLRegProc) {
+            retVal = (*lpfnDLLRegProc)();
+        } else {
+            _tprintf(_T("Couldn't find DllRegisterServer proc in '%s'.\n"), stdInput);
+        }
+        if (retVal != S_OK) {
+            _tprintf(_T("Couldn't find DllRegisterServer proc in '%s'.\n"), stdInput);
+        }
+        FreeLibrary(theLib);
+    } else {
+        _tprintf(_T("Could not load DLL '%s'.\n"), stdInput);
+    }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the unregisterDLL action.  It
+ * receives the currently read line, then loads and unregisters the requested DLLs
+ */
+void doUnregisterDLL(LPTSTR stdInput)
+{
+    HMODULE theLib = 0;
+    UINT retVal = 0;
+
+    /* Check for valid input */
+    if (stdInput == NULL) return;
+
+    /* Load and unregister the library, then free it */
+    theLib = LoadLibrary(stdInput);
+    if (theLib) {
+        FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
+        if (lpfnDLLRegProc) {
+            retVal = (*lpfnDLLRegProc)();
+        } else {
+            _tprintf(_T("Couldn't find DllUnregisterServer proc in '%s'.\n"), stdInput);
+        }
+        if (retVal != S_OK) {
+            _tprintf(_T("DLLUnregisterServer error 0x%x in '%s'.\n"), retVal, stdInput);
+        }
+        FreeLibrary(theLib);
+    } else {
+        _tprintf(_T("Could not load DLL '%s'.\n"), stdInput);
+    }
+}
+
+/****************************************************************************
+ * REGPROC_print_error
+ *
+ * Print the message for GetLastError
+ */
+
+void REGPROC_print_error(VOID)
+{
+    LPVOID lpMsgBuf;
+    DWORD error_code;
+    int status;
+
+    error_code = GetLastError ();
+    status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                           NULL, error_code, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
+    if (!status) {
+        _tprintf(_T("Cannot display message for error %ld, status %ld\n"), error_code, GetLastError());
+    } else {
+        _tprintf(_T("REGPROC_print_error() - "));
+        puts(lpMsgBuf);
+        LocalFree((HLOCAL)lpMsgBuf);
+    }
+    //exit(1);
+}
+
+/******************************************************************************
+ * Checks whether the buffer has enough room for the string or required size.
+ * Resizes the buffer if necessary.
+ *
+ * Parameters:
+ * buffer - pointer to a buffer for string
+ * len - current length of the buffer in characters.
+ * required_len - length of the string to place to the buffer in characters.
+ *   The length does not include the terminating null character.
+ */
+void REGPROC_resize_char_buffer(TCHAR **buffer, DWORD *len, DWORD required_len)
+{
+    required_len++;
+    if (required_len > *len) {
+        *len = required_len;
+        *buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *len * sizeof(**buffer));
+        CHECK_ENOUGH_MEMORY(*buffer);
+    }
+}
+
+/******************************************************************************
+ * Prints string str to file
+ */
+void REGPROC_export_string(FILE *file, TCHAR *str)
+{
+    size_t len = _tcslen(str);
+    size_t i;
+
+    /* escaping characters */
+    for (i = 0; i < len; i++) {
+        TCHAR c = str[i];
+        switch (c) {
+        //case _T('\\'): _fputts(_T("\\\\"), file); break;
+        case _T('\"'): _fputts(_T("\\\""), file); break;
+        case _T('\n'): _fputts(_T("\\\n"), file); break;
+        default:       _fputtc(c, file);          break;
+        }
+    }
+}
+
+/******************************************************************************
+ * Writes contents of the registry key to the specified file stream.
+ *
+ * Parameters:
+ * file - writable file stream to export registry branch to.
+ * key - registry branch to export.
+ * reg_key_name_buf - name of the key with registry class.
+ *      Is resized if necessary.
+ * reg_key_name_len - length of the buffer for the registry class in characters.
+ * val_name_buf - buffer for storing value name.
+ *      Is resized if necessary.
+ * val_name_len - length of the buffer for storing value names in characters.
+ * val_buf - buffer for storing values while extracting.
+ *      Is resized if necessary.
+ * val_size - size of the buffer for storing values in bytes.
+ */
+void export_hkey(FILE *file, HKEY key,
+                 TCHAR **reg_key_name_buf, DWORD *reg_key_name_len,
+                 TCHAR **val_name_buf, DWORD *val_name_len,
+                 BYTE **val_buf, DWORD *val_size)
+{
+    DWORD max_sub_key_len;
+    DWORD max_val_name_len;
+    DWORD max_val_size;
+    DWORD curr_len;
+    DWORD i;
+    BOOL more_data;
+    LONG ret;
+
+    /* get size information and resize the buffers if necessary */
+    if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL,
+                        NULL, &max_val_name_len, &max_val_size, NULL, NULL) != ERROR_SUCCESS) {
+        REGPROC_print_error();
+    }
+    curr_len = _tcslen(*reg_key_name_buf);
+    REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1);
+    REGPROC_resize_char_buffer(val_name_buf, val_name_len, max_val_name_len);
+    if (max_val_size > *val_size) {
+        *val_size = max_val_size;
+        *val_buf = HeapReAlloc(GetProcessHeap(), 0, *val_buf, *val_size * sizeof(TCHAR));
+        CHECK_ENOUGH_MEMORY(val_buf);
+    }
+    /* output data for the current key */
+    _fputts(_T("\n["), file);
+    _fputts(*reg_key_name_buf, file);
+    _fputts(_T("]\n"), file);
+    /* print all the values */
+    i = 0;
+    more_data = TRUE;
+    while (more_data) {
+        DWORD value_type;
+        DWORD val_name_len1 = *val_name_len;
+        DWORD val_size1 = *val_size;
+        ret = RegEnumValue(key, i, *val_name_buf, &val_name_len1, NULL, &value_type, *val_buf, &val_size1);
+        if (ret != ERROR_SUCCESS) {
+            more_data = FALSE;
+            if (ret != ERROR_NO_MORE_ITEMS) {
+                REGPROC_print_error();
+            }
+        } else {
+            i++;
+            if ((*val_name_buf)[0]) {
+                _fputts(_T("\""), file);
+                REGPROC_export_string(file, *val_name_buf);
+                _fputts(_T("\"="), file);
+            } else {
+                _fputts(_T("@="), file);
+            }
+            switch (value_type) {
+            case REG_EXPAND_SZ:
+                _fputts(_T("expand:"), file);
+            case REG_SZ:
+                _fputts(_T("\""), file);
+                REGPROC_export_string(file, *val_buf);
+                _fputts(_T("\"\n"), file);
+                break;
+            case REG_DWORD:
+                _ftprintf(file, _T("dword:%08lx\n"), *((DWORD *)*val_buf));
+                break;
+            default:
+/*
+                _tprintf(_T("warning - unsupported registry format '%ld', ") \
+                         _T("treating as binary\n"), value_type);
+                _tprintf(_T("key name: \"%s\"\n"), *reg_key_name_buf);
+                _tprintf(_T("value name:\"%s\"\n\n"), *val_name_buf);
+ */
+                /* falls through */
+            case REG_MULTI_SZ:
+                /* falls through */
+            case REG_BINARY:
+            {
+                DWORD i1;
+                TCHAR *hex_prefix;
+                TCHAR buf[20];
+                int cur_pos;
+
+                if (value_type == REG_BINARY) {
+                    hex_prefix = _T("hex:");
+                } else {
+                    hex_prefix = buf;
+                    _stprintf(buf, _T("hex(%ld):"), value_type);
+                }
+                /* position of where the next character will be printed */
+                /* NOTE: yes, _tcslen("hex:") is used even for hex(x): */
+                cur_pos = _tcslen(_T("\"\"=")) + _tcslen(_T("hex:")) +
+                    _tcslen(*val_name_buf);
+                _fputts(hex_prefix, file);
+                for (i1 = 0; i1 < val_size1; i1++) {
+                    _ftprintf(file, _T("%02x"), (unsigned int)(*val_buf)[i1]);
+                    if (i1 + 1 < val_size1) {
+                        _fputts(_T(","), file);
+                    }
+                    cur_pos += 3;
+                    /* wrap the line */
+                    if (cur_pos > REG_FILE_HEX_LINE_LEN) {
+                        _fputts(_T("\\\n  "), file);
+                        cur_pos = 2;
+                    }
+                }
+                _fputts(_T("\n"), file);
+                break;
+            }
+            }
+        }
+    }
+    i = 0;
+    more_data = TRUE;
+    (*reg_key_name_buf)[curr_len] = _T('\\');
+    while (more_data) {
+        DWORD buf_len = *reg_key_name_len - curr_len;
+        ret = RegEnumKeyEx(key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL);
+        if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
+            more_data = FALSE;
+            if (ret != ERROR_NO_MORE_ITEMS) {
+                REGPROC_print_error();
+            }
+        } else {
+            HKEY subkey;
+
+            i++;
+            if (RegOpenKey(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) {
+                export_hkey(file, subkey, reg_key_name_buf, reg_key_name_len, val_name_buf, val_name_len, val_buf, val_size);
+                RegCloseKey(subkey);
+            } else {
+                REGPROC_print_error();
+            }
+        }
+    }
+    (*reg_key_name_buf)[curr_len] = _T('\0');
+}
+/*
+#define REG_NONE                    ( 0 )   // No value type
+#define REG_SZ                      ( 1 )   // Unicode nul terminated string
+#define REG_EXPAND_SZ               ( 2 )   // Unicode nul terminated string
+                                            // (with environment variable references)
+#define REG_BINARY                  ( 3 )   // Free form binary
+#define REG_DWORD                   ( 4 )   // 32-bit number
+#define REG_DWORD_LITTLE_ENDIAN     ( 4 )   // 32-bit number (same as REG_DWORD)
+#define REG_DWORD_BIG_ENDIAN        ( 5 )   // 32-bit number
+#define REG_LINK                    ( 6 )   // Symbolic Link (unicode)
+#define REG_MULTI_SZ                ( 7 )   // Multiple Unicode strings
+#define REG_RESOURCE_LIST           ( 8 )   // Resource list in the resource map
+#define REG_FULL_RESOURCE_DESCRIPTOR ( 9 )  // Resource list in the hardware description
+#define REG_RESOURCE_REQUIREMENTS_LIST ( 10 )
+
+ */
+/******************************************************************************
+ * Open file for export.
+ */
+FILE *REGPROC_open_export_file(TCHAR *file_name)
+{
+//_CRTIMP FILE * __cdecl _wfopen(const wchar_t *, const wchar_t *);
+
+//FILE*        fopen (const char* szFileName, const char* szMode);
+//FILE*        _wfopen(const wchar_t *file, const wchar_t *mode);
+
+    FILE *file = _tfopen(file_name, _T("w"));
+    if (!file) {
+        perror("");
+        _tprintf(_T("REGPROC_open_export_file(%s) - Can't open file.\n"), file_name);
+        //exit(1);
+        return NULL;
+    }
+    _fputts(_T("REGEDIT4\n"), file);
+    return file;
+}
+
+/******************************************************************************
+ * Writes contents of the registry key to the specified file stream.
+ *
+ * Parameters:
+ * file_name - name of a file to export registry branch to.
+ * reg_key_name - registry branch to export. The whole registry is exported if
+ *      reg_key_name is NULL or contains an empty string.
+ */
+BOOL export_registry_key(TCHAR* file_name, TCHAR* reg_key_name)
+{
+    HKEY reg_key_class;
+
+    TCHAR *reg_key_name_buf;
+    TCHAR *val_name_buf;
+    BYTE *val_buf;
+    DWORD reg_key_name_len = KEY_MAX_LEN;
+    DWORD val_name_len = KEY_MAX_LEN;
+    DWORD val_size = REG_VAL_BUF_SIZE;
+    FILE *file = NULL;
+
+    //_tprintf(_T("export_registry_key(%s, %s)\n"), reg_key_name, file_name);
+
+    reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_len * sizeof(*reg_key_name_buf));
+    val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_len * sizeof(*val_name_buf));
+    val_buf = HeapAlloc(GetProcessHeap(), 0, val_size);
+    CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf);
+
+    if (reg_key_name && reg_key_name[0]) {
+        TCHAR *branch_name;
+        HKEY key;
+
+        REGPROC_resize_char_buffer(&reg_key_name_buf, &reg_key_name_len,
+                                   _tcslen(reg_key_name));
+        _tcscpy(reg_key_name_buf, reg_key_name);
+
+        /* open the specified key */
+        reg_key_class = getRegClass(reg_key_name);
+        if (reg_key_class == (HKEY)ERROR_INVALID_PARAMETER) {
+            _tprintf(_T("Incorrect registry class specification in '%s\n"), reg_key_name);
+            //exit(1);
+            return FALSE;
+        }
+        branch_name = getRegKeyName(reg_key_name);
+        CHECK_ENOUGH_MEMORY(branch_name);
+        if (!branch_name[0]) {
+            /* no branch - registry class is specified */
+            file = REGPROC_open_export_file(file_name);
+            export_hkey(file, reg_key_class,
+                        &reg_key_name_buf, &reg_key_name_len,
+                        &val_name_buf, &val_name_len,
+                        &val_buf, &val_size);
+        } else if (RegOpenKey(reg_key_class, branch_name, &key) == ERROR_SUCCESS) {
+            file = REGPROC_open_export_file(file_name);
+            export_hkey(file, key,
+                        &reg_key_name_buf, &reg_key_name_len,
+                        &val_name_buf, &val_name_len,
+                        &val_buf, &val_size);
+            RegCloseKey(key);
+        } else {
+            _tprintf(_T("Can't export. Registry key '%s does not exist!\n"), reg_key_name);
+            REGPROC_print_error();
+        }
+        HeapFree(GetProcessHeap(), 0, branch_name);
+    } else {
+        int i;
+
+        /* export all registry classes */
+        file = REGPROC_open_export_file(file_name);
+        for (i = 0; i < REG_CLASS_NUMBER; i++) {
+            /* do not export HKEY_CLASSES_ROOT */
+            if (reg_class_keys[i] != HKEY_CLASSES_ROOT &&
+                reg_class_keys[i] != HKEY_CURRENT_USER &&
+                reg_class_keys[i] != HKEY_CURRENT_CONFIG) {
+                _tcscpy(reg_key_name_buf, reg_class_names[i]);
+                export_hkey(file, reg_class_keys[i],
+                            &reg_key_name_buf, &reg_key_name_len,
+                            &val_name_buf, &val_name_len,
+                            &val_buf, &val_size);
+            }
+        }
+    }
+    if (file) {
+        fclose(file);
+    }
+//    HeapFree(GetProcessHeap(), 0, reg_key_name);
+    HeapFree(GetProcessHeap(), 0, val_buf);
+    HeapFree(GetProcessHeap(), 0, val_name_buf);
+    HeapFree(GetProcessHeap(), 0, reg_key_name_buf);
+    return TRUE;
+}
+
+/******************************************************************************
+ * Reads contents of the specified file into the registry.
+ */
+BOOL import_registry_file(LPTSTR filename)
+{
+    FILE* reg_file = _tfopen(filename, _T("r"));
+
+    if (reg_file) {
+        processRegLines(reg_file, doSetValue);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/******************************************************************************
+ * Recursive function which removes the registry key with all subkeys.
+ */
+BOOL delete_branch(HKEY key, TCHAR** reg_key_name_buf, DWORD* reg_key_name_len)
+{
+    HKEY branch_key;
+    DWORD max_sub_key_len;
+    DWORD subkeys;
+    DWORD curr_len;
+    LONG ret;
+    long int i;
+
+    if (RegOpenKey(key, *reg_key_name_buf, &branch_key) != ERROR_SUCCESS) {
+        REGPROC_print_error();
+        return FALSE;
+    }
+
+    /* get size information and resize the buffers if necessary */
+    if (RegQueryInfoKey(branch_key, NULL, NULL, NULL, &subkeys, &max_sub_key_len,
+                        NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
+        REGPROC_print_error();
+        RegCloseKey(branch_key);
+        return FALSE;
+    }
+    curr_len = _tcslen(*reg_key_name_buf);
+    REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1);
+
+    (*reg_key_name_buf)[curr_len] = '\\';
+    for (i = subkeys - 1; i >= 0; i--) {
+        DWORD buf_len = *reg_key_name_len - curr_len;
+        ret = RegEnumKeyEx(branch_key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL);
+        if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA && ret != ERROR_NO_MORE_ITEMS) {
+            REGPROC_print_error();
+            RegCloseKey(branch_key);
+            return FALSE;
+        } else {
+            delete_branch(key, reg_key_name_buf, reg_key_name_len);
+        }
+    }
+    (*reg_key_name_buf)[curr_len] = '\0';
+    RegCloseKey(branch_key);
+    RegDeleteKey(key, *reg_key_name_buf);
+    return TRUE;
+}
+
+/******************************************************************************
+ * Removes the registry key with all subkeys. Parses full key name.
+ *
+ * Parameters:
+ * reg_key_name - full name of registry branch to delete. Ignored if is NULL,
+ *      empty, points to register key class, does not exist.
+ */
+void delete_registry_key(TCHAR* reg_key_name)
+{
+    TCHAR* branch_name;
+    DWORD branch_name_len;
+    HKEY reg_key_class;
+    HKEY branch_key;
+
+    if (!reg_key_name || !reg_key_name[0]) {
+        return;
+    }
+    /* open the specified key */
+    reg_key_class = getRegClass(reg_key_name);
+    if (reg_key_class == (HKEY)ERROR_INVALID_PARAMETER) {
+        _tprintf(_T("Incorrect registry class specification in '%s'\n"), reg_key_name);
+        //exit(1);
+        return;
+    }
+    branch_name = getRegKeyName(reg_key_name);
+    CHECK_ENOUGH_MEMORY(branch_name);
+    branch_name_len = _tcslen(branch_name);
+    if (!branch_name[0]) {
+        _tprintf(_T("Can't delete registry class '%s'\n"), reg_key_name);
+        //exit(1);
+        return;
+    }
+    if (RegOpenKey(reg_key_class, branch_name, &branch_key) == ERROR_SUCCESS) {
+        /* check whether the key exists */
+        RegCloseKey(branch_key);
+        delete_branch(reg_key_class, &branch_name, &branch_name_len);
+    }
+    HeapFree(GetProcessHeap(), 0, branch_name);
+}
+
diff --git a/apps/tests/regdump/regproc.h b/apps/tests/regdump/regproc.h
new file mode 100644 (file)
index 0000000..70215a1
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1999 Sylvain St-Germain
+ * Copyright 2002 Andriy Palamarchuk
+ *
+ * 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
+ */
+
+/******************************************************************************
+ * Defines and consts
+ */
+#define KEY_MAX_LEN             1024
+
+/* Return values */
+#define SUCCESS               0
+#define KEY_VALUE_ALREADY_SET 2
+
+typedef void (*CommandAPI)(LPTSTR lpsLine);
+
+void doSetValue(LPTSTR lpsLine);
+void doDeleteValue(LPTSTR lpsLine);
+void doCreateKey(LPTSTR lpsLine);
+void doDeleteKey(LPTSTR lpsLine);
+void doQueryValue(LPTSTR lpsLine);
+void doRegisterDLL(LPTSTR lpsLine);
+void doUnregisterDLL(LPTSTR lpsLine);
+
+BOOL export_registry_key(TCHAR* file_name, TCHAR* reg_key_name);
+BOOL import_registry_file(LPTSTR filename);
+void delete_registry_key(TCHAR* reg_key_name);
+
+void processRegLines(FILE* in, CommandAPI command);
+
+/*
+ * Generic prototypes
+ */
+#ifdef _UNICODE
+#define get_file_name get_file_nameW
+#else
+#define get_file_name get_file_nameA
+#endif
+
+char*   getToken(char** str, const char* delims);
+void    get_file_nameA(CHAR** command_line, CHAR* filename, int max_filename);
+void    get_file_nameW(CHAR** command_line, WCHAR* filename, int max_filename);
+DWORD   convertHexToDWord(TCHAR* str, BYTE* buf);
+DWORD   convertHexCSVToHex(TCHAR* str, BYTE* buf, ULONG bufLen);
+LPTSTR  convertHexToHexCSV(BYTE* buf, ULONG len);
+LPTSTR  convertHexToDWORDStr(BYTE* buf, ULONG len);
+LPTSTR  getRegKeyName(LPTSTR lpLine);
+HKEY    getRegClass(LPTSTR lpLine);
+DWORD   getDataType(LPTSTR* lpValue, DWORD* parse_type);
+LPTSTR  getArg(LPTSTR arg);
+HRESULT openKey(LPTSTR stdInput);
+void    closeKey(VOID);
+
+/*
+ * api setValue prototypes
+ */
+void    processSetValue(LPTSTR cmdline);
+HRESULT setValue(LPTSTR val_name, LPTSTR val_data);
+
+/*
+ * api queryValue prototypes
+ */
+void    processQueryValue(LPTSTR cmdline);
+
+#ifdef __GNUC__
+#ifdef WIN32_REGDBG
+//typedef UINT_PTR SIZE_T, *PSIZE_T;
+//#define _MAX_PATH   260 /* max. length of full pathname */
+#endif /*WIN32_REGDBG*/
+
+#ifdef UNICODE
+#define _tfopen     _wfopen
+#else
+#define _tfopen     fopen
+#endif
+
+#endif /*__GNUC__*/
+
+LPVOID RegHeapAlloc(
+  HANDLE hHeap,   // handle to private heap block
+  DWORD dwFlags,  // heap allocation control
+  SIZE_T dwBytes  // number of bytes to allocate
+);
+
+LPVOID RegHeapReAlloc(
+  HANDLE hHeap,   // handle to heap block
+  DWORD dwFlags,  // heap reallocation options
+  LPVOID lpMem,   // pointer to memory to reallocate
+  SIZE_T dwBytes  // number of bytes to reallocate
+);
+
+BOOL RegHeapFree(
+  HANDLE hHeap,  // handle to heap
+  DWORD dwFlags, // heap free options
+  LPVOID lpMem   // pointer to memory
+);
diff --git a/apps/tests/regtest/.cvsignore b/apps/tests/regtest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/sectest/.cvsignore b/apps/tests/sectest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/sertest/.cvsignore b/apps/tests/sertest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/shm/.cvsignore b/apps/tests/shm/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/simple/.cvsignore b/apps/tests/simple/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/tests/GetSysMetrics/.cvsignore b/apps/tests/tests/GetSysMetrics/.cvsignore
new file mode 100644 (file)
index 0000000..6deb857
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.sym
+*.exe
+*.dsp
+*.dsw
diff --git a/apps/tests/tests/GetSystemInfo/.cvsignore b/apps/tests/tests/GetSystemInfo/.cvsignore
new file mode 100644 (file)
index 0000000..0ec02ac
--- /dev/null
@@ -0,0 +1,3 @@
+*.exe
+*.o
+*.sym
diff --git a/apps/tests/tests/Mutex/.cvsignore b/apps/tests/tests/Mutex/.cvsignore
new file mode 100644 (file)
index 0000000..4666b1a
--- /dev/null
@@ -0,0 +1,2 @@
+*.exe
+*.sym
diff --git a/apps/tests/tests/Parent_Child/.cvsignore b/apps/tests/tests/Parent_Child/.cvsignore
new file mode 100644 (file)
index 0000000..737e8b5
--- /dev/null
@@ -0,0 +1,3 @@
+*.sym
+*.exe
+*.o
diff --git a/apps/tests/tests/guitest/.cvsignore b/apps/tests/tests/guitest/.cvsignore
new file mode 100644 (file)
index 0000000..0ec02ac
--- /dev/null
@@ -0,0 +1,3 @@
+*.exe
+*.o
+*.sym
diff --git a/apps/tests/tests/hello/.cvsignore b/apps/tests/tests/hello/.cvsignore
new file mode 100644 (file)
index 0000000..916ee15
--- /dev/null
@@ -0,0 +1,3 @@
+*.exe
+*.sym
+*.o
diff --git a/apps/tests/tests/hello2/.cvsignore b/apps/tests/tests/hello2/.cvsignore
new file mode 100644 (file)
index 0000000..0ec02ac
--- /dev/null
@@ -0,0 +1,3 @@
+*.exe
+*.o
+*.sym
diff --git a/apps/tests/tests/new/.cvsignore b/apps/tests/tests/new/.cvsignore
new file mode 100644 (file)
index 0000000..0ec02ac
--- /dev/null
@@ -0,0 +1,3 @@
+*.exe
+*.o
+*.sym
diff --git a/apps/tests/tests/rolex/.cvsignore b/apps/tests/tests/rolex/.cvsignore
new file mode 100644 (file)
index 0000000..343a060
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.exe
+*.sym
diff --git a/apps/tests/tests/volinfo/.cvsignore b/apps/tests/tests/volinfo/.cvsignore
new file mode 100644 (file)
index 0000000..343a060
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.exe
+*.sym
diff --git a/apps/tests/thread/.cvsignore b/apps/tests/thread/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/tokentest/.cvsignore b/apps/tests/tokentest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/vmtest/.cvsignore b/apps/tests/vmtest/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/tests/winhello/.cvsignore b/apps/tests/winhello/.cvsignore
new file mode 100644 (file)
index 0000000..e543821
--- /dev/null
@@ -0,0 +1,6 @@
+winhello.exe
+winhello.nostrip.exe
+winhello.sym
+winhello.coff
+*.d
+*.o
\ No newline at end of file
diff --git a/apps/tests/wm_paint/Listing1_1.cpp b/apps/tests/wm_paint/Listing1_1.cpp
new file mode 100644 (file)
index 0000000..00bb7ad
--- /dev/null
@@ -0,0 +1,129 @@
+
+// ------------------------------------------------------------------
+// Windows 2000 Graphics API Black Book
+// Chapter 1 - Listing 1.1 (WM_PAINT Demo)
+//
+// Created by Damon Chandler <dmc27@ee.cornell.edu>
+// Updates can be downloaded at: <www.coriolis.com>
+//
+// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu 
+// if you have any questions about this code.
+// ------------------------------------------------------------------
+
+
+//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+#include <windows.h>
+//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+
+const char* WndClassName = "GMainWnd";
+LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 
+   LPARAM LParam);
+
+
+int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance,
+    LPTSTR lpCmdLine, int nCmdShow)
+{
+   WNDCLASS wc;
+   memset(&wc, 0, sizeof(WNDCLASS));
+    
+   wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+   wc.lpfnWndProc = MainWndProc;
+   wc.hInstance = HInstance;
+   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+   wc.hbrBackground = 
+      reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);
+   wc.lpszClassName = WndClassName;
+
+   if (RegisterClass(&wc))
+   {
+      HWND HWnd = 
+         CreateWindow(WndClassName, TEXT("WM_PAINT Demo"),
+                      WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_VISIBLE,
+                      CW_USEDEFAULT, CW_USEDEFAULT, 200, 150,
+                      NULL, NULL, HInstance, NULL);
+                                 
+      if (HWnd)
+      {
+         ShowWindow(HWnd, nCmdShow);
+         UpdateWindow(HWnd);
+
+         MSG msg;
+         while (GetMessage(&msg, NULL, 0, 0))
+         {
+             TranslateMessage(&msg);
+             DispatchMessage(&msg);
+         }
+      }
+    }
+    return 0;
+}
+//------------------------------------------------------------------
+
+
+LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, 
+   LPARAM LParam)
+{
+   switch (Msg)
+   {
+      case WM_PAINT:
+      {
+         // determine the invalidated area of the window            
+         RECT RUpdate;            
+         GetUpdateRect(HWnd, &RUpdate, false);
+
+         // grab a handle to our window's
+         // common display device context
+         HDC Hdc = GetDC(HWnd);
+#if 0
+         try
+#endif
+         {
+            RECT RClient;
+            GetClientRect(HWnd, &RClient);
+
+            // set the clipping region
+            IntersectClipRect(Hdc, RUpdate.left, RUpdate.top, 
+                              RUpdate.right, RUpdate.bottom);
+
+            // fill the client area with the background brush
+            HBRUSH HBrush = 
+               reinterpret_cast<HBRUSH>(
+                  GetClassLong(HWnd, GCL_HBRBACKGROUND)
+                  );
+            FillRect(Hdc, &RClient, HBrush);
+            
+            // render the persistent text
+            const char* text = "Persistent Text"; 
+            SetTextColor(Hdc, PALETTERGB(0, 0, 255));
+            DrawText(Hdc, text, strlen(text), &RClient,
+                     DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+         }
+#if 0
+         catch (...)
+#endif
+         {
+            // release the device context
+            ReleaseDC(HWnd, Hdc);
+
+            // validate the update area            
+            ValidateRect(HWnd, &RUpdate);
+         }
+         // release the device context
+         ReleaseDC(HWnd, Hdc);
+
+         // validate the update area            
+         ValidateRect(HWnd, &RUpdate);
+
+         break;
+      }
+      case WM_DESTROY:
+      {
+         PostQuitMessage(0);
+         return 0;
+      }
+   }
+   return DefWindowProc(HWnd, Msg, WParam, LParam);
+}
+//------------------------------------------------------------------
+
diff --git a/apps/tests/wm_paint/makefile b/apps/tests/wm_paint/makefile
new file mode 100644 (file)
index 0000000..c606328
--- /dev/null
@@ -0,0 +1,66 @@
+# Makefile - Proj_Listing1_1.dsp
+
+ifndef CFG
+CFG=Proj_Listing1_1 - Win32 Debug
+endif
+CC=gcc
+CFLAGS=
+CXX=g++
+CXXFLAGS=$(CFLAGS)
+RC=windres -O COFF
+ifeq "$(CFG)"  "Proj_Listing1_1 - Win32 Release"
+CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W
+LD=$(CXX) $(CXXFLAGS)
+LDFLAGS=
+LDFLAGS+=-Wl,--subsystem,windows
+LIBS+=-lkernel32 -luser32 -lgdi32
+else
+ifeq "$(CFG)"  "Proj_Listing1_1 - Win32 Debug"
+CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W
+LD=$(CXX) $(CXXFLAGS)
+LDFLAGS=
+LDFLAGS+=-Wl,--subsystem,windows
+LIBS+=-lkernel32 -luser32 -lgdi32
+endif
+endif
+
+ifndef TARGET
+TARGET=WM_PAINT.exe
+endif
+
+.PHONY: all
+all: $(TARGET)
+
+%.o: %.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+%.o: %.cpp
+       $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+%.res: %.rc
+       $(RC) $(CPPFLAGS) -o $@ -i $<
+
+SOURCE_FILES= \
+       Listing1_1.cpp
+
+HEADER_FILES=
+
+RESOURCE_FILES=
+
+SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) 
+
+OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS)))))
+
+$(TARGET): $(OBJS)
+       $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+.PHONY: clean
+clean:
+       -del $(OBJS) $(TARGET)
+
+.PHONY: depends
+depends:
+       -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_1.dep
+
+-include Proj_Listing1_1.dep
+
diff --git a/apps/testsets/Makefile b/apps/testsets/Makefile
new file mode 100644 (file)
index 0000000..8aaf049
--- /dev/null
@@ -0,0 +1,188 @@
+#
+# ReactOS system testsets makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Testset applications
+TEST_SETS = loadlib
+
+TEST_KERNEL32 = 
+
+TEST_MSVCRT = 
+
+TEST_COM = 
+
+TEST_SEH = 
+
+TEST_REGRESSIONS = 
+
+all: $(TEST_SETS)  $(TEST_KERNEL32) $(TEST_MSVCRT) $(TEST_COM) $(TEST_SEH) $(TEST_REGRESSIONS) 
+
+depends: 
+
+implib: $(TEST_SETS:%=%_implib) \
+       $(TEST_KERNEL32:%=%_implib) \
+       $(TEST_MSVCRT:%=%_implib) \
+       $(TEST_COM:%=%_implib) \
+       $(TEST_SEH:%=%_implib) \
+       $(TEST_REGRESSIONS:%=%_implib)
+
+clean:         $(TEST_SETS:%=%_clean) \
+       $(TEST_KERNEL32:%=%_clean) \
+       $(TEST_MSVCRT:%=%_clean) \
+       $(TEST_COM:%=%_clean) \
+       $(TEST_SEH:%=%_clean) \
+       $(TEST_REGRESSIONS:%=%_clean)
+
+install: $(TEST_SETS:%=%_install) \
+        $(TEST_KERNEL32:%=%_install) \
+        $(TEST_MSVCRT:%=%_install) \
+        $(TEST_COM:%=%_install) \
+        $(TEST_SEH:%=%_install) \
+        $(TEST_REGRESSIONS:%=%_install)
+
+dist:  $(TEST_SETS:%=%_dist) \
+       $(TEST_KERNEL32:%=%_dist) \
+       $(TEST_MSVCRT:%=%_dist) \
+       $(TEST_COM:%=%_dist) \
+       $(TEST_SEH:%=%_dist) \
+       $(TEST_REGRESSIONS:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Testset Applications
+#
+$(TEST_SETS): %:
+       make -C $*
+
+$(TEST_SETS:%=%_implib): %_implib:
+       make -C $* implib
+
+$(TEST_SETS:%=%_clean): %_clean:
+       make -C $* clean
+
+$(TEST_SETS:%=%_dist): %_dist:
+       make -C $* dist
+
+$(TEST_SETS:%=%_install): %_install:
+       make -C $* install
+
+.PHONY: $(TEST_SETS) $(TEST_SETS:%=%_implib) $(TEST_SETS:%=%_clean) $(TEST_SETS:%=%_install) $(TEST_SETS:%=%_dist)
+
+
+#
+# Kernel32 Test Applications
+#
+$(TEST_KERNEL32): %:
+       make -C kernel32/$*
+
+$(TEST_KERNEL32:%=%_implib): %_implib:
+       make -C kernel32/$* implib
+
+$(TEST_KERNEL32:%=%_clean): %_clean:
+       make -C kernel32/$* clean
+
+$(TEST_KERNEL32:%=%_dist): %_dist:
+       make -C kernel32/$* dist
+
+$(TEST_KERNEL32:%=%_install): %_install:
+       make -C kernel32/$* install
+
+.PHONY: $(TEST_KERNEL32) $(TEST_KERNEL32:%=%_implib) $(TEST_KERNEL32:%=%_clean) $(TEST_KERNEL32:%=%_install) $(TEST_KERNEL32:%=%_dist)
+
+
+#
+# msvcrt Test Applications
+#
+$(TEST_MSVCRT): %:
+       make -C msvcrt/$*
+
+$(TEST_MSVCRT:%=%_implib): %_implib:
+       make -C msvcrt/$* implib
+
+$(TEST_MSVCRT:%=%_clean): %_clean:
+       make -C msvcrt/$* clean
+
+$(TEST_MSVCRT:%=%_dist): %_dist:
+       make -C msvcrt/$* dist
+
+$(TEST_MSVCRT:%=%_install): %_install:
+       make -C msvcrt/$* install
+
+.PHONY: $(TEST_MSVCRT) $(TEST_MSVCRT:%=%_implib) $(TEST_MSVCRT:%=%_clean) $(TEST_MSVCRT:%=%_install) $(TEST_MSVCRT:%=%_dist)
+
+
+#
+# COM Test Applications
+#
+$(TEST_COM): %:
+       make -C com/$*
+
+$(TEST_COM:%=%_implib): %_implib:
+       make -C com/$* implib
+
+$(TEST_COM:%=%_clean): %_clean:
+       make -C com/$* clean
+
+$(TEST_COM:%=%_dist): %_dist:
+       make -C com/$* dist
+
+$(TEST_COM:%=%_install): %_install:
+       make -C com/$* install
+
+.PHONY: $(TEST_COM) $(TEST_COM:%=%_implib) $(TEST_COM:%=%_clean) $(TEST_COM:%=%_install) $(TEST_COM:%=%_dist)
+
+
+#
+# SEH Test Applications
+#
+$(TEST_SEH): %:
+       make -C seh/$*
+
+$(TEST_SEH:%=%_implib): %_implib:
+       make -C seh/$* implib
+
+$(TEST_SEH:%=%_clean): %_clean:
+       make -C seh/$* clean
+
+$(TEST_SEH:%=%_dist): %_dist:
+       make -C seh/$* dist
+
+$(TEST_SEH:%=%_install): %_install:
+       make -C seh/$* install
+
+.PHONY: $(TEST_SEH) $(TEST_SEH:%=%_implib) $(TEST_SEH:%=%_clean) $(TEST_SEH:%=%_install) $(TEST_SEH:%=%_dist)
+
+
+#
+# Regression Test Applications
+#
+$(TEST_REGRESSIONS): %:
+       make -C regres/$*
+
+$(TEST_REGRESSIONS:%=%_implib): %_implib:
+       make -C regres/$* implib
+
+$(TEST_REGRESSIONS:%=%_clean): %_clean:
+       make -C regres/$* clean
+
+$(TEST_REGRESSIONS:%=%_dist): %_dist:
+       make -C regres/$* dist
+
+$(TEST_REGRESSIONS:%=%_install): %_install:
+       make -C regres/$* install
+
+.PHONY: $(TEST_REGRESSIONS) $(TEST_REGRESSIONS:%=%_implib) $(TEST_REGRESSIONS:%=%_clean) $(TEST_REGRESSIONS:%=%_install) $(TEST_REGRESSIONS:%=%_dist)
+
+
+etags:
+       find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
diff --git a/apps/testsets/loadlib/.cvsignore b/apps/testsets/loadlib/.cvsignore
new file mode 100644 (file)
index 0000000..bd2c3a8
--- /dev/null
@@ -0,0 +1,9 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
+*.dsp
+*.dsw
+*.ncb
+*.opt
diff --git a/apps/testsets/loadlib/loadlib.c b/apps/testsets/loadlib/loadlib.c
new file mode 100644 (file)
index 0000000..fd767c0
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  loadlib.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include "loadlib.h"
+
+
+#define APP_VERSION 1
+#define MAX_LIBS    25
+
+#ifdef UNICODE
+#define TARGET  "UNICODE"
+BOOL bUseAnsi = FALSE;
+#else
+#define TARGET  "MBCS"
+BOOL bUseAnsi = TRUE;
+#endif
+BOOL verbose_flagged = FALSE;
+BOOL debug_flagged = FALSE;
+BOOL loop_flagged = FALSE;
+BOOL recursive_flagged = FALSE;
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+void dprintf(char* fmt, ...)
+{
+   va_list args;
+   char buffer[255];
+
+   va_start(args, fmt);
+   wvsprintfA(buffer, fmt, args);
+   WriteConsoleA(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
+   va_end(args);
+}
+
+long getinput(char* buf, int buflen)
+{
+    DWORD result;
+
+    ReadConsoleA(InputHandle, buf, buflen, &result, NULL);
+    return (long)result;
+}
+
+DWORD ReportLastError(void)
+{
+    DWORD dwError = GetLastError();
+    if (dwError != ERROR_SUCCESS) {
+        PSTR msg = NULL;
+        if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+            0, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PSTR)&msg, 0, NULL)) {
+            if (msg != NULL) {
+                dprintf("ReportLastError() %d - %s\n", dwError, msg);
+            } else {
+                dprintf("ERROR: ReportLastError() %d - returned TRUE but with no msg string!\n", dwError);
+            }
+        } else {
+            dprintf("ReportLastError() %d - unknown error\n", dwError);
+        }
+        if (msg != NULL) {
+            LocalFree(msg);
+        }
+    }
+    return dwError;
+}
+
+const char* appName(const char* argv0)
+{
+    const char* name;
+
+    name = (const char*)strrchr(argv0, '\\');
+    if (name != NULL) 
+        return name + 1;
+    return argv0;
+}
+
+int usage(const char* appName)
+{
+    dprintf("USAGE: %s libname [libname ...] [unicode]|[ansi] [loop][recurse]\n", appName);
+    dprintf("\tWhere libname(s) is one or more libraries to load.\n");
+    dprintf("\t[unicode] - perform tests using UNICODE api calls\n");
+    dprintf("\t[ansi] - perform tests using ANSI api calls\n");
+    dprintf("\t    default is %s\n", TARGET);
+    dprintf("\t[loop] - run test process in continuous loop\n");
+    dprintf("\t[recurse] - load libraries recursively rather than sequentually\n");
+    dprintf("\t[debug] - enable debug mode (unused)\n");
+    dprintf("\t[verbose] - enable verbose output (unused)\n");
+    return 0;
+}
+
+DWORD LoadLibraryList(char** libnames, int counter, BOOL bUseAnsi)
+{
+    HMODULE hModule;
+
+    dprintf("Attempting to LoadLibrary");
+    if (bUseAnsi) {
+        dprintf("A(%s) - ", *libnames);
+        hModule = LoadLibraryA(*libnames);
+    } else {
+        int len;
+        wchar_t libnameW[500];
+        len = mbstowcs(libnameW, *libnames, strlen(*libnames));
+        if (len) {
+            libnameW[len] = L'\0';
+            dprintf("W(%S) - ", libnameW);
+            hModule = LoadLibraryW(libnameW);
+        } else {
+            return ERROR_INVALID_PARAMETER;
+        }
+    }
+    if (hModule == NULL) {
+        dprintf("\nERROR: failed to obtain handle to module %s - %x\n", *libnames, hModule);
+        return ReportLastError();
+    }
+    dprintf("%x\n", hModule);
+
+    if (counter--) {
+        LoadLibraryList(++libnames, counter, bUseAnsi);
+    }
+
+    if (!FreeLibrary(hModule)) {
+        dprintf("ERROR: failed to free module %s - %x\n", *libnames, hModule);
+        return ReportLastError();
+    } else {
+        dprintf("FreeLibrary(%x) - successfull.\n", hModule);
+    }
+    return 0L;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+    char* libs[MAX_LIBS];
+    int lib_count = 0;
+    int test_num = 0;
+    int result = 0;
+    int i = 0;
+
+    AllocConsole();
+    InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+    OutputHandle =  GetStdHandle(STD_OUTPUT_HANDLE);
+
+    dprintf("%s application - build %03d (default: %s)\n", appName(argv[0]), APP_VERSION, TARGET);
+    if (argc < 2) {
+        /*return */usage(appName(argv[0]));
+    }
+    memset(libs, 0, sizeof(libs));
+    for (i = 1; i < argc; i++) {
+        if (lstrcmpiA(argv[i], "ansi") == 0) {
+            bUseAnsi = TRUE;
+        } else if (lstrcmpiA(argv[i], "unicode") == 0) {
+            bUseAnsi = FALSE;
+        } else if (lstrcmpiA(argv[i], "loop") == 0) {
+            loop_flagged = 1;
+        } else if (lstrcmpiA(argv[i], "recurse") == 0) {
+            recursive_flagged = 1;
+        } else if (lstrcmpiA(argv[i], "verbose") == 0) {
+            verbose_flagged = 1;
+        } else if (lstrcmpiA(argv[i], "debug") == 0) {
+            debug_flagged = 1;
+        } else {
+            if (lib_count < MAX_LIBS) {
+                libs[lib_count] = argv[i];
+                ++lib_count;
+            }
+        }
+    }
+    if (lib_count) {
+        do {
+            if (recursive_flagged) {
+                result = LoadLibraryList(libs, lib_count - 1, bUseAnsi);
+            } else {
+                for (i = 0; i < lib_count; i++) {
+                    result = LoadLibraryList(&libs[i], 0, bUseAnsi);
+                    //if (result != 0) break;
+                }
+            }
+        } while (loop_flagged);
+    } else {
+        int len;
+        char buffer[500];
+        do {
+            dprintf("\nEnter library name to attempt loading: ");
+            len = getinput(buffer, sizeof(buffer) - 1);
+            if (len > 2) {
+                char* buf = buffer;
+                buffer[len-2] = '\0';
+                result = LoadLibraryList(&buf, 0, bUseAnsi);
+            } else break;
+        } while (!result && len);
+    }
+    dprintf("finished\n");
+    return result;
+}
+
+
+#ifdef _NOCRT
+char* args[] = { "loadlib.exe", "advapi32.dll", "user32.dll", "recurse"};
+int __cdecl mainCRTStartup(void)
+{
+    return main(3, args);
+}
+#endif /*__GNUC__*/
diff --git a/apps/testsets/loadlib/loadlib.h b/apps/testsets/loadlib/loadlib.h
new file mode 100644 (file)
index 0000000..51210d4
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  loadlib.h
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LOADLIB_H__
+#define __LOADLIB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern BOOL verbose_flagged;
+extern BOOL debug_flagged;
+extern BOOL loop_flagged;
+extern BOOL recursive_flagged;
+
+DWORD ReportLastError(void);
+long getinput(char* Buffer, int buflen);
+void dprintf(char* fmt, ...);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __LOADLIB_H__
diff --git a/apps/testsets/loadlib/makefile b/apps/testsets/loadlib/makefile
new file mode 100644 (file)
index 0000000..a10e244
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = loadlib
+
+#TARGET_CFLAGS = -DDBG -DUNICODE -D_UNICODE
+
+TARGET_SDKLIBS = kernel32.a ntdll.a 
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/testsets/msvcrt/fileio/.cvsignore b/apps/testsets/msvcrt/fileio/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/testsets/msvcrt/fileio/_tfileio.c b/apps/testsets/msvcrt/fileio/_tfileio.c
new file mode 100644 (file)
index 0000000..84d0e1a
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  _tfileio.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tchar.h>
+#include <wchar.h>
+#include <stdio.h>
+
+
+#ifdef UNICODE
+#define _tfopen      _wfopen
+#define _tunlink     _wunlink
+#define _TEOF        WEOF
+#define _gettchar    getwchar 
+#define _puttchar    putwchar  
+#define _THEX_FORMAT _T("0x%04x ")
+#else /*UNICODE*/
+#define _tfopen      fopen
+#define _tunlink     _unlink
+#define _TEOF        EOF
+#define _gettchar    getchar
+#define _puttchar    putchar
+#define _THEX_FORMAT "0x%02x "
+#endif /*UNICODE*/
+
+
+#define TEST_BUFFER_SIZE 200
+#define TEST_FILE_LINES  4
+
+extern BOOL verbose_flagged;
+extern BOOL status_flagged;
+
+static TCHAR test_buffer[TEST_BUFFER_SIZE];
+
+static TCHAR dos_data[] = _T("line1: this is a bunch of readable text.\r\n")\
+                   _T("line2: some more printable text and punctuation !@#$%^&*()\r\n")\
+                   _T("line3: followed up with some numerals 1234567890\r\n")\
+                   _T("line4: done.\r\n");
+
+static TCHAR nix_data[] = _T("line1: this is a bunch of readable text.\n")\
+                   _T("line2: some more printable text and punctuation !@#$%^&*()\n")\
+                   _T("line3: followed up with some numerals 1234567890\n")\
+                   _T("line4: done.\n");
+
+#ifdef UNICODE
+#define TEST_B1_FILE_SIZE ((((sizeof(dos_data)/2)-1)+TEST_FILE_LINES)/2) // (166+4)/2=85
+#define TEST_B2_FILE_SIZE (((sizeof(dos_data)/2)-1)*2)                   // (166*2)  =332
+#define TEST_B3_FILE_SIZE ((((sizeof(nix_data)/2)-1)+TEST_FILE_LINES)/2) // (162+4)/2=83
+#define TEST_B4_FILE_SIZE (((sizeof(nix_data)/2)-1)*2)                   // (162*2)  =324
+#else /*UNICODE*/
+#define TEST_B1_FILE_SIZE (sizeof(dos_data)-1+TEST_FILE_LINES) // (166+4)=170
+#define TEST_B2_FILE_SIZE (sizeof(dos_data)-1-TEST_FILE_LINES) // (166-4)=162
+#define TEST_B3_FILE_SIZE (sizeof(nix_data)-1+TEST_FILE_LINES) // (162+4)=166
+#define TEST_B4_FILE_SIZE (sizeof(nix_data)-1)                 // (162)  =162
+#endif /*UNICODE*/
+
+
+//    result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
+
+static BOOL test_file_truncate(TCHAR* file_name)
+{
+    BOOL result = FALSE;
+    int count = -1;
+    int error_code;
+    TCHAR ch;
+    TCHAR* file_data = _T("this file should have been truncated to zero bytes...");
+    FILE *file = _tfopen(file_name, _T("wb"));
+
+    if (verbose_flagged) {
+        _tprintf(_T("test_file_truncate(\"%s\")\n"), file_name);
+    }
+
+    if (file != NULL) {
+        if (_fputts(file_data, file) != _TEOF) {
+        } else {
+            _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
+            _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+        }
+        fclose(file);
+    } else {
+        _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
+        _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+    }
+
+    file = _tfopen(file_name, _T("wb"));
+    if (file != NULL) {
+        error_code = ferror(file);
+        if (error_code) {
+             _tprintf(_T("ERROR: (%s) ferror returned %d\n"), file_name, error_code);
+        }
+        fclose(file);
+    } else {
+        _tprintf(_T("ERROR: (%s) failed to open file for truncating\n"), file_name);
+    }
+
+    file = _tfopen(file_name, _T("rb"));
+    if (file != NULL) {
+        count = 0;
+        while ((ch = _fgettc(file)) != _TEOF) {
+            if (verbose_flagged) {
+                _tprintf(_THEX_FORMAT, ch);
+            }
+            ++count;
+        }
+        error_code = ferror(file);
+        if (error_code) {
+             _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+             perror("Read error");
+        }
+        fclose(file);
+    } else {
+        _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
+    }
+    if (count) {
+        result = TRUE;
+    }
+    return result;
+}
+
+static BOOL create_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
+{
+    BOOL result = FALSE;
+    FILE *file = _tfopen(file_name, file_mode);
+    if (file != NULL) {
+        if (_fputts(file_data, file) != _TEOF) {
+            result = TRUE;
+        } else {
+            _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
+            _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+        }
+        fclose(file);
+    } else {
+        _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
+        _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+    }
+    return result;
+}
+
+static BOOL verify_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
+{
+    int error_code;
+    int offset = 0;
+    int line_num = 0;
+    BOOL result = FALSE;
+    BOOL error_flagged = FALSE;
+    FILE* file = _tfopen(file_name, file_mode);
+    if (file == NULL) {
+        _tprintf(_T("ERROR: (%s) Can't open file for reading\n"), file_name);
+        _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+        return FALSE;
+    } else if (status_flagged) {
+        _tprintf(_T("STATUS: (%s) opened file for reading\n"), file_name);
+    }
+    while (_fgetts(test_buffer, TEST_BUFFER_SIZE, file)) {
+        int length = _tcslen(test_buffer);
+        int req_len = _tcschr(file_data+offset, _T('\n')) - (file_data+offset) + 1;
+
+        ++line_num;
+        if (length > req_len) {
+            _tprintf(_T("ERROR: read excess bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
+            error_flagged = TRUE;
+            break;
+        }
+        if (length < req_len) {
+            _tprintf(_T("ERROR: read to few bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
+            error_flagged = TRUE;
+            break;
+        }
+        if (status_flagged) {
+            _tprintf(_T("STATUS: Verifying %d bytes read from line %d\n"), length, line_num);
+        }
+        if (_tcsncmp(test_buffer, file_data+offset, length - 1) == 0) {
+            result = TRUE;
+        } else {
+            if (status_flagged) {
+                int i;
+                _tprintf(_T("WARNING: (%s) failed to verify file\n"), file_name);
+                for (i = 0; i < length; i++) {
+                    if (file_data[offset+i] != test_buffer[i]) {
+                        _tprintf(_T("line %d, offset %d expected: 0x%04x found: 0x%04x\n"), line_num, i, (int)file_data[offset+i], (int)test_buffer[i]);
+                    }
+                }
+                _tprintf(_T("\n"));
+            } else {
+                error_flagged = TRUE;
+            }
+        }
+        offset += length;
+    }
+    error_code = ferror(file);
+    if (error_code) {
+         _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+         perror("Read error");
+    }
+    if (!line_num) {
+        _tprintf(_T("ERROR: (%s) failed to read from file\n"), file_name);
+    }
+    if (error_flagged == TRUE) {
+        _tprintf(_T("ERROR: (%s) failed to verify file\n"), file_name);
+        result = FALSE;
+    }
+    fclose(file);
+    return result;
+}
+
+static int create_test_file(TCHAR* file_name, TCHAR* write_mode, TCHAR* read_mode, TCHAR* file_data)
+{
+    if (status_flagged) {
+        _tprintf(_T("STATUS: Attempting to create output file %s\n"), file_name);
+    }
+    if (create_output_file(file_name, write_mode, file_data)) {
+        if (status_flagged) {
+            _tprintf(_T("STATUS: Attempting to verify output file %s\n"), file_name);
+        }
+        if (verify_output_file(file_name, read_mode, file_data)) {
+            if (status_flagged) {
+                _tprintf(_T("SUCCESS: %s verified ok\n"), file_name);
+            }
+        } else {
+            //_tprintf(_T("ERROR: failed to verify file %s\n"), file_name);
+            return 2;
+        }
+    } else {
+        _tprintf(_T("ERROR: failed to create file %s\n"), file_name);
+        return 1;
+    }
+    return 0;
+}
+
+static int check_file_size(TCHAR* file_name, TCHAR* file_mode, int expected)
+{
+    int count = 0;
+    FILE* file;
+    TCHAR ch;
+    int error_code;
+
+    if (status_flagged) {
+        //_tprintf(_T("STATUS: (%s) checking for %d bytes in %s mode\n"), file_name, expected, _tcschr(file_mode, _T('b')) ? _T("binary") : _T("text"));
+        _tprintf(_T("STATUS: (%s) checking for %d bytes with mode %s\n"), file_name, expected, file_mode);
+    }
+    file = _tfopen(file_name, file_mode);
+    if (file == NULL) {
+        _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
+        return 1;
+    }
+    while ((ch = _fgettc(file)) != _TEOF) {
+        if (verbose_flagged) {
+            _tprintf(_THEX_FORMAT, ch);
+        }
+        ++count;
+    }
+    error_code = ferror(file);
+    if (error_code) {
+         _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+         perror("Read error");
+    }
+
+    if (verbose_flagged) {
+//        _puttc(_T('\n'), stdout);
+    }
+    fclose(file);
+    if (count == expected) {
+        if (status_flagged) {
+            _tprintf(_T("PASSED: (%s) read %d bytes\n"), file_name, count);
+        }
+    } else {
+        _tprintf(_T("FAILED: (%s) read %d bytes but expected %d using mode \"%s\"\n"), file_name, count, expected, file_mode);
+    }
+    return (count == expected) ? 0 : -1;
+}
+
+static int test_console_io(void)
+{
+    TCHAR buffer[81];
+    TCHAR ch;
+    int i, j;
+
+    _tprintf(_T("Enter a line for echoing:\n"));
+
+    //for (i = 0; (i < 80) && ((ch = _gettchar()) != _TEOF) && (ch != _T('\n')); i++) {
+    for (i = 0; (i < 80) && ((ch = _gettc(stdin)) != _TEOF) && (ch != _T('\n')); i++) {
+        buffer[i] = (TCHAR)ch;
+    }
+    buffer[i] = _T('\0');
+    for (j = 0; j < i; j++) {
+        _puttc(buffer[j], stdout);
+    }
+    _puttc(_T('\n'), stdout);
+    _tprintf(_T("%s\n"), buffer);
+    return 0;
+}
+
+static int test_console_getchar(void)
+{
+    int result = 0;
+    TCHAR ch;
+
+    _tprintf(_T("Enter lines for dumping or <ctrl-z><nl> to finish:\n"));
+
+    //while ((ch = _gettchar()) != _TEOF) {
+    while ((ch = _gettc(stdin)) != _TEOF) {
+        _tprintf(_THEX_FORMAT, ch);
+        //printf("0x%04x ", ch);
+    }
+    return result;
+}
+
+static int test_console_putch(void)
+{
+    int result = 0;
+
+    _putch('1');
+    _putch('@');
+    _putch('3');
+    _putch(':');
+    _putch('\n');
+    _putch('a');
+    _putch('B');
+    _putch('c');
+    _putch(':');
+    _putch('\n');
+    return result;
+}
+
+static int test_unlink_files(void)
+{
+    int result = 0;
+
+    //printf("sizeof dos_data: %d\n", sizeof(dos_data));
+    //printf("sizeof nix_data: %d\n", sizeof(nix_data));
+
+    result |= _tunlink(_T("binary.dos"));
+    result |= _tunlink(_T("binary.nix"));
+    result |= _tunlink(_T("text.dos"));
+    result |= _tunlink(_T("text.nix"));
+    return result;
+}
+
+static int test_text_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
+{
+    int result = 0;
+
+    result = create_test_file(file_name, _T("w"), _T("r"), file_data);
+    result = check_file_size(file_name, _T("r"), tsize);
+    result = check_file_size(file_name, _T("rb"), bsize);
+    return result;
+}
+
+static int test_binary_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
+{
+    int result = 0;
+
+    result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
+    result = check_file_size(file_name, _T("r"), tsize);
+    result = check_file_size(file_name, _T("rb"), bsize);
+    return result;
+}
+
+static int test_files(int test_num, char* type)
+{
+    int result = 0;
+
+    printf("performing test: %d (%s)\n", test_num, type);
+
+
+    if (test_file_truncate(_T("zerosize.foo"))) {
+        printf("System unable to truncate files yet, unlinking:\n");
+        test_unlink_files();
+    }
+
+    switch (test_num) {
+    case 1:
+        result = test_text_fileio(_T("text.dos"), dos_data, 166, TEST_B1_FILE_SIZE);
+        break;
+    case 2:
+        result = test_binary_fileio(_T("binary.dos"), dos_data, TEST_B2_FILE_SIZE, 166);
+        break;
+    case 3:
+        result = test_text_fileio(_T("text.nix"), nix_data, 162, TEST_B3_FILE_SIZE);
+        break;
+    case 4:
+        result = test_binary_fileio(_T("binary.nix"), nix_data, TEST_B4_FILE_SIZE, 162);
+        break;
+    case 5:
+        result = test_console_io();
+        break;
+    case 6:
+        result = test_console_getchar();
+        break;
+    case 7:
+        result = test_console_putch();
+        break;
+    case -1:
+        result = test_unlink_files();
+        break;
+    default:
+        _tprintf(_T("no test number selected\n"));
+        break;
+    }
+    return result;
+}
diff --git a/apps/testsets/msvcrt/fileio/fileio.c b/apps/testsets/msvcrt/fileio/fileio.c
new file mode 100644 (file)
index 0000000..ab29300
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  _fileio.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#undef UNICODE
+#undef _UNICODE
+#include "_tfileio.c"
+
+
+int run_ansi_tests(int test_num)
+{
+    return test_files(test_num, "ANSI");
+}
diff --git a/apps/testsets/msvcrt/fileio/main.c b/apps/testsets/msvcrt/fileio/main.c
new file mode 100644 (file)
index 0000000..64f5476
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  main.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tchar.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "main.h"
+
+
+#define VERSION 1
+
+#ifdef UNICODE
+#define TARGET  "UNICODE"
+#else
+#define TARGET  "MBCS"
+#endif
+
+BOOL verbose_flagged = 0;
+BOOL status_flagged = 0;
+
+int usage(char* argv0)
+{
+    printf("USAGE: %s test_id [unicode]|[ansi] [clean]|[status][verbose]\n", argv0);
+    printf("\tWhere test_id is one of:\n");
+    printf("\t0 - (default) regression mode, run tests 1-4 displaying failures only\n");
+    printf("\t1 - Write DOS style eol data to file in text mode (text.dos)\n");
+    printf("\t2 - Write NIX style eol data to file in binary mode (binary.dos)\n");
+    printf("\t3 - Write DOS style eol data to file in text mode (text.nix)\n");
+    printf("\t4 - Write NIX style eol data to file in binary mode (binary.nix)\n");
+    printf("\t5 - Echo console line input\n");
+    printf("\t6 - Dump console line input in hex format\n");
+    printf("\t7 - The source code is your friend\n");
+    printf("\t[unicode] - perform tests using UNICODE versions of library functions\n");
+    printf("\t[ansi] - perform tests using ANSI versions of library functions\n");
+    printf("\t    If neither unicode or ansi is specified build default is used\n");
+    printf("\t[clean] - delete all temporary test output files\n");
+    printf("\t[status] - enable extra status display while running\n");
+    printf("\t[verbose] - enable verbose output when running\n");
+    return 0;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+    int test_num = 0;
+    int version = 0;
+    int result = 0;
+    int i = 0;
+
+    printf("%s test application - build %03d (default: %s)\n", argv[0], VERSION, TARGET);
+    if (argc < 2) {
+        return usage(argv[0]);
+    }
+    for (i = 1; i < argc; i++) {
+        if (strstr(argv[i], "ansi") || strstr(argv[i], "ANSI")) {
+            version = 1;
+        } else if (strstr(argv[i], "unicode") || strstr(argv[i], "UNICODE")) {
+            version = 2;
+        } else if (strstr(argv[i], "clean") || strstr(argv[i], "CLEAN")) {
+            test_num = -1;
+        } else if (strstr(argv[i], "verbose") || strstr(argv[i], "VERBOSE")) {
+            verbose_flagged = 1;
+        } else if (strstr(argv[i], "status") || strstr(argv[i], "STATUS")) {
+            status_flagged = 1;
+        } else {
+            test_num = atoi(argv[1]);
+            //if (test_num < 0
+        }
+    }
+    for (i = test_num; i <= test_num; i++) {
+        if (!test_num) {
+            test_num = 4;
+            i = 1;
+        }
+        switch (version) {
+        case 1:
+            result = run_ansi_tests(i);
+            break;
+        case 2:
+            result = run_unicode_tests(i);
+            break;
+        default:
+            result = run_ansi_tests(i);
+            result = run_unicode_tests(i);
+            break;
+        }
+    }
+    printf("finished\n");
+    return result;
+}
+
+#ifndef __GNUC__
+
+char* args[] = { "fileio.exe", "0", "unicode", "verbose"};
+
+int __cdecl mainCRTStartup(void)
+{
+    main(2, args);
+    return 0;
+}
+
+#endif /*__GNUC__*/
diff --git a/apps/testsets/msvcrt/fileio/main.h b/apps/testsets/msvcrt/fileio/main.h
new file mode 100644 (file)
index 0000000..ee20fbe
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  main.h
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int app_main(int argc, char* argv[]);
+DWORD GetInput(char* Buffer, int buflen);
+
+int test_ansi_files(int test_num);
+int test_unicode_files(int test_num);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __MAIN_H__
diff --git a/apps/testsets/msvcrt/fileio/makefile b/apps/testsets/msvcrt/fileio/makefile
new file mode 100644 (file)
index 0000000..e0a22da
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../../..
+
+TEST_ROOT = $(PATH_TO_TOP)/apps/testsets/test
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = fileio
+
+#TARGET_CFLAGS = -I$(TEST_ROOT) -DDBG -DUNICODE -D_UNICODE
+TARGET_CFLAGS = -I$(TEST_ROOT) -DDBG
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o wfileio.o main.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/testsets/msvcrt/fileio/wfileio.c b/apps/testsets/msvcrt/fileio/wfileio.c
new file mode 100644 (file)
index 0000000..5985a8a
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  wfileio.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define UNICODE
+#define _UNICODE
+#include "_tfileio.c"
+
+
+int run_unicode_tests(int test_num)
+{
+    return test_files(test_num, "UNICODE");
+}
diff --git a/apps/utils/Makefile b/apps/utils/Makefile
new file mode 100644 (file)
index 0000000..a9b1033
--- /dev/null
@@ -0,0 +1,82 @@
+#
+# ReactOS system utilities makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Console system utilities
+# cabman cat net objdir partinfo pice ps sc stats
+UTIL_APPS = cat objdir partinfo sc stats tickcount
+
+UTIL_NET_APPS = 
+
+
+all: $(UTIL_APPS) $(UTIL_NET_APPS)
+
+depends: 
+
+implib: $(UTIL_APPS:%=%_implib) \
+       $(UTIL_NET_APPS:%=%_implib)
+
+clean:         $(UTIL_APPS:%=%_clean) \
+       $(UTIL_NET_APPS:%=%_clean)
+
+install: $(UTIL_APPS:%=%_install) \
+        $(UTIL_NET_APPS:%=%_install)
+
+dist:  $(UTIL_APPS:%=%_dist) \
+       $(UTIL_NET_APPS:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Utility Applications
+#
+$(UTIL_APPS): %:
+       make -C $*
+
+$(UTIL_APPS:%=%_implib): %_implib:
+       make -C $* implib
+
+$(UTIL_APPS:%=%_clean): %_clean:
+       make -C $* clean
+
+$(UTIL_APPS:%=%_dist): %_dist:
+       make -C $* dist
+
+$(UTIL_APPS:%=%_install): %_install:
+       make -C $* install
+
+.PHONY: $(UTIL_APPS) $(UTIL_APPS:%=%_implib) $(UTIL_APPS:%=%_clean) $(UTIL_APPS:%=%_install) $(UTIL_APPS:%=%_dist)
+
+
+#
+# GUI Utility Applications
+#
+$(UTIL_NET_APPS): %:
+       make -C net/$*
+
+$(UTIL_NET_APPS:%=%_implib): %_implib:
+       make -C net/$* implib
+
+$(UTIL_NET_APPS:%=%_clean): %_clean:
+       make -C net/$* clean
+
+$(UTIL_NET_APPS:%=%_dist): %_dist:
+       make -C net/$* dist
+
+$(UTIL_NET_APPS:%=%_install): %_install:
+       make -C net/$* install
+
+.PHONY: $(UTIL_NET_APPS) $(UTIL_NET_APPS:%=%_implib) $(UTIL_NET_APPS:%=%_clean) $(UTIL_NET_APPS:%=%_install) $(UTIL_NET_APPS:%=%_dist)
+
+
+etags:
+       find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
diff --git a/apps/utils/cabman/.cvsignore b/apps/utils/cabman/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/cat/.cvsignore b/apps/utils/cat/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/net/roshttpd/.cvsignore b/apps/utils/net/roshttpd/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/net/telnet/.cvsignore b/apps/utils/net/telnet/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/objdir/.cvsignore b/apps/utils/objdir/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/partinfo/.cvsignore b/apps/utils/partinfo/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/pice/.cvsignore b/apps/utils/pice/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/ps/.cvsignore b/apps/utils/ps/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/ps/ps.c b/apps/utils/ps/ps.c
new file mode 100644 (file)
index 0000000..2b226ed
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id$
+ *
+ *  ReactOS ps - process list console viewer
+ *
+ *  ps.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+static char* title = "     PID   PARENT  TIME NAME\n";
+char buf[256];
+
+int main()
+{
+    DWORD r;
+    HANDLE pl;
+    PROCESSENTRY32 pe;
+    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+
+    WriteFile(stdout, title, lstrlen(title), &r, NULL);
+    pl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    pe.dwSize = sizeof(PROCESSENTRY32);
+    pe.th32ParentProcessID = 0;
+
+    if (Process32First(pl, &pe)) do {
+        int hour;
+        int minute;
+        WORD fatdate;
+        WORD fattime;
+        HANDLE p = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
+        FILETIME cr;
+        FILETIME ex;
+        FILETIME kt;
+        FILETIME ut;
+        GetProcessTimes(p, &cr, &ex, &kt, &ut);
+        FileTimeToDosDateTime(&cr, &fatdate, &fattime);
+        hour = (fattime & 0xf800) >> 11;
+        minute = (fattime & 0x07e0) >> 5;
+        wsprintf(buf,"%08X %08X %2d:%02d %s\n", pe.th32ProcessID, pe.th32ParentProcessID, hour, minute, pe.szExeFile);
+        WriteFile(stdout, buf, lstrlen(buf), &r, NULL);
+        CloseHandle(p);
+        pe.th32ParentProcessID = 0;
+  } while (Process32Next(pl, &pe));
+
+  CloseHandle(pl);
+}
+/*
+WINBOOL
+STDCALL
+FileTimeToDosDateTime(
+                     CONST FILETIME *lpFileTime,
+                     LPWORD lpFatDate,
+                     LPWORD lpFatTime
+                     );
+ */
diff --git a/apps/utils/sc/.cvsignore b/apps/utils/sc/.cvsignore
new file mode 100644 (file)
index 0000000..efa8e8d
--- /dev/null
@@ -0,0 +1,7 @@
+*.o
+*.d
+sc.exe
+sc.nostrip.exe
+sc.coff
+sc.sym
+sc.map
diff --git a/apps/utils/sc/command.c b/apps/utils/sc/command.c
new file mode 100644 (file)
index 0000000..60066dd
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  ReactOS SC - service control console program
+ *
+ *  command.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+int sc_Lock(SC_HANDLE hSCManager)
+{
+    dprintf("sc_Lock(%x) - not implemented.\n", hSCManager);
+    return 0;
+}
+
+int sc_QueryLock(SC_HANDLE hSCManager)
+{
+    QUERY_SERVICE_LOCK_STATUS LockStatus;
+    DWORD cbBufSize = sizeof(QUERY_SERVICE_LOCK_STATUS);
+    DWORD cbBytesNeeded;
+
+    dprintf("sc_QueryLock() - called.\n");
+
+        if (QueryServiceLockStatus(hSCManager, &LockStatus, cbBufSize, &cbBytesNeeded)) {
+
+        } else {
+            dprintf("Failed to Query Service Lock Status.\n");
+            ReportLastError();
+        }
+
+        if (!CloseServiceHandle(hSCManager)) {
+            dprintf("Failed to CLOSE handle to SCM.\n");
+            ReportLastError();
+        }
+
+    return 0;
+}
+
+int sc_control(SC_HANDLE hSCManager, char* service, DWORD dwControl)
+{
+    int ret = 0;
+    SC_HANDLE schService;
+    SERVICE_STATUS serviceStatus;
+
+    dprintf("sc_control(%x, %s, %d) - called.\n", hSCManager, service, dwControl);
+
+    schService = OpenServiceA(hSCManager, service, SERVICE_ALL_ACCESS);
+    if (schService != NULL) {
+        ret = ControlService(schService, dwControl, &serviceStatus);
+        dprintf("ControlService(%x, %x, %x) returned %d\n", schService, dwControl, &serviceStatus, ret);
+        if (!ret) {
+
+
+        }
+        CloseServiceHandle(schService);
+    }
+    return ret;
+}
+
+int sc_command(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+//    dprintf("sc_command(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[]);
+    switch (sc_cmd) {
+    case SC_CMD_START:
+        //return sc_control(hSCManager, sc_cmd_arg, SERVICE_CONTROL_START);
+        dprintf(" - not implemented.\n");
+        break;
+    case SC_CMD_PAUSE:
+        return sc_control(hSCManager, argv[0], SERVICE_CONTROL_PAUSE);
+    case SC_CMD_INTERROGATE:
+        return sc_control(hSCManager, argv[0], SERVICE_CONTROL_INTERROGATE);
+    case SC_CMD_CONTINUE:
+        return sc_control(hSCManager, argv[0], SERVICE_CONTROL_CONTINUE);
+    case SC_CMD_STOP:
+        return sc_control(hSCManager, argv[0], SERVICE_CONTROL_STOP);
+       
+//    case SC_CMD_CONFIG:
+//    case SC_CMD_DESCRIPTION:
+//    case SC_CMD_CONTROL:
+
+    case SC_CMD_LOCK:
+        return sc_Lock(hSCManager);
+    case SC_CMD_QUERYLOCK:
+        return sc_QueryLock(hSCManager);
+    default:
+        dprintf("sc_command(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+        break;
+    }
+    return 0;
+}
diff --git a/apps/utils/sc/config.c b/apps/utils/sc/config.c
new file mode 100644 (file)
index 0000000..87f4ae7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  ReactOS SC - service control console program
+ *
+ *  config.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+int sc_config(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+    dprintf("sc_config(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[0]);
+
+    switch (sc_cmd) {
+    case SC_CMD_CONFIG:
+    case SC_CMD_DESCRIPTION:
+    case SC_CMD_FAILURE:
+    case SC_CMD_SDSHOW:
+    case SC_CMD_SDSET:
+        dprintf(" - not implemented.\n");
+        break;
+    default:
+        dprintf("sc_config(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+        break;
+    }
+    return 0;
+}
+/*
+    switch (sc_cmd) {
+    case SC_CMD_QUERY:
+    case SC_CMD_QUERYEX:
+    case SC_CMD_START:
+    case SC_CMD_PAUSE:
+    case SC_CMD_INTERROGATE:
+    case SC_CMD_CONTINUE:
+    case SC_CMD_STOP:
+    case SC_CMD_CONFIG:
+    case SC_CMD_DESCRIPTION:
+    case SC_CMD_FAILURE:
+    case SC_CMD_QC:
+    case SC_CMD_QDESCRIPTION:
+    case SC_CMD_QFAILURE:
+    case SC_CMD_DELETE:
+    case SC_CMD_CREATE:
+    case SC_CMD_CONTROL:
+    case SC_CMD_SDSHOW:
+    case SC_CMD_SDSET:
+    case SC_CMD_GETDISPLAYNAME:
+    case SC_CMD_GETKEYNAME:
+    case SC_CMD_ENUMDEPEND:
+    case SC_CMD_BOOT:
+    case SC_CMD_LOCK:
+    case SC_CMD_QUERYLOCK:
+        break;
+    }
+ */
diff --git a/apps/utils/sc/main.c b/apps/utils/sc/main.c
new file mode 100644 (file)
index 0000000..507d749
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ *  ReactOS SC - service control console program
+ *
+ *  main.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <tchar.h>
+#include "main.h"
+
+
+#define VERSION 1
+
+#ifdef UNICODE
+#define TARGET  "UNICODE"
+#else
+#define TARGET  "MBCS"
+#endif
+
+BOOL verbose_flagged = 0;
+BOOL status_flagged = 0;
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+void dprintf(char* fmt, ...)
+{
+   va_list args;
+   char buffer[255];
+
+   va_start(args, fmt);
+   wvsprintfA(buffer, fmt, args);
+   WriteConsoleA(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
+   va_end(args);
+}
+
+long getinput(char* buf, int buflen)
+{
+    DWORD result;
+
+    ReadConsoleA(InputHandle, buf, buflen, &result, NULL);
+    return (long)result;
+}
+
+DWORD ReportLastError(void)
+{
+    DWORD dwError = GetLastError();
+    if (dwError != ERROR_SUCCESS) {
+        PTSTR msg = NULL;
+        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+            0, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) {
+            if (msg != NULL) {
+                dprintf("ReportLastError() %d - %s\n", dwError, msg);
+            } else {
+                dprintf("ERROR: ReportLastError() %d - returned TRUE but with no msg string!\n", dwError);
+            }
+        } else {
+            dprintf("ReportLastError() %d - unknown error\n", dwError);
+        }
+        if (msg != NULL) {
+            LocalFree(msg);
+        }
+    }
+    return dwError;
+}
+
+int usage(char* argv0)
+{
+    dprintf("DESCRIPTION:\n");
+    dprintf("\tSC is a command line program used for communicating with\n");
+    dprintf("\tthe Service Control Manager and its services.\n");
+    dprintf("USAGE:\n");
+    dprintf("\tsc <server> [command] [service name] <option1> <option2>...\n");
+
+    dprintf("\tThe optional parameter <server> has the form \"\\ServerName\"\n");
+    dprintf("\tFurther help on commands can be obtained by typing: \"sc [command]\"\n");
+    dprintf("\tService Commands:\n");
+    dprintf("\t  query          : Queries the status for a service, or\n");
+    dprintf("\t                   enumerates the status for types of services.\n");
+    dprintf("\t  queryex        : Queries the extended status for a service, or\n");
+    dprintf("\t                   enumerates the status for types of services.\n");
+    dprintf("\t  start          : Starts a service.\n");
+    dprintf("\t  pause          : Sends a PAUSE control request to a service.\n");
+    dprintf("\t  interrogate    : Sends a INTERROGATE control request to a service.\n");
+    dprintf("\t  continue       : Sends a CONTINUE control request to a service.\n");
+    dprintf("\t  stop           : Sends a STOP request to a service.\n");
+    dprintf("\t  config         : Changes the configuration of a service (persistant).\n");
+    dprintf("\t  description    : Changes the description of a service.\n");
+    dprintf("\t  failure        : Changes the actions taken by a service upon failure.\n");
+    dprintf("\t  qc             : Queries the configuration information for a service.\n");
+    dprintf("\t  qdescription   : Queries the description for a service.\n");
+    dprintf("\t  qfailure       : Queries the actions taken by a service upon failure.\n");
+    dprintf("\t  delete         : Deletes a service (from the registry).\n");
+    dprintf("\t  create         : Creates a service. (adds it to the registry).\n");
+    dprintf("\t  control        : Sends a control to a service.\n");
+//    dprintf("\t  sdshow         : Displays a service's security descriptor.\n");
+//    dprintf("\t  sdset          : Sets a service's security descriptor.\n");
+    dprintf("\t  GetDisplayName : Gets the DisplayName for a service.\n");
+    dprintf("\t  GetKeyName     : Gets the ServiceKeyName for a service.\n");
+    dprintf("\t  EnumDepend     : Enumerates Service Dependencies.\n");
+    dprintf("\n");
+    dprintf("\tService Name Independant Commands:\n");
+    dprintf("\t  boot           : (ok | bad) Indicates whether the last boot should\n");
+    dprintf("\t                   be saved as the last-known-good boot configuration\n");
+    dprintf("\t  Lock           : Locks the SCM Database\n");
+    dprintf("\t  QueryLock      : Queries the LockStatus for the SCM Database\n");
+
+    return 0;
+}
+
+
+typedef int (*sc_cmd_proc)(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+
+typedef struct {
+    SC_CMDS sc_cmd;
+    const char* cmd_str;
+    sc_cmd_proc funcptr;
+    DWORD dwDesiredAccess;
+} sc_cmd_entry;
+
+sc_cmd_entry sc_cmds_table[] = {
+  { SC_CMD_QUERY, "query", sc_query, SC_MANAGER_ALL_ACCESS },
+  { SC_CMD_QUERYEX, "queryex", sc_query, SC_MANAGER_ALL_ACCESS },
+  { SC_CMD_START, "start", sc_command, 0L },
+  { SC_CMD_PAUSE, "pause", sc_command, 0L },
+  { SC_CMD_INTERROGATE, "interrogate", sc_command, 0L },
+  { SC_CMD_CONTINUE, "continue", sc_command, 0L },
+  { SC_CMD_STOP, "stop", sc_command, 0L },
+  { SC_CMD_CONFIG, "config", sc_setup, 0L },
+  { SC_CMD_DESCRIPTION, "description", sc_setup, 0L },
+  { SC_CMD_FAILURE, "failure", sc_setup, 0L },
+  { SC_CMD_QC, "qc", sc_query, 0L },
+  { SC_CMD_QDESCRIPTION, "qdescription", sc_query, 0L },
+  { SC_CMD_QFAILURE, "qfailure", sc_query, 0L },
+  { SC_CMD_DELETE, "delete", sc_setup, 0L },
+  { SC_CMD_CREATE, "create", sc_setup, 0L },
+  { SC_CMD_CONTROL, "control", sc_setup, 0L },
+  { SC_CMD_SDSHOW, "sdshow", sc_query, 0L },
+  { SC_CMD_SDSET, "sdset", sc_setup, 0L },
+  { SC_CMD_GETDISPLAYNAME, "GetDisplayName", sc_query, 0L },
+  { SC_CMD_GETKEYNAME, "GetKeyName", sc_query, 0L },
+  { SC_CMD_ENUMDEPEND, "EnumDepend", sc_query, 0L },
+  { SC_CMD_BOOT, "boot", sc_config, 0L },
+  { SC_CMD_LOCK, "Lock", sc_config, 0L },
+  { SC_CMD_QUERYLOCK, "QueryLock", sc_config, 0L }
+};
+
+
+int sc_main(const sc_cmd_entry* cmd_entry,
+            const char* sc_machine_name,
+            char* sc_cmd_arg[])
+{
+    int result = 1;
+    SC_HANDLE hSCManager;
+    DWORD dwDesiredAccess;
+
+    dprintf("sc_main(%s) - called.\n", cmd_entry->cmd_str);
+    if (sc_machine_name) {
+        dprintf("remote service control not yet implemented.\n");
+        return 2;
+    }
+    dwDesiredAccess = cmd_entry->dwDesiredAccess;
+    if (!dwDesiredAccess) dwDesiredAccess = SC_MANAGER_CONNECT + GENERIC_READ;
+
+    hSCManager = OpenSCManagerA(sc_machine_name, NULL, dwDesiredAccess);
+    //hSCManager = OpenSCManagerW(NULL, NULL, dwDesiredAccess);
+    if (hSCManager != NULL) {
+        result =  cmd_entry->funcptr(hSCManager, cmd_entry->sc_cmd, sc_cmd_arg);
+        if (!CloseServiceHandle(hSCManager)) {
+            dprintf("Failed to CLOSE handle to SCM.\n");
+            ReportLastError();
+        }
+    } else {
+        dprintf("Failed to open Service Control Manager.\n");
+        ReportLastError();
+    }
+    return result;
+}
+
+
+int __cdecl main(int argc, char* argv[])
+{
+    int i;
+    const char* sc_machine_name = NULL;
+    const char* sc_cmd_str = argv[1];
+    char** sc_cmd_arg = NULL;
+
+    AllocConsole();
+    InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+    OutputHandle =  GetStdHandle(STD_OUTPUT_HANDLE);
+
+    dprintf("%s application - build %03d (default: %s)\n", argv[0], VERSION, TARGET);
+    if (argc < 2) {
+        return usage(argv[0]);
+    }
+
+    if ((argv[1][0] == '\\') && (argv[1][1] == '\\')) {
+        if (argc < 3) {
+            return usage(argv[0]);
+        }
+        sc_machine_name = argv[1];
+        sc_cmd_str = argv[2];
+        sc_cmd_arg = &argv[3];
+    } else {
+        sc_machine_name = NULL;
+        sc_cmd_str = argv[1];
+        sc_cmd_arg = &argv[2];
+    }
+
+    for (i = 0; i < sizeof(sc_cmds_table)/sizeof(sc_cmd_entry); i++) {
+        sc_cmd_entry* cmd_entry = &(sc_cmds_table[i]);
+        if (lstrcmpiA(sc_cmd_str, cmd_entry->cmd_str) == 0) {
+            return sc_main(cmd_entry, sc_machine_name, sc_cmd_arg);
+        }
+    }
+    return usage(argv[0]);
+}
+
+
+#ifdef _NOCRT
+
+//char* args[] = { "sc.exe", "pause", "smplserv" };
+char* args[] = { "sc.exe", "EnumDepend", "" };
+
+int __cdecl mainCRTStartup(void)
+{
+    main(3, args);
+    return 0;
+}
+
+#endif /*_NOCRT*/
diff --git a/apps/utils/sc/main.h b/apps/utils/sc/main.h
new file mode 100644 (file)
index 0000000..c178571
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  ReactOS test program - 
+ *
+ *  main.h
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+DWORD ReportLastError(void);
+long getinput(char* Buffer, int buflen);
+void dprintf(char* fmt, ...);
+
+typedef enum tag_SC_CMDS {
+    SC_CMD_QUERY,
+    SC_CMD_QUERYEX,
+    SC_CMD_START,
+    SC_CMD_PAUSE,
+    SC_CMD_INTERROGATE,
+    SC_CMD_CONTINUE,
+    SC_CMD_STOP,
+    SC_CMD_CONFIG,
+    SC_CMD_DESCRIPTION,
+    SC_CMD_FAILURE,
+    SC_CMD_QC,
+    SC_CMD_QDESCRIPTION,
+    SC_CMD_QFAILURE,
+    SC_CMD_DELETE,
+    SC_CMD_CREATE,
+    SC_CMD_CONTROL,
+    SC_CMD_SDSHOW,
+    SC_CMD_SDSET,
+    SC_CMD_GETDISPLAYNAME,
+    SC_CMD_GETKEYNAME,
+    SC_CMD_ENUMDEPEND,
+    SC_CMD_BOOT,
+    SC_CMD_LOCK,
+    SC_CMD_QUERYLOCK
+} SC_CMDS;
+
+int sc_query(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_setup(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_config(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_command(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __MAIN_H__
diff --git a/apps/utils/sc/makefile b/apps/utils/sc/makefile
new file mode 100644 (file)
index 0000000..4cadccf
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = sc
+
+TARGET_CFLAGS = -DDBG
+
+TARGET_SDKLIBS = kernel32.a ntdll.a advapi32.a
+
+TARGET_OBJECTS = command.o config.o main.o query.o setup.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/utils/sc/query.c b/apps/utils/sc/query.c
new file mode 100644 (file)
index 0000000..fd03b2a
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  ReactOS SC - service control console program
+ *
+ *  query.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+
+int DisplayServiceInfo(BOOL display_ex)
+{
+    const char* type_str = "WIN32_SHARE_PROCESS";
+    const char* state_str = "RUNNING";
+    const char* flags_str = "RUNS_IN_SYSTEM_PROCESS";
+    const char* features_str = "NOT_STOPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN";
+
+    const char* ServiceName = "none";
+    const char* DisplayName = "none";
+    int Type;
+    int State;
+    int Win32ExitCode;
+    int ServiceExitCode;
+    int CheckPoint;
+    int WaitHint;
+    int Pid;
+    int Flags;
+
+    Type = 20;
+    State = 4;
+    Win32ExitCode = 0;
+    ServiceExitCode = 0;
+    CheckPoint = 0;
+    WaitHint = 0;
+    Pid = 0;
+    Flags = 0;
+
+    dprintf("\nSERVICE_NAME: %s\n", ServiceName);
+    dprintf("DISPLAY_NAME: %s\n", DisplayName);
+    dprintf("\tTYPE               : %d  %s\n", Type, type_str);
+    dprintf("\tSTATE              : %d  %s\n", State, state_str);
+    dprintf("\t                   :    (%s)\n", features_str);
+    dprintf("\tWIN32_EXIT_CODE    : %d  (0x%01x)\n", Win32ExitCode, Win32ExitCode);
+    dprintf("\tSERVICE_EXIT_CODE  : %d  (0x%01x)\n", ServiceExitCode, ServiceExitCode);
+    dprintf("\tCHECKPOINT         : 0x%01x\n", CheckPoint);
+    dprintf("\tWAIT_HINT          : 0x%01x\n", WaitHint);
+
+    if (display_ex) {
+        dprintf("\tPID                : %d\n", Pid);
+        dprintf("\tFLAGS              : %s\n", flags_str);
+    }
+
+    return 0;
+}
+
+int EnumServicesInfo(void)
+{
+    int entriesRead = 0;
+    int resumeIndex = 0;
+
+    dprintf("Enum: entriesRead = %d\n", entriesRead);
+    dprintf("Enum: resumeIndex = %d\n", resumeIndex);
+
+    DisplayServiceInfo(1);
+
+    return 0;
+}
+
+int sc_query(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+    switch (sc_cmd) {
+    case SC_CMD_QUERY:
+    case SC_CMD_QUERYEX:
+    case SC_CMD_QC:
+    case SC_CMD_QDESCRIPTION:
+    case SC_CMD_QFAILURE:
+    case SC_CMD_SDSHOW:
+    case SC_CMD_GETDISPLAYNAME:
+    case SC_CMD_GETKEYNAME:
+        dprintf("sc_query(%x, %d, %s) - command not implemented.\n", hSCManager, sc_cmd, argv[0]);
+        break;
+    case SC_CMD_ENUMDEPEND:
+        return EnumServicesInfo();
+//    case SC_CMD_QUERYLOCK:
+//        return sc_QueryLock(hSCManager);
+    default:
+        dprintf("sc_query(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+        break;
+    }
+    return 0;
+}
+
diff --git a/apps/utils/sc/setup.c b/apps/utils/sc/setup.c
new file mode 100644 (file)
index 0000000..ccbe9bc
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  ReactOS SC - service control console program
+ *
+ *  setup.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+int sc_delete(char* argv[])
+{
+    dprintf("sc_delete(%s) - not implemented.\n", argv[0]);
+    return 0;
+}
+
+int sc_boot(char* arg)
+{
+    dprintf("sc_boot(%s) - not implemented.\n", arg);
+    return 0;
+}
+
+int sc_setup(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+    dprintf("sc_setup(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[0]);
+
+    switch (sc_cmd) {
+//    case SC_CMD_DESCRIPTION:
+//    case SC_CMD_FAILURE:
+    case SC_CMD_DELETE:
+        return sc_delete(argv);
+    case SC_CMD_CREATE:
+        dprintf(" - not implemented.\n");
+        break;
+//    case SC_CMD_SDSHOW:
+//    case SC_CMD_SDSET:
+    case SC_CMD_BOOT:
+        return sc_boot(argv[0]);
+    default:
+        dprintf("sc_setup(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+        break;
+    }
+    return 0;
+}
+
diff --git a/apps/utils/stats/.cvsignore b/apps/utils/stats/.cvsignore
new file mode 100644 (file)
index 0000000..7e87816
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
diff --git a/apps/utils/tickcount/makefile b/apps/utils/tickcount/makefile
new file mode 100644 (file)
index 0000000..9679181
--- /dev/null
@@ -0,0 +1,19 @@
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = tickcount
+
+TARGET_SDKLIBS = kernel32.a
+
+TARGET_OBJECTS = tickcount.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/apps/utils/tickcount/tickcount.c b/apps/utils/tickcount/tickcount.c
new file mode 100644 (file)
index 0000000..c00674d
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id$
+*/
+/*
+ tickcount -- Display the kernel tick count in human-readable format
+
+ This is public domain software
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#define TICKS_YEAR   (TICKS_DAY * ((uint64_t)365))
+#define TICKS_MONTH  (TICKS_DAY * ((uint64_t)30))
+#define TICKS_WEEK   (TICKS_DAY * ((uint64_t)7))
+#define TICKS_DAY    (TICKS_HOUR * ((uint64_t)24))
+#define TICKS_HOUR   (TICKS_MINUTE * ((uint64_t)60))
+#define TICKS_MINUTE (TICKS_SECOND * ((uint64_t)60))
+#define TICKS_SECOND ((uint64_t)1000)
+
+#define SLICES_COUNT (sizeof(ticks_per_slice) / sizeof(ticks_per_slice[0]))
+
+uint64_t ticks_per_slice[] =
+{
+ TICKS_YEAR,
+ TICKS_MONTH,
+ TICKS_WEEK, 
+ TICKS_DAY,
+ TICKS_HOUR,
+ TICKS_MINUTE,
+ TICKS_SECOND,
+ 1
+};
+
+_TCHAR * slice_names_singular[] =
+{
+ _T("year"),
+ _T("month"),
+ _T("week"),
+ _T("day"),
+ _T("hour"),
+ _T("minute"),
+ _T("second"),
+ _T("millisecond")
+};
+
+_TCHAR * slice_names_plural[] =
+{
+ _T("years"),
+ _T("months"),
+ _T("weeks"),
+ _T("days"),
+ _T("hours"),
+ _T("minutes"),
+ _T("seconds"),
+ _T("milliseconds")
+};
+
+void print_uptime
+(
+ uint64_t tickcount,
+ uint64_t prevsliceval,
+ _TCHAR * prevsliceunit,
+ int curslice
+)
+{
+ uint64_t tick_cur = tickcount / ticks_per_slice[curslice];
+ uint64_t tick_residual = tickcount % ticks_per_slice[curslice];
+
+ assert(tick_cur <= (~((unsigned)0)));
+
+ if(tick_residual == 0)
+ {
+  /* the current slice is the last */
+
+  if(prevsliceval == 0)
+  {
+   /* the current slice is the only */
+   _tprintf
+   (
+    _T("%u %s"),
+    (unsigned)tick_cur,
+    (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
+   );
+  }
+  else
+  {
+   /* the current slice is the last, and there's a previous slice */
+   assert(prevsliceunit);
+
+   /* print the previous and the current slice, and terminate */
+   _tprintf
+   (
+    _T("%u %s %s %u %s"),
+    (unsigned)prevsliceval,
+    prevsliceunit,
+    _T("and"),
+    (unsigned)tick_cur,
+    (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
+   );   
+  }
+ }
+ else if(tick_cur != 0)
+ {
+  /* the current slice is not the last, and non-zero */
+
+  if(prevsliceval != 0)
+  {
+   /* there's a previous slice: print it */
+   assert(prevsliceunit);
+   _tprintf(_T("%u %s, "), (unsigned)prevsliceval, prevsliceunit);
+  }
+
+  /* recursion on the next slice size, storing the current slice */
+  print_uptime
+  (
+   tick_residual,
+   tick_cur,
+   (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice],
+   curslice + 1
+  );
+ }
+ else
+ {
+  /*
+   the current slice is not the last, and zero: recursion, remembering the
+   previous non-zero slice
+  */
+  print_uptime(tick_residual, prevsliceval, prevsliceunit, curslice + 1);
+ }
+}
+
+int _tmain()
+{
+ print_uptime((uint64_t)GetTickCount(), 0, NULL, 0);
+ _puttc(_T('\n'), stdout);
+ return 0;
+}
diff --git a/drivers/bus/acpi/ospm/busmgr/.cvsignore b/drivers/bus/acpi/ospm/busmgr/.cvsignore
new file mode 100644 (file)
index 0000000..31dc307
--- /dev/null
@@ -0,0 +1,2 @@
+*.d
+*.o
diff --git a/drivers/bus/acpi/resource/.cvsignore b/drivers/bus/acpi/resource/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/dd/vga/display/main/.cvsignore b/drivers/dd/vga/display/main/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/dd/vga/display/objects/.cvsignore b/drivers/dd/vga/display/objects/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/dd/vga/display/vgavideo/.cvsignore b/drivers/dd/vga/display/vgavideo/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/fs/fs_rec/udfs.c b/drivers/fs/fs_rec/udfs.c
new file mode 100644 (file)
index 0000000..ba7c1cf
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             drivers/fs/fs_rec/udfs.c
+ * PURPOSE:          Filesystem recognizer driver
+ * PROGRAMMER:       Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#include "fs_rec.h"
+
+
+#define UDFS_VRS_START_SECTOR   16
+#define UDFS_AVDP_SECTOR       256
+
+/* TYPES ********************************************************************/
+
+typedef struct _TAG
+{
+  USHORT Identifier;
+  USHORT Version;
+  UCHAR  Checksum;
+  UCHAR  Reserved;
+  USHORT SerialNumber;
+  USHORT Crc;
+  USHORT CrcLength;
+  ULONG  Location;
+} PACKED TAG, *PTAG;
+
+typedef struct _EXTENT
+{
+  ULONG Length;
+  ULONG Location;
+} PACKED EXTENT, *PEXTENT;
+
+typedef struct _AVDP
+{
+  TAG    DescriptorTag;
+  EXTENT MainVolumeDescriptorExtent;
+  EXTENT ReserveVolumeDescriptorExtent;
+} PACKED AVDP, *PAVDP;
+
+/* FUNCTIONS ****************************************************************/
+
+static NTSTATUS
+FsRecCheckVolumeRecognitionSequence(IN PDEVICE_OBJECT DeviceObject,
+                                   IN ULONG SectorSize)
+{
+  PUCHAR Buffer;
+  ULONG Sector;
+  NTSTATUS Status;
+  ULONG State;
+
+  Buffer = ExAllocatePool(NonPagedPool,
+                         SectorSize);
+  if (Buffer == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  State = 0;
+  Sector = UDFS_VRS_START_SECTOR;
+  while (TRUE)
+    {
+      Status = FsRecReadSectors(DeviceObject,
+                               Sector,
+                               1,
+                               SectorSize,
+                               Buffer);
+      if (!NT_SUCCESS(Status))
+       {
+         DPRINT1("FsRecReadSectors() failed (Status %lx)\n", Status);
+         break;
+       }
+
+      DPRINT1("Descriptor identifier: [%.5s]\n", Buffer + 1);
+
+      switch (State)
+       {
+         case 0:
+           if ((Sector == UDFS_VRS_START_SECTOR) &&
+               (Buffer[1] == 'B') &&
+               (Buffer[2] == 'E') &&
+               (Buffer[3] == 'A') &&
+               (Buffer[4] == '0') &&
+               (Buffer[5] == '1'))
+             {
+               State = 1;
+             }
+           else
+             {
+               DPRINT1("VRS start sector is not 'BEA01'\n");
+               ExFreePool(Buffer);
+               return(STATUS_UNRECOGNIZED_VOLUME);
+             }
+           break;
+
+         case 1:
+           if ((Buffer[1] == 'N') &&
+               (Buffer[2] == 'S') &&
+               (Buffer[3] == 'R') &&
+               (Buffer[4] == '0') &&
+               ((Buffer[5] == '2') || (Buffer[5] == '3')))
+             {
+               State = 2;
+             }
+           break;
+
+         case 2:
+           if ((Buffer[1] == 'T') &&
+               (Buffer[2] == 'E') &&
+               (Buffer[3] == 'A') &&
+               (Buffer[4] == '0') &&
+               (Buffer[5] == '1'))
+             {
+               DPRINT1("Found 'TEA01'\n");
+               ExFreePool(Buffer);
+               return(STATUS_SUCCESS);
+             }
+           break;
+       }
+
+      Sector++;
+      if (Sector == UDFS_AVDP_SECTOR)
+       {
+         DPRINT1("No 'TEA01' found\n");
+         ExFreePool(Buffer);
+         return(STATUS_UNRECOGNIZED_VOLUME);
+       }
+    }
+
+  ExFreePool(Buffer);
+
+  return(STATUS_UNRECOGNIZED_VOLUME);
+}
+
+
+static NTSTATUS
+FsRecCheckAnchorVolumeDescriptorPointer(IN PDEVICE_OBJECT DeviceObject,
+                                       IN ULONG SectorSize)
+{
+  PUCHAR Buffer;
+  ULONG Sector;
+  NTSTATUS Status;
+  PAVDP Avdp;
+
+  Buffer = ExAllocatePool(NonPagedPool,
+                         SectorSize);
+  if (Buffer == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  Sector = UDFS_AVDP_SECTOR;
+  Status = FsRecReadSectors(DeviceObject,
+                           Sector,
+                           1,
+                           SectorSize,
+                           Buffer);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("FsRecReadSectors() failed (Status %lx)\n", Status);
+      ExFreePool(Buffer);
+      return(Status);
+    }
+
+  Avdp = (PAVDP)Buffer;
+  DPRINT1("Descriptor identifier: %hu\n", Avdp->DescriptorTag.Identifier);
+
+  DPRINT1("Main volume descriptor sequence location: %lu\n",
+         Avdp->MainVolumeDescriptorExtent.Location);
+
+  DPRINT1("Main volume descriptor sequence length: %lu\n",
+         Avdp->MainVolumeDescriptorExtent.Length);
+
+  DPRINT1("Reserve volume descriptor sequence location: %lu\n",
+         Avdp->ReserveVolumeDescriptorExtent.Location);
+
+  DPRINT1("Reserve volume descriptor sequence length: %lu\n",
+         Avdp->ReserveVolumeDescriptorExtent.Length);
+
+  ExFreePool(Buffer);
+
+//  return(Status);
+  return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS
+FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject)
+{
+  DISK_GEOMETRY DiskGeometry;
+  ULONG Size;
+  NTSTATUS Status;
+
+  Size = sizeof(DISK_GEOMETRY);
+  Status = FsRecDeviceIoControl(DeviceObject,
+                               IOCTL_CDROM_GET_DRIVE_GEOMETRY,
+                               NULL,
+                               0,
+                               &DiskGeometry,
+                               &Size);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("FsRecDeviceIoControl() failed (Status %lx)\n", Status);
+      return(Status);
+    }
+  DPRINT1("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
+
+  /* Check the volume recognition sequence */
+  Status = FsRecCheckVolumeRecognitionSequence(DeviceObject,
+                                              DiskGeometry.BytesPerSector);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  Status = FsRecCheckAnchorVolumeDescriptorPointer(DeviceObject,
+                                                  DiskGeometry.BytesPerSector);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+  PIO_STACK_LOCATION Stack;
+  UNICODE_STRING RegistryPath;
+  NTSTATUS Status;
+
+  Stack = IoGetCurrentIrpStackLocation(Irp);
+
+  switch (Stack->MinorFunction)
+    {
+      case IRP_MN_MOUNT_VOLUME:
+       DPRINT("Udfs: IRP_MN_MOUNT_VOLUME\n");
+       Status = FsRecIsUdfsVolume(Stack->Parameters.MountVolume.DeviceObject);
+       if (NT_SUCCESS(Status))
+         {
+           DPRINT("Identified UDFS volume\n");
+           Status = STATUS_FS_DRIVER_REQUIRED;
+         }
+       break;
+
+      case IRP_MN_LOAD_FILE_SYSTEM:
+       DPRINT("Udfs: IRP_MN_LOAD_FILE_SYSTEM\n");
+       RtlInitUnicodeStringFromLiteral(&RegistryPath,
+                            L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs");
+       Status = ZwLoadDriver(&RegistryPath);
+       if (!NT_SUCCESS(Status))
+         {
+           DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
+         }
+       else
+         {
+           IoUnregisterFileSystem(DeviceObject);
+         }
+       break;
+
+      default:
+       DPRINT("Udfs: Unknown minor function %lx\n", Stack->MinorFunction);
+       Status = STATUS_INVALID_DEVICE_REQUEST;
+       break;
+    }
+  return(Status);
+}
+
+/* EOF */
diff --git a/drivers/fs/vfat/flush.c b/drivers/fs/vfat/flush.c
new file mode 100644 (file)
index 0000000..7262598
--- /dev/null
@@ -0,0 +1,119 @@
+/* $Id$
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             drivers/fs/vfat/flush.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Hartmut Birr
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include "vfat.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
+{
+   IO_STATUS_BLOCK IoStatus;
+
+   DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%S'\n", DeviceExt, Fcb, Fcb->PathName);
+
+   CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
+   if (IoStatus.Status == STATUS_INVALID_PARAMETER)
+   {
+      /* FIXME: Caching was possible not initialized */
+      IoStatus.Status = STATUS_SUCCESS;
+   }
+   return IoStatus.Status;
+}
+
+NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
+{
+   PLIST_ENTRY ListEntry;
+   PVFATFCB Fcb;
+   PVFATCCB Ccb;
+   NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
+
+   DPRINT("VfatFlushVolume(DeviceExt %x, FatFcb %x)\n", DeviceExt, VolumeFcb);
+
+   ListEntry = DeviceExt->FcbListHead.Flink;
+   while (ListEntry != &DeviceExt->FcbListHead)
+   {
+      Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
+      ListEntry = ListEntry->Flink;
+      ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+      Status = VfatFlushFile(DeviceExt, Fcb);
+      ExReleaseResourceLite (&Fcb->MainResource);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+        ReturnStatus = Status;
+      }
+      /* FIXME: Stop flushing if this a removable media and the media was removed */
+   }
+
+   Ccb = (PVFATCCB) DeviceExt->FATFileObject->FsContext2;
+   Fcb =  Ccb->pFcb;
+  
+   ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+   Status = VfatFlushFile(DeviceExt, Fcb);
+   ExReleaseResourceLite(&DeviceExt->FatResource);
+
+   /* FIXME: Flush the buffers from storage device */
+
+   if (!NT_SUCCESS(Status))
+   {
+      DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+      ReturnStatus = Status;
+   }
+
+   return ReturnStatus;
+}
+
+NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext)
+{
+  NTSTATUS Status;
+  PVFATFCB Fcb;
+  PVFATCCB Ccb;
+  /*
+   * This request is not allowed on the main device object.
+   */
+  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
+  {
+     Status = STATUS_INVALID_DEVICE_REQUEST;
+     goto ByeBye;
+  }
+
+  Ccb = (PVFATCCB) IrpContext->FileObject->FsContext2;
+  assert(Ccb);
+  Fcb =  Ccb->pFcb;
+  assert(Fcb);
+
+  if (Fcb->Flags & FCB_IS_VOLUME)
+  {
+     ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
+     Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
+     ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
+  }
+  else
+  {
+     ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+     Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
+     ExReleaseResourceLite (&Fcb->MainResource);
+  }
+
+ByeBye:
+  IrpContext->Irp->IoStatus.Status = Status;
+  IrpContext->Irp->IoStatus.Information = 0;
+  IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
+  VfatFreeIrpContext(IrpContext);
+
+  return (Status);
+}
+
+/* EOF */
diff --git a/drivers/lib/bzip2/.cvsignore b/drivers/lib/bzip2/.cvsignore
new file mode 100644 (file)
index 0000000..80ade3d
--- /dev/null
@@ -0,0 +1,5 @@
+unbzip2.sys
+unbzip2.nostrip.sys
+unbzip2.sym
+*.d
+*.o
\ No newline at end of file
diff --git a/drivers/net/afd/afd/.cvsignore b/drivers/net/afd/afd/.cvsignore
new file mode 100644 (file)
index 0000000..d273b98
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.sym
+*.d
diff --git a/drivers/net/dd/ne2000/ne2000/.cvsignore b/drivers/net/dd/ne2000/ne2000/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/ndis/ndis/.cvsignore b/drivers/net/ndis/ndis/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/npf/.cvsignore b/drivers/net/npf/.cvsignore
new file mode 100644 (file)
index 0000000..d7687d4
--- /dev/null
@@ -0,0 +1,5 @@
+*.coff
+*.d
+*.o
+*.sym
+*.sys
diff --git a/drivers/net/npf/Makefile b/drivers/net/npf/Makefile
new file mode 100644 (file)
index 0000000..4d66ad3
--- /dev/null
@@ -0,0 +1,38 @@
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+#TARGET_TYPE = export_driver
+TARGET_TYPE = driver
+
+TARGET_NAME = npf
+
+#TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -I$(PATH_TO_TOP)/ntoskrnl/include
+
+TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -DUSE_KLOCKS -I$(PATH_TO_TOP)/ntoskrnl/include
+
+TARGET_DDKLIBS = ndis.a
+
+TARGET_OBJECTS = \
+       packet.o    \
+       openclos.o  \
+       read.o      \
+       write.o     \
+       dump.o      \
+       jitter.o      \
+       win_bpf_filter.o \
+       tme.o \
+       count_packets.o \
+       win_bpf_filter_init.o \
+       tcp_session.o \
+       memory_t.o \
+       time_calls.o \
+       functions.o \
+       bucket_lookup.o \
+       normal_lookup.o
+
+TARGET_PATH = .
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
diff --git a/drivers/net/npf/bucket_lookup.c b/drivers/net/npf/bucket_lookup.c
new file mode 100644 (file)
index 0000000..e2c5fde
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "bucket_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/bucket_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/bucket_lookup.h>
+#endif
+
+#endif
+
+
+
+/* the key is represented by the initial and final value */
+/* of the bucket. At the moment bucket_lookup is able to */
+/* manage values of 16, 32 bits.                         */
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)  
+{
+       uint32 value;
+       uint32 i,j;
+       int found=-1;
+       uint32 blocks;
+       uint32 block_size;
+       uint8 *temp;
+       if ((data->key_len!=1)&&  /*16 bit value*/
+               (data->key_len!=2))   /*32 bit value*/
+               return TME_ERROR;
+       
+       /*32 bit values*/
+       blocks=data->filled_blocks-1;
+       block_size=data->block_size;
+       i=blocks/2; /*relative shift*/
+       j=i;
+       temp=data->shared_memory_base_address+block_size;
+
+       if (data->key_len==2)
+       {
+               value=SW_ULONG_AT(key,0);
+       
+               if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
+               {
+                       uint32 *key32=(uint32*) key;
+                       key32[0]=key32[1]=0;
+
+                       GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+                       data->last_found=NULL;
+                       return TME_FALSE;
+               }
+                       
+               while(found==-1) /* search routine */
+               {   
+                       i=(i==1)? 1:i>>1;
+                       if (SW_ULONG_AT(temp+block_size*j,0)>value)
+                               if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
+                                       found=-2;
+                               else
+                                       j-=i;
+                       else
+                               if (SW_ULONG_AT(temp+block_size*j,4)<value) 
+                                       if (SW_ULONG_AT(temp+block_size*j,0)>value)
+                                               found=-2;
+                                       else
+                                               j+=i;
+                               else found=j;
+               }       
+               if (found<0)
+               {
+                       uint32 *key32=(uint32*) key;
+                       key32[0]=key32[1]=0;
+
+                       GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+                       
+                       data->last_found=NULL;
+                       return TME_FALSE;
+               }
+       
+               data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+               COPY_MEMORY(key,temp+block_size*found,8);
+
+               GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
+
+               return TME_TRUE;
+       }
+       else
+       {
+               value=SW_USHORT_AT(key,0);
+       
+               if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
+               {
+                       uint16 *key16=(uint16*) key;
+                       key16[0]=key16[1]=0;
+                       
+                       GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+                       data->last_found=NULL;
+                       return TME_FALSE;
+               }
+                       
+               while(found==-1) /* search routine */
+               {   
+                       i=(i==1)? 1:i>>1;
+                       if (SW_USHORT_AT(temp+block_size*j,0)>value)
+                               if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
+                                       found=-2;
+                               else
+                                       j-=i;
+                       else
+                               if (SW_USHORT_AT(temp+block_size*j,2)<value) 
+                                       if (SW_USHORT_AT(temp+block_size*j,0)>value)
+                                               found=-2;
+                                       else
+                                               j+=i;
+                               else found=j;
+               }       
+
+               if (found<0)
+               {
+                       uint16 *key16=(uint16*) key;
+                       key16[0]=key16[1]=0;
+
+                       GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+                       data->last_found=NULL;
+                       return TME_FALSE;
+               }
+       
+               data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+               GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
+
+               COPY_MEMORY(key,temp+block_size*found,4);
+               
+               return TME_TRUE;
+       }
+               
+}
+
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)   
+{      
+       RECORD *records=(RECORD*)data->lut_base_address;
+
+       if ((data->key_len!=1)&&  /*16 bit value*/
+               (data->key_len!=2))   /*32 bit value*/
+               return TME_ERROR;
+
+       if(data->key_len==2)
+       {
+               uint32 start,stop;
+               uint8 *tmp;
+
+               start=SW_ULONG_AT(key,0);       
+               stop=SW_ULONG_AT(key,4);
+
+               if (start>stop)
+                       return TME_ERROR;
+               if (data->filled_entries>0)
+               {
+                       tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);               
+                       /*check if it is coherent with the previous block*/
+                       if (SW_ULONG_AT(tmp,4)>=start)
+                               return TME_ERROR;
+               }
+               
+               if (data->filled_blocks==data->shared_memory_blocks)
+                       return TME_ERROR;
+
+               if (data->filled_entries==data->lut_entries)
+                       return TME_ERROR;
+
+               tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;              
+               
+               COPY_MEMORY(tmp,key,8);
+               
+               SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+               SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+               
+               GET_TIME((struct timeval *)(tmp+8),time_ref);           
+               
+               data->filled_blocks++;
+               data->filled_entries++;
+               
+               return TME_TRUE;
+       }
+       else
+       {
+               uint16 start,stop;
+               uint8 *tmp;
+
+               start=SW_USHORT_AT(key,0);      
+               stop=SW_USHORT_AT(key,2);
+
+               if (start>stop)
+                       return TME_ERROR;
+               if (data->filled_entries>0)
+               {
+                       tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);               
+                       /*check if it is coherent with the previous block*/
+                       if (SW_USHORT_AT(tmp,2)>=start)
+                               return TME_ERROR;
+               }
+               
+               if (data->filled_blocks==data->shared_memory_blocks)
+                       return TME_ERROR;
+
+               if (data->filled_entries==data->lut_entries)
+                       return TME_ERROR;
+
+               tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);         
+               
+               COPY_MEMORY(tmp,key,4);
+               
+               SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+               SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+               
+               GET_TIME((struct timeval *)(tmp+4),time_ref);           
+               
+               data->filled_blocks++;
+               data->filled_entries++;
+               
+               return TME_TRUE;
+       }
+}
\ No newline at end of file
diff --git a/drivers/net/npf/bucket_lookup.h b/drivers/net/npf/bucket_lookup.h
new file mode 100644 (file)
index 0000000..512d637
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define BUCKET_LOOKUP_INSERT    0x00000011
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define BUCKET_LOOKUP           0x00000010
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/count_packets.c b/drivers/net/npf/count_packets.c
new file mode 100644 (file)
index 0000000..71aa61f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "count_packets.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/count_packets.h>
+#else
+#include <tme/tme.h>
+#include <tme/count_packets.h>
+#endif
+
+#endif
+
+
+
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+{
+               
+       c_p_data *counters=(c_p_data*)(block+data->key_len*4);
+
+       counters->bytes+=pkt_size;
+       counters->packets++;
+       
+       return TME_SUCCESS;
+
+}
diff --git a/drivers/net/npf/count_packets.h b/drivers/net/npf/count_packets.h
new file mode 100644 (file)
index 0000000..819b5b5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+typedef struct __c_p_data
+{
+    struct timeval timestamp;
+    uint64 packets;
+    uint64 bytes;
+}
+    c_p_data;
+
+#define COUNT_PACKETS                   0x00000000
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
+
diff --git a/drivers/net/npf/debug.h b/drivers/net/npf/debug.h
new file mode 100644 (file)
index 0000000..7461b8b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1999, 2000
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
+
+
+#if DBG
+
+#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
+extern ULONG PacketDebugFlag;
+
+#define PACKET_DEBUG_LOUD               0x00000001  // debugging info
+#define PACKET_DEBUG_VERY_LOUD          0x00000002  // excessive debugging info
+
+#define PACKET_DEBUG_INIT               0x00000100  // init debugging info
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
+#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_LOUD(A)
+
+#endif
+
+#endif /*#define __DEBUG_INCLUDE*/
diff --git a/drivers/net/npf/dump.c b/drivers/net/npf/dump.c
new file mode 100644 (file)
index 0000000..1f1b754
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 1999, 2000
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+//#define PsGetCurrentProcess() IoGetCurrentProcess()
+#define PsGetCurrentThread() ((PETHREAD) (KeGetCurrentThread()))
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
+{
+    NTSTATUS ntStatus;
+    IO_STATUS_BLOCK IoStatus;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PWCHAR PathPrefix;
+    USHORT PathLen;
+    UNICODE_STRING FullFileName;
+    ULONG FullFileNameLength;
+    PDEVICE_OBJECT fsdDevice;
+
+    FILE_STANDARD_INFORMATION StandardInfo;
+    
+    IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+    if(fileName->Buffer[0] == L'\\' &&
+        fileName->Buffer[1] == L'?' &&
+        fileName->Buffer[2] == L'?' &&
+        fileName->Buffer[3] == L'\\'
+    ){
+        PathLen = 0;
+    }
+    else{
+        PathPrefix = L"\\??\\";
+        PathLen = 8;
+    }
+    
+    // Insert the correct path prefix.
+    FullFileNameLength = PathLen + fileName->MaximumLength;
+    
+#define NPF_TAG_FILENAME  TAG('0', 'D', 'W', 'A')
+    FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 
+        FullFileNameLength,
+        NPF_TAG_FILENAME);
+    
+    if (FullFileName.Buffer == NULL) {
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        return ntStatus;
+    }
+    
+    FullFileName.Length = PathLen;
+    FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+    
+    if(PathLen)
+        RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+    
+    RtlAppendUnicodeStringToString (&FullFileName, fileName);
+    
+    IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+    
+    InitializeObjectAttributes ( &ObjectAttributes,
+        &FullFileName,
+        OBJ_CASE_INSENSITIVE,
+        NULL,
+        NULL );
+    
+    // Create the dump file
+    ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+        SYNCHRONIZE | FILE_WRITE_DATA,
+        &ObjectAttributes,
+        &IoStatus,
+        NULL,
+        FILE_ATTRIBUTE_NORMAL,
+        FILE_SHARE_READ,
+        (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+        FILE_SYNCHRONOUS_IO_NONALERT,
+        NULL,
+        0 );
+
+    if ( !NT_SUCCESS( ntStatus ) )
+    {
+        IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+        
+        ExFreePool(FullFileName.Buffer);
+        Open->DumpFileHandle=NULL;
+        ntStatus = STATUS_NO_SUCH_FILE;
+        return ntStatus;
+    }
+    
+    ExFreePool(FullFileName.Buffer);
+    
+    ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+        FILE_WRITE_ACCESS,
+#ifndef __GNUC__
+        *IoFileObjectType,
+#else
+        IoFileObjectType,
+#endif
+        KernelMode,
+        (PVOID)&Open->DumpFileObject,
+        0);
+    
+    if ( !NT_SUCCESS( ntStatus ) )
+    {
+        IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+            
+        ZwClose( Open->DumpFileHandle );
+        Open->DumpFileHandle=NULL;
+        
+        ntStatus = STATUS_NO_SUCH_FILE;
+        return ntStatus;
+    }
+    
+    fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+    IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+    return ntStatus;
+}   
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+    NTSTATUS ntStatus;
+    struct packet_file_header hdr;
+    IO_STATUS_BLOCK IoStatus;
+    NDIS_REQUEST pRequest;
+    ULONG MediaType;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+
+    IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+    // Init the file header
+    hdr.magic = TCPDUMP_MAGIC;
+    hdr.version_major = PCAP_VERSION_MAJOR;
+    hdr.version_minor = PCAP_VERSION_MINOR;
+    hdr.thiszone = 0; /*Currently not set*/
+    hdr.snaplen = 1514;
+    hdr.sigfigs = 0;
+
+    // Detect the medium type
+    switch (Open->Medium){
+        
+    case NdisMediumWan:
+        hdr.linktype = DLT_EN10MB;
+        break;
+        
+    case NdisMedium802_3:
+        hdr.linktype = DLT_EN10MB;
+        break;
+        
+    case NdisMediumFddi:
+        hdr.linktype = DLT_FDDI;
+        break;
+        
+    case NdisMedium802_5:           
+        hdr.linktype = DLT_IEEE802; 
+        break;
+        
+    case NdisMediumArcnet878_2:
+        hdr.linktype = DLT_ARCNET;
+        break;
+        
+    case NdisMediumAtm:
+        hdr.linktype = DLT_ATM_RFC1483;
+        break;
+        
+    default:
+        hdr.linktype = DLT_EN10MB;
+    }
+
+    // Write the header.
+    // We can use ZwWriteFile because we are in the context of the application
+    ntStatus = ZwWriteFile(Open->DumpFileHandle,
+        NULL,
+        NULL,
+        NULL,
+        &IoStatus,
+        &hdr,
+        sizeof(hdr),
+        NULL,
+        NULL );
+
+    
+    if ( !NT_SUCCESS( ntStatus ) )
+    {
+        IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+        
+        ZwClose( Open->DumpFileHandle );
+        Open->DumpFileHandle=NULL;
+        
+        ntStatus = STATUS_NO_SUCH_FILE;
+        return ntStatus;
+    }
+
+    Open->DumpOffset.QuadPart=24;
+            
+    ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+        THREAD_ALL_ACCESS,
+        (ACCESS_MASK)0L,
+        0,
+        0,
+        (PKSTART_ROUTINE)NPF_DumpThread,
+        Open);
+    
+    if ( !NT_SUCCESS( ntStatus ) )
+    {
+        IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+        
+        ZwClose( Open->DumpFileHandle );
+        Open->DumpFileHandle=NULL;
+
+        return ntStatus;
+    }  
+    ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+        THREAD_ALL_ACCESS,
+        NULL,
+        KernelMode,
+        (PVOID*)&Open->DumpThreadObject,
+        0);
+    if ( !NT_SUCCESS( ntStatus ) )
+    {
+        IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+        
+        ObDereferenceObject(Open->DumpFileObject);
+        ZwClose( Open->DumpFileHandle );
+        Open->DumpFileHandle=NULL;
+
+        return ntStatus;
+    }  
+  
+    return ntStatus;
+    
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+    ULONG       FrozenNic;
+
+    IF_LOUD(DbgPrint("NPF: In the work routine.  Parameter = 0x%0x\n",Open);)
+
+    while(TRUE){
+
+        // Wait until some packets arrive or the timeout expires
+        NdisWaitEvent(&Open->DumpEvent, 5000);  
+
+        IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
+            
+        if(Open->DumpLimitReached ||
+            Open->BufSize==0){      // BufSize=0 means that this instance was closed, or that the buffer is too
+                                    // small for any capture. In both cases it is better to end the dump
+
+            IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+            IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+            PsTerminateSystemThread(STATUS_SUCCESS);
+            return;
+        }
+        
+        NdisResetEvent(&Open->DumpEvent);
+
+        // Write the content of the buffer to the file
+        if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+            PsTerminateSystemThread(STATUS_SUCCESS);
+            return;
+        }
+    
+    }
+    
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+    UINT        Thead;
+    UINT        Ttail;
+    UINT        TLastByte;
+    PUCHAR      CurrBuff;
+    NTSTATUS    ntStatus;
+    IO_STATUS_BLOCK IoStatus;
+    PMDL        lMdl;
+    UINT        SizeToDump;
+
+    
+    Thead=Open->Bhead;
+    Ttail=Open->Btail;
+    TLastByte=Open->BLastByte;
+    
+    IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+    // Get the address of the buffer
+    CurrBuff=Open->Buffer;
+    //
+    // Fill the application buffer
+    //
+    if( Ttail < Thead )
+    {
+        if(Open->MaxDumpBytes &&
+            (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
+        {
+            // Size limit reached
+            UINT PktLen;
+            
+            SizeToDump = 0;
+            
+            // Scan the buffer to detect the exact amount of data to save
+            while(TRUE){
+                PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+                
+                if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+                    break;
+                
+                SizeToDump += PktLen;
+            }
+            
+        }
+        else
+            SizeToDump = TLastByte-Thead;
+        
+        lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+        if (lMdl == NULL)
+        {
+            // No memory: stop dump
+            IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        MmBuildMdlForNonPagedPool(lMdl);
+        
+        // Write to disk
+        NPF_WriteDumpFile(Open->DumpFileObject,
+            &Open->DumpOffset,
+            SizeToDump,
+            lMdl,
+            &IoStatus);
+        
+        IoFreeMdl(lMdl);
+        
+        if(!NT_SUCCESS(IoStatus.Status)){
+            // Error
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        if(SizeToDump != TLastByte-Thead){
+            // Size limit reached.
+            Open->DumpLimitReached = TRUE;
+    
+            // Awake the application
+            KeSetEvent(Open->ReadEvent,0,FALSE);
+
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        // Update the packet buffer
+        Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+        Open->BLastByte=Ttail;
+        Open->Bhead=0;
+    }
+
+    if( Ttail > Thead ){
+        
+        if(Open->MaxDumpBytes &&
+            (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
+        {
+            // Size limit reached
+            UINT PktLen;
+                        
+            SizeToDump = 0;
+            
+            // Scan the buffer to detect the exact amount of data to save
+            while(Thead + SizeToDump < Ttail){
+
+                PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+                
+                if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+                    break;
+                
+                SizeToDump += PktLen;
+            }
+            
+        }
+        else
+            SizeToDump = Ttail-Thead;
+                
+        lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+        if (lMdl == NULL)
+        {
+            // No memory: stop dump
+            IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        MmBuildMdlForNonPagedPool(lMdl);
+        
+        // Write to disk
+        NPF_WriteDumpFile(Open->DumpFileObject,
+            &Open->DumpOffset,
+            SizeToDump,
+            lMdl,
+            &IoStatus);
+        
+        IoFreeMdl(lMdl);
+        
+        if(!NT_SUCCESS(IoStatus.Status)){
+            // Error
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        if(SizeToDump != Ttail-Thead){
+            // Size limit reached.
+            Open->DumpLimitReached = TRUE;
+
+            // Awake the application
+            KeSetEvent(Open->ReadEvent,0,FALSE);
+            
+            return STATUS_UNSUCCESSFUL;
+        }
+        
+        // Update the packet buffer
+        Open->DumpOffset.QuadPart+=(Ttail-Thead);           
+        Open->Bhead=Ttail;
+        
+    }
+
+    return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+    NTSTATUS    ntStatus;
+    IO_STATUS_BLOCK IoStatus;
+    PMDL        WriteMdl;
+    PUCHAR      VMBuff;
+    UINT        VMBufLen;
+
+
+    IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+    IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+    // Consistency check
+    if(Open->DumpFileHandle == NULL)
+        return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+    ZwClose( Open->DumpFileHandle );
+
+    ObDereferenceObject(Open->DumpFileObject);
+/*
+    if(Open->DumpLimitReached == TRUE)
+        // Limit already reached: don't save the rest of the buffer.
+        return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+    NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+    // Flush the buffer to file 
+    NPF_SaveCurrentBuffer(Open);
+
+    // Close The file
+    ObDereferenceObject(Open->DumpFileObject);
+    ZwClose( Open->DumpFileHandle );
+    
+    Open->DumpFileHandle = NULL;
+
+    ObDereferenceObject(Open->DumpFileObject);
+
+    return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+#ifndef __GNUC__
+static NTSTATUS 
+#else
+NTSTATUS STDCALL
+#endif
+PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+                                PIRP Irp,
+                                PVOID Context)
+{
+
+    // Copy the status information back into the "user" IOSB
+    *Irp->UserIosb = Irp->IoStatus;
+    
+    // Wake up the mainline code
+    KeSetEvent(Irp->UserEvent, 0, FALSE);
+          
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+                                PLARGE_INTEGER Offset,
+                                ULONG Length,
+                                PMDL Mdl,
+                                PIO_STATUS_BLOCK IoStatusBlock)
+{
+    PIRP irp;
+    KEVENT event;
+    PIO_STACK_LOCATION ioStackLocation;
+    PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
+    NTSTATUS Status;
+    // Set up the event we'll use
+    KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+    
+    // Allocate and build the IRP we'll be sending to the FSD
+    irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
+
+    if (!irp) {
+        // Allocation failed, presumably due to memory allocation failure
+        IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoStatusBlock->Information = 0;
+
+        return;
+    }
+
+    irp->MdlAddress = Mdl;
+    irp->UserEvent = &event;
+    irp->UserIosb = IoStatusBlock;
+    irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    irp->Tail.Overlay.OriginalFileObject= FileObject;
+    irp->RequestorMode = KernelMode;
+
+    // Indicate that this is a WRITE operation
+    irp->Flags = IRP_WRITE_OPERATION;
+
+    // Set up the next I/O stack location
+    ioStackLocation = IoGetNextIrpStackLocation(irp);
+    ioStackLocation->MajorFunction = IRP_MJ_WRITE;
+    ioStackLocation->MinorFunction = 0;
+    ioStackLocation->DeviceObject = fsdDevice;
+    ioStackLocation->FileObject = FileObject;
+    IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
+    ioStackLocation->Parameters.Write.Length = Length;
+    ioStackLocation->Parameters.Write.ByteOffset = *Offset;
+
+
+    // Send it on.  Ignore the return code
+    (void) IoCallDriver(fsdDevice, irp);
+
+    // Wait for the I/O to complete.
+    KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
+
+    // Free the IRP now that we are done with it
+    IoFreeIrp(irp);
+
+    return;
+}
diff --git a/drivers/net/npf/functions.c b/drivers/net/npf/functions.c
new file mode 100644 (file)
index 0000000..04c7e4b
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "functions.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/bpf.h>
+#include <net/tme/functions.h>
+#else
+#include <tme/tme.h>
+#include <bpf.h>
+#include <tme/functions.h>
+#endif
+
+#endif
+
+
+
+lut_fcn lut_fcn_mapper(uint32 index)
+{
+
+       switch (index)
+       {
+       case NORMAL_LUT_W_INSERT:
+               return (lut_fcn) normal_lut_w_insert;
+
+       case NORMAL_LUT_WO_INSERT:
+               return (lut_fcn) normal_lut_wo_insert;
+
+       case BUCKET_LOOKUP:
+               return (lut_fcn) bucket_lookup;
+
+       case BUCKET_LOOKUP_INSERT:
+               return (lut_fcn) bucket_lookup_insert;
+       
+       default:
+               return NULL;
+       }
+       
+       return NULL;
+
+}
+
+exec_fcn exec_fcn_mapper(uint32 index)
+{
+       switch (index)
+       {
+       case COUNT_PACKETS:
+               return (exec_fcn) count_packets;
+       
+       case TCP_SESSION:
+               return (exec_fcn) tcp_session;
+       default:
+               return NULL;
+       }
+       
+       return NULL;
+}
diff --git a/drivers/net/npf/functions.h b/drivers/net/npf/functions.h
new file mode 100644 (file)
index 0000000..d25c679
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+/*function mappers */
+
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+/* lookup functions */
+
+#ifdef WIN32
+#include "bucket_lookup.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/bucket_lookup.h>
+#include <net/tme/normal_lookup.h>
+#endif
+
+/* execution functions */
+
+#ifdef WIN32
+#include "count_packets.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/count_packets.h>
+#include <ne/tme/tcp_session.h>
+#endif
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/jitter.c b/drivers/net/npf/jitter.c
new file mode 100644 (file)
index 0000000..2be1cf9
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 2002
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "packet.h"
+#include "win_bpf.h"
+
+emit_func emitm;
+
+//
+// emit routine to update the jump table
+//
+void emit_lenght(binary_stream *stream, ULONG value, UINT len)
+{
+    (stream->refs)[stream->bpf_pc]+=len;
+    stream->cur_ip+=len;
+}
+
+//
+// emit routine to output the actual binary code
+//
+void emit_code(binary_stream *stream, ULONG value, UINT len)
+{
+    
+    switch (len){
+
+    case 1:
+        stream->ibuf[stream->cur_ip]=(UCHAR)value;
+        stream->cur_ip++;
+        break;
+
+    case 2:
+        *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
+        stream->cur_ip+=2;
+        break;
+
+    case 4:
+        *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
+        stream->cur_ip+=4;
+        break;
+
+    default:;
+    
+    }
+
+    return;
+
+}
+
+//
+// Function that does the real stuff
+//
+BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
+{
+    struct bpf_insn *ins;
+    UINT i, pass;
+    binary_stream stream;
+
+
+    // Allocate the reference table for the jumps
+#ifdef NTKERNEL
+#define NPF_TAG_REFTABLE  TAG('0', 'J', 'W', 'A')
+    stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), NPF_TAG_REFTABLE);
+#else
+    stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
+#endif
+    if(stream.refs==NULL) 
+    {
+        return NULL;
+    }
+
+    // Reset the reference table
+    for(i=0; i< nins + 1; i++)
+        stream.refs[i]=0;
+
+    stream.cur_ip=0;
+    stream.bpf_pc=0;
+
+    // the first pass will emit the lengths of the instructions 
+    // to create the reference table
+    emitm=emit_lenght;
+    
+    for(pass=0;;){
+
+        ins = prog;
+
+        /* create the procedure header */
+        PUSH(EBP)
+        MOVrd(EBP,ESP)
+        PUSH(EBX)
+        PUSH(ECX)
+        PUSH(EDX)
+        PUSH(ESI)
+        PUSH(EDI)
+        MOVodd(EBX, EBP, 8)
+
+        for(i=0;i<nins;i++){
+            
+            stream.bpf_pc++;
+            
+            switch (ins->code) {
+                
+            default:
+                
+                return NULL;
+                
+            case BPF_RET|BPF_K:
+                
+                MOVid(EAX,ins->k)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                RET()
+                
+                break;
+                
+
+            case BPF_RET|BPF_A:
+                
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                RET()
+                
+                break;
+
+                
+            case BPF_LD|BPF_W|BPF_ABS:
+                
+                MOVid(ECX,ins->k)
+                MOVrd(ESI,ECX)
+                ADDib(ECX,sizeof(INT))
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  //this can be optimized with xor eax,eax
+                RET()
+                MOVobd(EAX, EBX, ESI)
+                BSWAP(EAX)
+
+                break;
+
+            case BPF_LD|BPF_H|BPF_ABS:
+
+                MOVid(ECX,ins->k)
+                MOVrd(ESI,ECX)
+                ADDib(ECX,sizeof(SHORT))
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVid(EAX,0)  
+                MOVobw(AX, EBX, ESI)
+                SWAP_AX()
+
+                break;
+                
+            case BPF_LD|BPF_B|BPF_ABS:
+            
+                MOVid(ECX,ins->k)
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVid(EAX,0)  
+                MOVobb(AL,EBX,ECX)
+
+                break;
+
+            case BPF_LD|BPF_W|BPF_LEN:
+
+                MOVodd(EAX, EBP, 0xc)
+
+                break;
+
+            case BPF_LDX|BPF_W|BPF_LEN:
+
+                MOVodd(EDX, EBP, 0xc)
+
+                break;
+            
+            case BPF_LD|BPF_W|BPF_IND:
+            
+                MOVid(ECX,ins->k)
+                ADDrd(ECX,EDX)
+                MOVrd(ESI,ECX)
+                ADDib(ECX,sizeof(INT))
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVobd(EAX, EBX, ESI)
+                BSWAP(EAX)
+
+                break;
+
+            case BPF_LD|BPF_H|BPF_IND:
+
+                MOVid(ECX,ins->k)
+                ADDrd(ECX,EDX)
+                MOVrd(ESI,ECX)
+                ADDib(ECX,sizeof(SHORT))
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVid(EAX,0)  
+                MOVobw(AX, EBX, ESI)
+                SWAP_AX()
+
+                break;
+
+            case BPF_LD|BPF_B|BPF_IND:
+
+                MOVid(ECX,ins->k)
+                ADDrd(ECX,EDX)
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVid(EAX,0)  
+                MOVobb(AL,EBX,ECX)
+
+                break;
+
+            case BPF_LDX|BPF_MSH|BPF_B:
+
+                MOVid(ECX,ins->k)
+                CMPodd(ECX, EBP, 0x10)
+                JLEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVid(EDX,0)
+                MOVobb(DL,EBX,ECX)
+                ANDib(DL, 0xf)
+                SHLib(EDX, 2)
+                                
+                break;
+
+            case BPF_LD|BPF_IMM:
+
+                MOVid(EAX,ins->k)
+
+                break;
+
+            case BPF_LDX|BPF_IMM:
+            
+                MOVid(EDX,ins->k)
+
+                break;
+
+            case BPF_LD|BPF_MEM:
+
+                MOVid(ECX,(INT)mem)
+                MOVid(ESI,ins->k*4)
+                MOVobd(EAX, ECX, ESI)
+
+                break;
+
+            case BPF_LDX|BPF_MEM:
+
+                MOVid(ECX,(INT)mem)
+                MOVid(ESI,ins->k*4)
+                MOVobd(EDX, ECX, ESI)
+
+                break;
+
+            case BPF_ST:
+
+                // XXX: this command and the following could be optimized if the previous
+                // instruction was already of this type
+                MOVid(ECX,(INT)mem)
+                MOVid(ESI,ins->k*4)
+                MOVomd(ECX, ESI, EAX)
+
+                break;
+
+            case BPF_STX:
+
+                MOVid(ECX,(INT)mem)
+                MOVid(ESI,ins->k*4)
+                MOVomd(ECX, ESI, EDX)
+                break;
+
+            case BPF_JMP|BPF_JA:
+
+                JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
+
+                break;
+
+            case BPF_JMP|BPF_JGT|BPF_K:
+
+                CMPid(EAX, ins->k)
+                JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+                break;
+
+            case BPF_JMP|BPF_JGE|BPF_K:
+
+                CMPid(EAX, ins->k)
+                JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+
+                break;
+
+            case BPF_JMP|BPF_JEQ|BPF_K:
+
+                CMPid(EAX, ins->k)
+                JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+
+                break;
+
+            case BPF_JMP|BPF_JSET|BPF_K:
+
+                MOVrd(ECX,EAX)
+                ANDid(ECX,ins->k)
+                JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])              
+
+                break;
+
+            case BPF_JMP|BPF_JGT|BPF_X:
+
+                CMPrd(EAX, EDX)
+                JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+                break;
+
+            case BPF_JMP|BPF_JGE|BPF_X:
+
+                CMPrd(EAX, EDX)
+                JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+
+                break;
+
+            case BPF_JMP|BPF_JEQ|BPF_X:
+
+                CMPrd(EAX, EDX)
+                JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])              
+
+                break;
+
+            case BPF_JMP|BPF_JSET|BPF_X:
+
+                MOVrd(ECX,EAX)
+                ANDrd(ECX,EDX)
+                JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+                JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])              
+                
+                break;
+
+            case BPF_ALU|BPF_ADD|BPF_X:
+
+                ADDrd(EAX,EDX)
+                
+                break;
+
+            case BPF_ALU|BPF_SUB|BPF_X:
+
+                SUBrd(EAX,EDX)
+
+                break;
+
+            case BPF_ALU|BPF_MUL|BPF_X:
+
+                MOVrd(ECX,EDX)
+                MULrd(EDX)
+                MOVrd(EDX,ECX)
+                break;
+
+            case BPF_ALU|BPF_DIV|BPF_X:
+
+                CMPid(EDX, 0)
+                JNEb(12)
+                POP(EDI)
+                POP(ESI)
+                POP(EDX)
+                POP(ECX)
+                POP(EBX)
+                POP(EBP)
+                MOVid(EAX,0)  
+                RET()
+                MOVrd(ECX,EDX)
+                MOVid(EDX,0)  
+                DIVrd(ECX)
+                MOVrd(EDX,ECX)
+
+                break;
+
+            case BPF_ALU|BPF_AND|BPF_X:
+
+                ANDrd(EAX,EDX)
+                
+                break;
+
+            case BPF_ALU|BPF_OR|BPF_X:
+
+                ORrd(EAX,EDX)
+
+                break;
+
+            case BPF_ALU|BPF_LSH|BPF_X:
+
+                MOVrd(ECX,EDX)
+                SHL_CLrb(EAX)
+
+                break;
+
+            case BPF_ALU|BPF_RSH|BPF_X:
+
+                MOVrd(ECX,EDX)
+                SHR_CLrb(EAX)
+
+                break;
+
+            case BPF_ALU|BPF_ADD|BPF_K:
+
+                ADD_EAXi(ins->k)
+
+                break;
+
+            case BPF_ALU|BPF_SUB|BPF_K:
+
+                SUB_EAXi(ins->k)
+                
+                break;
+
+            case BPF_ALU|BPF_MUL|BPF_K:
+
+                MOVrd(ECX,EDX)
+                MOVid(EDX,ins->k)  
+                MULrd(EDX)
+                MOVrd(EDX,ECX)
+
+                break;
+
+            case BPF_ALU|BPF_DIV|BPF_K:
+
+                MOVrd(ECX,EDX)
+                MOVid(EDX,0)  
+                MOVid(ESI,ins->k)
+                DIVrd(ESI)
+                MOVrd(EDX,ECX)
+
+                break;
+
+            case BPF_ALU|BPF_AND|BPF_K:
+
+                ANDid(EAX, ins->k)
+
+                break;
+
+            case BPF_ALU|BPF_OR|BPF_K:
+
+                ORid(EAX, ins->k)
+                
+                break;
+
+            case BPF_ALU|BPF_LSH|BPF_K:
+
+                SHLib(EAX, (ins->k) & 255)
+
+                break;
+
+            case BPF_ALU|BPF_RSH|BPF_K:
+
+                SHRib(EAX, (ins->k) & 255)
+
+                break;
+
+            case BPF_ALU|BPF_NEG:
+
+                NEGd(EAX)
+
+                break;
+
+            case BPF_MISC|BPF_TAX:
+
+                MOVrd(EDX,EAX)
+
+                break;
+
+            case BPF_MISC|BPF_TXA:
+
+                MOVrd(EAX,EDX)
+
+                break;
+
+
+
+            }
+        
+            ins++;  
+        }
+
+        pass++;
+        if(pass == 2) break;
+        
+#ifdef NTKERNEL
+#define NPF_TAG_STREAMBUF  TAG('1', 'J', 'W', 'A')
+        stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, NPF_TAG_STREAMBUF);
+#else
+        stream.ibuf=(CHAR*)malloc(stream.cur_ip);
+#endif
+        if(stream.ibuf==NULL) 
+        {
+#ifdef NTKERNEL
+            ExFreePool(stream.refs);
+#else
+            free(stream.refs);
+#endif
+            return NULL;
+        }
+        
+        // modify the reference table to contain the offsets and not the lengths of the instructions
+        for(i=1; i< nins + 1; i++)
+            stream.refs[i]+=stream.refs[i-1];
+
+        // Reset the counters
+        stream.cur_ip=0;
+        stream.bpf_pc=0;
+        // the second pass creates the actual code
+        emitm=emit_code;
+
+    }
+
+    // the reference table is needed only during compilation, now we can free it
+#ifdef NTKERNEL
+    ExFreePool(stream.refs);
+#else
+    free(stream.refs);
+#endif
+    return (BPF_filter_function)stream.ibuf;
+
+}
+
+
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
+{
+    JIT_BPF_Filter *Filter;
+
+
+    // Allocate the filter structure
+#ifdef NTKERNEL
+#define NPF_TAG_FILTSTRUCT  TAG('2', 'J', 'W', 'A')
+    Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), NPF_TAG_FILTSTRUCT);
+#else
+    Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
+#endif
+    if(Filter==NULL)
+    {
+        return NULL;
+    }
+
+    // Allocate the filter's memory
+#ifdef NTKERNEL
+#define NPF_TAG_FILTMEM  TAG('3', 'J', 'W', 'A')
+    Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), NPF_TAG_FILTMEM);
+#else
+    Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
+#endif
+    if(Filter->mem==NULL)
+    {
+#ifdef NTKERNEL
+        ExFreePool(Filter);
+#else
+        free(Filter);
+#endif
+        return NULL;
+    }
+
+    // Create the binary
+    if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
+    {
+#ifdef NTKERNEL
+        ExFreePool(Filter->mem);
+        ExFreePool(Filter);
+#else
+        free(Filter->mem);
+        free(Filter);
+
+        return NULL;
+#endif
+    }
+
+    return Filter;
+
+}
+
+//////////////////////////////////////////////////////////////
+
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
+    
+#ifdef NTKERNEL
+    ExFreePool(Filter->mem);
+    ExFreePool(Filter->Function);
+    ExFreePool(Filter);
+#else
+    free(Filter->mem);
+    free(Filter->Function);
+    free(Filter);
+#endif
+
+}
diff --git a/drivers/net/npf/jitter.h b/drivers/net/npf/jitter.h
new file mode 100644 (file)
index 0000000..de4e609
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2002
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions 
+ *  @{
+ */
+
+//
+// Registers
+//
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+
+#define AX 0
+#define CX 1
+#define DX 2
+#define BX 3
+#define SP 4
+#define BP 5
+#define SI 6
+#define DI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+
+/*! \brief A stream of X86 binary code.*/
+typedef struct binary_stream{
+    INT cur_ip;     ///< Current X86 instruction pointer.
+    INT bpf_pc;     ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
+    PCHAR ibuf;     ///< Instruction buffer, contains the X86 generated code.
+    PUINT refs;     ///< Jumps reference table.
+}binary_stream;
+
+
+/*! \brief Prototype of a filtering function created by the jitter. 
+
+  The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
+  is not among the parameters, because it is hardwired in the function.
+*/
+typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
+
+/*! \brief Prototype of the emit functions.
+
+  Different emit functions are used to create the reference table and to generate the actual filtering code.
+  This allows to have simpler instruction macros.
+  The first parameter is the stream that will receive the data. The secon one is a variable containing
+  the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
+  or a work at a time.
+*/
+typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
+
+/*! \brief Structure describing a x86 filtering program created by the jitter.*/
+typedef struct JIT_BPF_Filter{
+    BPF_filter_function Function;   ///< The x86 filtering binary, in the form of a BPF_filter_function.
+    PINT mem;
+}
+JIT_BPF_Filter;
+
+
+
+
+/**************************/
+/* X86 INSTRUCTION MACROS */
+/**************************/
+
+/// mov r32,i32
+#define MOVid(r32, i32) \
+  emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
+
+/// mov dr32,sr32
+#define MOVrd(dr32, sr32) \
+  emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream,  3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// mov dr32,sr32[off]
+#define MOVodd(dr32, sr32, off) \
+  emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+  emitm(&stream,  1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+  emitm(&stream,  off, 1);
+
+/// mov dr32,sr32[or32]
+#define MOVobd(dr32, sr32, or32) \
+  emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+  emitm(&stream,  (dr32 & 0x7) << 3 | 4 , 1);\
+  emitm(&stream,  (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr16,sr32[or32]
+#define MOVobw(dr32, sr32, or32) \
+  emitm(&stream, 0x66, 1); \
+  emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+  emitm(&stream,  (dr32 & 0x7) << 3 | 4 , 1);\
+  emitm(&stream,  (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr8,sr32[or32]
+#define MOVobb(dr8, sr32, or32) \
+  emitm(&stream, 0x8a, 1); \
+  emitm(&stream,  (dr8 & 0x7) << 3 | 4 , 1);\
+  emitm(&stream,  (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov [dr32][or32],sr32
+#define MOVomd(dr32, or32, sr32) \
+  emitm(&stream, 0x89, 1); \
+  emitm(&stream,  (sr32 & 0x7) << 3 | 4 , 1);\
+  emitm(&stream,  (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
+
+/// bswap dr32
+#define BSWAP(dr32) \
+  emitm(&stream, 0xf, 1); \
+  emitm(&stream,  0x19 << 3 | dr32 , 1);
+
+/// xchg al,ah
+#define SWAP_AX() \
+  emitm(&stream, 0x86, 1); \
+  emitm(&stream,  0xc4 , 1);
+
+/// push r32
+#define PUSH(r32) \
+  emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
+
+/// pop r32
+#define POP(r32) \
+  emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
+
+/// ret
+#define RET() \
+  emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
+
+/// add dr32,sr32
+#define ADDrd(dr32, sr32) \
+  emitm(&stream, 0x03, 1);\
+  emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// add eax,i32
+#define ADD_EAXi(i32) \
+  emitm(&stream, 0x05, 1);\
+  emitm(&stream, i32, 4);
+
+/// add r32,i32
+#define ADDid(r32, i32) \
+  emitm(&stream, 0x81, 1);\
+  emitm(&stream, 24 << 3 | r32, 1);\
+  emitm(&stream, i32, 4);
+
+/// add r32,i8
+#define ADDib(r32, i8) \
+  emitm(&stream, 0x83, 1);\
+  emitm(&stream, 24 << 3 | r32, 1);\
+  emitm(&stream, i8, 1);
+
+/// sub dr32,sr32
+#define SUBrd(dr32, sr32) \
+  emitm(&stream, 0x2b, 1);\
+  emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// sub eax,i32
+#define SUB_EAXi(i32) \
+  emitm(&stream, 0x2d, 1);\
+  emitm(&stream, i32, 4);
+
+/// mul r32
+#define MULrd(r32) \
+  emitm(&stream, 0xf7, 1);\
+  emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
+
+/// div r32
+#define DIVrd(r32) \
+  emitm(&stream, 0xf7, 1);\
+  emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
+
+/// and r8,i8
+#define ANDib(r8, i8) \
+  emitm(&stream, 0x80, 1);\
+  emitm(&stream, 7 << 5 | r8, 1);\
+  emitm(&stream, i8, 1);
+
+/// and r32,i32
+#define ANDid(r32, i32) \
+  if (r32 == EAX){ \
+  emitm(&stream, 0x25, 1);\
+  emitm(&stream, i32, 4);}\
+  else{ \
+  emitm(&stream, 0x81, 1);\
+  emitm(&stream, 7 << 5 | r32, 1);\
+  emitm(&stream, i32, 4);}
+
+/// and dr32,sr32
+#define ANDrd(dr32, sr32) \
+  emitm(&stream, 0x23, 1);\
+  emitm(&stream,  3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or dr32,sr32
+#define ORrd(dr32, sr32) \
+  emitm(&stream, 0x0b, 1);\
+  emitm(&stream,  3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or r32,i32
+#define ORid(r32, i32) \
+  if (r32 == EAX){ \
+  emitm(&stream, 0x0d, 1);\
+  emitm(&stream, i32, 4);}\
+  else{ \
+  emitm(&stream, 0x81, 1);\
+  emitm(&stream, 25 << 3 | r32, 1);\
+  emitm(&stream, i32, 4);}
+
+/// shl r32,i8
+#define SHLib(r32, i8) \
+  emitm(&stream, 0xc1, 1);\
+  emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
+  emitm(&stream, i8, 1);
+
+/// shl dr32,cl
+#define SHL_CLrb(dr32) \
+  emitm(&stream, 0xd3, 1);\
+  emitm(&stream,  7 << 5 | dr32 & 0x7, 1);
+
+/// shr r32,i8
+#define SHRib(r32, i8) \
+  emitm(&stream, 0xc1, 1);\
+  emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
+  emitm(&stream, i8, 1);
+
+/// shr dr32,cl
+#define SHR_CLrb(dr32) \
+  emitm(&stream, 0xd3, 1);\
+  emitm(&stream,  29 << 3 | dr32 & 0x7, 1);
+
+/// neg r32
+#define NEGd(r32) \
+  emitm(&stream, 0xf7, 1);\
+  emitm(&stream,  27 << 3 | r32 & 0x7, 1);
+
+/// cmp dr32,sr32[off]
+#define CMPodd(dr32, sr32, off) \
+  emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
+  emitm(&stream,  1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+  emitm(&stream,  off, 1);
+
+/// cmp dr32,sr32
+#define CMPrd(dr32, sr32) \
+  emitm(&stream, 0x3b, 1); \
+  emitm(&stream,  3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// cmp dr32,i32
+#define CMPid(dr32, i32) \
+  if (dr32 == EAX){ \
+  emitm(&stream, 0x3d, 1); \
+  emitm(&stream,  i32, 4);} \
+  else{ \
+  emitm(&stream, 0x81, 1); \
+  emitm(&stream,  0x1f << 3 | (dr32 & 0x7), 1);\
+  emitm(&stream,  i32, 4);}
+
+/// jne off32
+#define JNEb(off8) \
+   emitm(&stream, 0x75, 1);\
+   emitm(&stream, off8, 1);
+
+/// je off32
+#define JE(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x84, 1);\
+   emitm(&stream, off32, 4);
+
+/// jle off32
+#define JLE(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x8e, 1);\
+   emitm(&stream, off32, 4);
+
+/// jle off8
+#define JLEb(off8) \
+   emitm(&stream, 0x7e, 1);\
+   emitm(&stream, off8, 1);
+
+/// ja off32
+#define JA(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x87, 1);\
+   emitm(&stream, off32, 4);
+   
+/// jae off32
+#define JAE(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x83, 1);\
+   emitm(&stream, off32, 4);
+
+/// jg off32
+#define JG(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x8f, 1);\
+   emitm(&stream, off32, 4);
+
+/// jge off32
+#define JGE(off32) \
+   emitm(&stream, 0x0f, 1);\
+   emitm(&stream, 0x8d, 1);\
+   emitm(&stream, off32, 4);
+
+/// jmp off32
+#define JMP(off32) \
+   emitm(&stream, 0xe9, 1);\
+   emitm(&stream, off32, 4);
+
+/**
+ *  @}
+ */
+
+/**
+ *  @}
+ */
+
+/**************************/
+/* Prototypes             */
+/**************************/
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_code NPF functions 
+ *  @{
+ */
+
+/*!
+  \brief BPF jitter, builds an x86 function from a BPF program.
+  \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
+  \param nins Number of instructions of the input filter.
+  \return The JIT_BPF_Filter structure containing the x86 filtering binary.
+
+  BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
+  calling BPFtoX86().
+*/ 
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
+
+/*!
+  \brief Translates a set of BPF instructions in a set of x86 ones.
+  \param ins Pointer to the BPF instructions that will be translated into x86 code.
+  \param nins Number of instructions to translate.
+  \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
+  \return The x86 filtering function.
+
+  This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and 
+  through the instruction macros defined in jitter.h it is able to create an function directly executable
+  by NPF.
+*/ 
+BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
+/*!
+  \brief Deletes a filtering function that was previously created by BPF_jitter().
+  \param Filter The filter to destroy.
+
+  This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
+*/ 
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
+
+/**
+ *  @}
+ */
+
+/**
+ *  @}
+ */
diff --git a/drivers/net/npf/memory_t.c b/drivers/net/npf/memory_t.c
new file mode 100644 (file)
index 0000000..361082c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "memory_t.h"
+
+#ifdef _USE_SW_FUNCS_
+
+int32 SW_LONG_AT(void *b, uint32 c)
+{
+       return  ((int32)*((uint8 *)b+c)<<24|
+                (int32)*((uint8 *)b+c+1)<<16|
+                (int32)*((uint8 *)b+c+2)<<8|
+                (int32)*((uint8 *)b+c+3)<<0);
+}
+
+uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+       return  ((uint32)*((uint8 *)b+c)<<24|
+                (uint32)*((uint8 *)b+c+1)<<16|
+                (uint32)*((uint8 *)b+c+2)<<8|
+                (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+int16 SW_SHORT_AT(void *b, uint32 os)
+{
+       return ((int16)
+               ((int16)*((uint8 *)b+os+0)<<8|
+                (int16)*((uint8 *)b+os+1)<<0));
+}
+
+uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+       return ((uint16)
+               ((uint16)*((uint8 *)b+os+0)<<8|
+                (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+       *((uint8*)dst+0)=*((uint8*)&src+3);
+       *((uint8*)dst+1)=*((uint8*)&src+2);
+       *((uint8*)dst+2)=*((uint8*)&src+1);
+       *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#endif /*_USE_SW_FUNCS_*/
+
+void assert(void* assert, const char* file, int line, void* msg) { };
diff --git a/drivers/net/npf/memory_t.h b/drivers/net/npf/memory_t.h
new file mode 100644 (file)
index 0000000..57f24e7
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define     uint8   UCHAR
+#define     int8    CHAR
+#define     uint16  USHORT
+#define     int16   SHORT
+#define     uint32  ULONG
+#define     int32   LONG
+#define     uint64  ULONGLONG
+#define     int64   LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+    uint8 *buffer;
+    uint32 size;
+}  MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+#ifdef __GNUC__
+#define __inline inline
+#define _USE_SW_FUNCS_
+#endif
+
+#ifdef _USE_SW_FUNCS_
+
+inline int32 SW_LONG_AT(void *b, uint32 c);
+inline uint32 SW_ULONG_AT(void *b, uint32 c);
+inline int16 SW_SHORT_AT(void *b, uint32 os);
+inline uint16 SW_USHORT_AT(void *b, uint32 os);
+inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
+
+#else /*_USE_SW_FUNCS_*/
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+    return  ((int32)*((uint8 *)b+c)<<24|
+         (int32)*((uint8 *)b+c+1)<<16|
+         (int32)*((uint8 *)b+c+2)<<8|
+         (int32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+    return  ((uint32)*((uint8 *)b+c)<<24|
+         (uint32)*((uint8 *)b+c+1)<<16|
+         (uint32)*((uint8 *)b+c+2)<<8|
+         (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+    return ((int16)
+        ((int16)*((uint8 *)b+os+0)<<8|
+         (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+    return ((uint16)
+        ((uint16)*((uint8 *)b+os+0)<<8|
+         (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+    *((uint8*)dst+0)=*((uint8*)&src+3);
+    *((uint8*)dst+1)=*((uint8*)&src+2);
+    *((uint8*)dst+2)=*((uint8*)&src+1);
+    *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#endif /*_USE_SW_FUNCS_*/
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+      (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+    { \
+        (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
+        if ((dest)!=NULL) \
+            RtlZeroMemory((dest),sizeof(type)*(amount)); \
+    }   
+
+#define FREE_MEMORY(dest) ExFreePool(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif 
+
diff --git a/drivers/net/npf/normal_lookup.c b/drivers/net/npf/normal_lookup.c
new file mode 100644 (file)
index 0000000..ea6442f
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/normal_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/normal_lookup.h>
+#endif
+
+#endif
+
+
+/* lookup in the table, seen as an hash               */
+/* if not found, inserts an element                   */
+/* returns TME_TRUE if the entry is found or created, */
+/* returns TME_FALSE if no more blocks are available  */
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) 
+{
+       uint32 i;
+       uint32 tocs=0;
+       uint32 *key32=(uint32*) key;
+       uint32 shrinked_key=0;
+       uint32 index;
+       RECORD *records=(RECORD*)data->lut_base_address;
+       uint8 *offset;
+       uint32 key_len=data->key_len;
+       /*the key is shrinked into a 32-bit value */    
+       for (i=0; i<key_len;i++) 
+               shrinked_key^=key32[i];
+    /*the first index in the table is calculated*/
+       index=shrinked_key % data->lut_entries;
+
+       while (tocs<=data->filled_entries)
+       {       
+
+               if (records[index].block==0)
+               {   /*creation of a new entry*/
+
+                       if (data->filled_blocks==data->shared_memory_blocks)
+                       {
+                               /*no more free blocks*/
+                               GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+                               data->last_found=NULL;  
+                               return TME_FALSE;
+                       }
+
+                       /*offset=absolute pointer to the block associated*/
+                       /*with the newly created entry*/
+                       offset=data->shared_memory_base_address+
+                       data->block_size*data->filled_blocks;
+                       
+                       /*copy the key in the block*/
+                       COPY_MEMORY(offset,key32,key_len*4);
+                       GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+                       /*assign the block relative offset to the entry, in NBO*/
+                       SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
+
+                       data->filled_blocks++;
+                       
+                       /*assign the exec function ID to the entry, in NBO*/
+                       SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+                       data->filled_entries++;
+
+                       data->last_found=(uint8*)&records[index];
+                       
+                       return TME_TRUE;        
+               }
+               /*offset contains the absolute pointer to the block*/
+               /*associated with the current entry */
+               offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);             
+
+               for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+               
+               if (i==key_len)
+                       {
+                               /*key in the block matches the one provided, right entry*/
+                               GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+                               data->last_found=(uint8*)&records[index];
+                               return TME_TRUE;
+                       }
+               else 
+               {
+                       /* wrong entry, rehashing */
+                       if (IS_DELETABLE(offset+key_len*4,data))
+                       {
+                               ZERO_MEMORY(offset,data->block_size);
+                               COPY_MEMORY(offset,key32,key_len*4);
+                               SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+                               GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
+                               data->last_found=(uint8*)&records[index];
+                               return TME_TRUE;        
+                       }
+                       else
+                       {
+                               index=(index+data->rehashing_value) % data->lut_entries;
+                               tocs++;
+                       }
+               }
+       }
+
+       /* nothing found, last found= out of lut */
+       GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+       data->last_found=NULL;
+       return TME_FALSE;
+
+}
+
+/* lookup in the table, seen as an hash           */
+/* if not found, returns out of count entry index */
+/* returns TME_TRUE if the entry is found         */
+/* returns TME_FALSE if the entry is not found    */
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) 
+{
+       uint32 i;
+       uint32 tocs=0;
+       uint32 *key32=(uint32*) key;
+       uint32 shrinked_key=0;
+       uint32 index;
+       RECORD *records=(RECORD*)data->lut_base_address;
+       uint8 *offset;
+       uint32 key_len=data->key_len;
+       /*the key is shrinked into a 32-bit value */    
+       for (i=0; i<key_len;i++) 
+               shrinked_key^=key32[i];
+    /*the first index in the table is calculated*/
+       index=shrinked_key % data->lut_entries;
+
+       while (tocs<=data->filled_entries)
+       {       
+
+               if (records[index].block==0)
+               {   /*out of table, insertion is not allowed*/
+                       GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+                       data->last_found=NULL;  
+                       return TME_FALSE;
+               }
+               /*offset contains the absolute pointer to the block*/
+               /*associated with the current entry */
+               
+               offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);             
+
+               for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+               
+               if (i==key_len)
+                       {
+                               /*key in the block matches the one provided, right entry*/
+                               GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+                               data->last_found=(uint8*)&records[index];
+                               return TME_TRUE;
+                       }
+               else 
+               {
+                       /*wrong entry, rehashing*/
+                       index=(index+data->rehashing_value) % data->lut_entries;
+                       tocs++;
+               }
+       }
+
+       /*nothing found, last found= out of lut*/
+       GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+       data->last_found=NULL;
+       return TME_FALSE;
+
+}
diff --git a/drivers/net/npf/normal_lookup.h b/drivers/net/npf/normal_lookup.h
new file mode 100644 (file)
index 0000000..69e21ce
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define NORMAL_LUT_W_INSERT             0x00000000
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);   
+#define NORMAL_LUT_WO_INSERT            0x00000001
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref); 
+#define DUMMY_INSERT                    1234
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/npf.def b/drivers/net/npf/npf.def
new file mode 100644 (file)
index 0000000..3517ee3
--- /dev/null
@@ -0,0 +1,8 @@
+; packet capture driver - ReactOS Operating System
+
+LIBRARY PACKET.SYS
+
+EXPORTS
+DriverEntry@8
+
+; EOF
diff --git a/drivers/net/npf/npf.edf b/drivers/net/npf/npf.edf
new file mode 100644 (file)
index 0000000..11994e4
--- /dev/null
@@ -0,0 +1,8 @@
+; PACKET.SYS - PACKET protocol driver
+
+LIBRARY packet.sys
+
+EXPORTS
+DriverEntry=DriverEntry@8
+
+; EOF
diff --git a/drivers/net/npf/npf.rc b/drivers/net/npf/npf.rc
new file mode 100644 (file)
index 0000000..47f2b3d
--- /dev/null
@@ -0,0 +1,47 @@
+//#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,0,0,13
+ PRODUCTVERSION 3,0,0,13
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x3L
+ FILESUBTYPE 0x7L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "Comments", "Netgroup Packet Filter Driver\0"
+            VALUE "CompanyName", "Politecnico di Torino\0"
+            VALUE "FileDescription", "NPF Driver - TME extensions\0"
+            VALUE "FileVersion", "3, 0, 0, 13\0"
+            VALUE "InternalName", "NPF + TME \0"
+            VALUE "LegalCopyright", "Copyright Â© 2002\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "NPF.RC\0"
+            VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
+            VALUE "ProductName", "NPF Driver\0"
+            VALUE "ProductVersion", "3, 0, 0, 13\0"
+            VALUE "SpecialBuild", "Beta testing use only\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+
+
diff --git a/drivers/net/npf/ntddpack.h b/drivers/net/npf/ntddpack.h
new file mode 100644 (file)
index 0000000..a855138
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+
+#ifdef _MSC_VER
+#include "devioctl.h"
+/*#include <packon.h> */
+#else
+#endif
+
+struct _PACKET_OID_DATA {
+    ULONG Oid;
+    ULONG Length;
+    UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL        0x8000
+#define IOCTL_PROTOCOL_QUERY_OID    CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID      CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS   CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET        CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ         CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE        CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME      CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN                  CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE                 CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/drivers/net/npf/openclos.c b/drivers/net/npf/openclos.c
new file mode 100644 (file)
index 0000000..bdb5b1a
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+#include "debug.h"
+#include "packet.h"
+
+static NDIS_MEDIUM MediumArray[] = {
+       NdisMedium802_3,
+       NdisMediumWan,
+       NdisMediumFddi,
+       NdisMediumArcnet878_2,
+       NdisMediumAtm,
+       NdisMedium802_5
+};
+
+#define NUM_NDIS_MEDIA  (sizeof MediumArray / sizeof MediumArray[0])
+
+ULONG NamedEventsCounter=0;
+
+//Itoa. Replaces the buggy RtlIntegerToUnicodeString
+void PacketItoa(UINT n,PUCHAR buf){
+int i;
+
+       for(i=0;i<20;i+=2){
+               buf[18-i]=(n%10)+48;
+               buf[19-i]=0;
+               n/=10;
+       }
+
+}
+
+/// Global start time. Used as an absolute reference for timestamp conversion.
+struct time_conv G_Start_Time = {
+       0,      
+       {0, 0}, 
+};
+
+UINT n_Opened_Instances = 0;
+
+NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+
+    PDEVICE_EXTENSION DeviceExtension;
+
+    POPEN_INSTANCE    Open;
+
+    PIO_STACK_LOCATION  IrpSp;
+
+    NDIS_STATUS     Status;
+    NDIS_STATUS     ErrorStatus;
+    UINT            i;
+       PUCHAR                  tpointer;
+    PLIST_ENTRY     PacketListEntry;
+       PCHAR                   EvName;
+
+    IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
+
+    DeviceExtension = DeviceObject->DeviceExtension;
+
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    //  allocate some memory for the open structure
+#define NPF_TAG_OPENSTRUCT  TAG('0', 'O', 'W', 'A')
+    Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), NPF_TAG_OPENSTRUCT);
+
+
+    if (Open==NULL) {
+        // no memory
+        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlZeroMemory(
+        Open,
+        sizeof(OPEN_INSTANCE)
+        );
+
+
+#define NPF_TAG_EVNAME  TAG('1', 'O', 'W', 'A')
+       EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), NPF_TAG_EVNAME);
+
+    if (EvName==NULL) {
+        // no memory
+        ExFreePool(Open);
+           Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //  Save or open here
+    IrpSp->FileObject->FsContext=Open;
+       
+    Open->DeviceExtension=DeviceExtension;
+       
+       
+    //  Save the Irp here for the completeion routine to retrieve
+    Open->OpenCloseIrp=Irp;
+       
+    //  Allocate a packet pool for our xmit and receive packets
+    NdisAllocatePacketPool(
+        &Status,
+        &Open->PacketPool,
+        TRANSMIT_PACKETS,
+        sizeof(PACKET_RESERVED));
+       
+       
+    if (Status != NDIS_STATUS_SUCCESS) {
+               
+        IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
+                       
+               ExFreePool(Open);
+               ExFreePool(EvName);
+        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+
+       RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
+
+       //Create the string containing the name of the read event
+       RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
+
+       PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
+
+       InterlockedIncrement(&NamedEventsCounter);
+       
+       IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
+
+       //allocate the event objects
+       Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
+       if(Open->ReadEvent==NULL){
+               ExFreePool(Open);
+               ExFreePool(EvName);
+        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
+       }
+       
+       KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
+       KeClearEvent(Open->ReadEvent);
+       NdisInitializeEvent(&Open->WriteEvent);
+       NdisInitializeEvent(&Open->IOEvent);
+       NdisInitializeEvent(&Open->DumpEvent);
+       NdisInitializeEvent(&Open->IOEvent);
+       NdisAllocateSpinLock(&Open->machine_lock);
+
+
+    //  list to hold irp's want to reset the adapter
+    InitializeListHead(&Open->ResetIrpList);
+       
+       
+    //  Initialize the request list
+    KeInitializeSpinLock(&Open->RequestSpinLock);
+    InitializeListHead(&Open->RequestList);
+
+       // Initializes the extended memory of the NPF machine
+#define NPF_TAG_MACHINE  TAG('2', 'O', 'W', 'A')
+       Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, NPF_TAG_MACHINE);
+       if((Open->mem_ex.buffer) == NULL)
+       {
+        // no memory
+        ExFreePool(Open);
+               ExFreePool(EvName);
+           Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+       
+       Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
+       RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
+       
+       //
+       // Initialize the open instance
+       //
+       Open->BufSize = 0;
+       Open->Buffer = NULL;
+       Open->Bhead = 0;
+       Open->Btail = 0;
+       (INT)Open->BLastByte = -1;
+       Open->Dropped = 0;              //reset the dropped packets counter
+       Open->Received = 0;             //reset the received packets counter
+       Open->Accepted = 0;             //reset the accepted packets counter
+       Open->bpfprogram = NULL;        //reset the filter
+       Open->mode = MODE_CAPT;
+       Open->Nbytes.QuadPart = 0;
+       Open->Npackets.QuadPart = 0;
+       Open->Nwrites = 1;
+       Open->Multiple_Write_Counter = 0;
+       Open->MinToCopy = 0;
+       Open->TimeOut.QuadPart = (LONGLONG)1;
+       Open->Bound = TRUE;
+       Open->DumpFileName.Buffer = NULL;
+       Open->DumpFileHandle = NULL;
+       Open->tme.active = TME_NONE_ACTIVE;
+       Open->DumpLimitReached = FALSE;
+       Open->MaxFrameSize = 0;
+
+       //allocate the spinlock for the statistic counters
+    NdisAllocateSpinLock(&Open->CountersLock);
+
+       //allocate the spinlock for the buffer pointers
+    NdisAllocateSpinLock(&Open->BufLock);
+       
+    //
+    //  link up the request stored in our open block
+    //
+    for (i=0;i<MAX_REQUESTS;i++) {
+        ExInterlockedInsertTailList(
+            &Open->RequestList,
+            &Open->Requests[i].ListElement,
+            &Open->RequestSpinLock);
+               
+    }
+       
+
+    IoMarkIrpPending(Irp);
+       
+    //
+    //  Try to open the MAC
+    //
+    IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
+
+       NdisOpenAdapter(
+        &Status,
+        &ErrorStatus,
+        &Open->AdapterHandle,
+        &Open->Medium,
+        MediumArray,
+        NUM_NDIS_MEDIA,
+        DeviceExtension->NdisProtocolHandle,
+        Open,
+        &DeviceExtension->AdapterName,
+        0,
+        NULL);
+
+    IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
+
+       if (Status != NDIS_STATUS_PENDING)
+    {
+               NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
+    }
+       
+    return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_OpenAdapterComplete(
+       IN NDIS_HANDLE  ProtocolBindingContext,
+    IN NDIS_STATUS  Status,
+    IN NDIS_STATUS  OpenErrorStatus)
+{
+
+    PIRP                Irp;
+    POPEN_INSTANCE      Open;
+    PLIST_ENTRY                        RequestListEntry;
+       PINTERNAL_REQUEST       MaxSizeReq;
+       NDIS_STATUS                     ReqStatus;
+
+
+    IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
+
+    Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+    //
+    //  get the open irp
+    //
+    Irp=Open->OpenCloseIrp;
+
+    if (Status != NDIS_STATUS_SUCCESS) {
+
+        IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
+
+        NdisFreePacketPool(Open->PacketPool);
+
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+               ExFreePool(Open->ReadEventName.Buffer);
+
+               ZwClose(Open->ReadEventHandle);
+
+
+        ExFreePool(Open);
+    }
+       else {
+               NdisAcquireSpinLock(&Opened_Instances_Lock);
+               n_Opened_Instances++;
+               NdisReleaseSpinLock(&Opened_Instances_Lock);
+               
+               IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+               // Get the absolute value of the system boot time.
+               // This is used for timestamp conversion.
+               TIME_SYNCHRONIZE(&G_Start_Time);
+
+               // Extract a request from the list of free ones
+               RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
+
+               if (RequestListEntry == NULL)
+               {
+
+                   Open->MaxFrameSize = 1514;  // Assume Ethernet
+
+                       Irp->IoStatus.Status = Status;
+                   Irp->IoStatus.Information = 0;
+                   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+                   return;
+               }
+
+               MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
+               MaxSizeReq->Irp = Irp;
+               MaxSizeReq->Internal = TRUE;
+
+               
+               MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
+               MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
+
+               
+               MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
+               MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
+
+               //  submit the request
+               NdisRequest(
+                       &ReqStatus,
+                       Open->AdapterHandle,
+                       &MaxSizeReq->Request);
+
+
+               if (ReqStatus != NDIS_STATUS_PENDING) {
+                       NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
+               }
+
+               return;
+
+       }
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+
+    POPEN_INSTANCE    Open;
+    NDIS_STATUS     Status;
+    PIO_STACK_LOCATION  IrpSp;
+       LARGE_INTEGER ThreadDelay;
+
+    IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
+
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    Open=IrpSp->FileObject->FsContext;
+
+       // Reset the buffer size. This tells the dump thread to stop.
+       Open->BufSize = 0;
+
+       if( Open->Bound == FALSE){
+
+               NdisWaitEvent(&Open->IOEvent,10000);
+
+               // Free the filter if it's present
+               if(Open->bpfprogram != NULL)
+                       ExFreePool(Open->bpfprogram);
+
+               // Free the jitted filter if it's present
+               if(Open->Filter != NULL)
+                       BPF_Destroy_JIT_Filter(Open->Filter);
+
+               //free the buffer
+               Open->BufSize=0;
+               if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
+               
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+                               
+               NdisFreePacketPool(Open->PacketPool);
+
+               // Free the string with the name of the dump file
+               if(Open->DumpFileName.Buffer!=NULL)
+                       ExFreePool(Open->DumpFileName.Buffer);
+                       
+               ExFreePool(Open->ReadEventName.Buffer);
+               ExFreePool(Open);
+
+               Irp->IoStatus.Information = 0;
+               Irp->IoStatus.Status = STATUS_SUCCESS;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+               
+               return(STATUS_SUCCESS);
+       }
+
+       // Unfreeze the consumer
+       if(Open->mode & MODE_DUMP)
+               NdisSetEvent(&Open->DumpEvent);
+       else
+               KeSetEvent(Open->ReadEvent,0,FALSE);
+
+    // Save the IRP
+    Open->OpenCloseIrp = Irp;
+
+    IoMarkIrpPending(Irp);
+       // If this instance is in dump mode, complete the dump and close the file
+       if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
+               NTSTATUS wres;
+
+               ThreadDelay.QuadPart = -50000000;
+               // Wait the completion of the thread
+               wres = KeWaitForSingleObject(Open->DumpThreadObject,
+                               UserRequest,
+                               KernelMode,
+                               TRUE,
+                               &ThreadDelay);
+
+               ObDereferenceObject(Open->DumpThreadObject);
+
+
+               // Flush and close the dump file
+               NPF_CloseDumpFile(Open);
+       }
+
+       // Destroy the read Event
+       ZwClose(Open->ReadEventHandle);
+
+       // Close the adapter
+       NdisCloseAdapter(
+               &Status,
+               Open->AdapterHandle
+               );
+
+       if (Status != NDIS_STATUS_PENDING) {
+               
+               NPF_CloseAdapterComplete(
+                       Open,
+                       Status
+                       );
+               return STATUS_SUCCESS;
+               
+       }
+       
+       return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_CloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
+{
+    POPEN_INSTANCE    Open;
+    PIRP              Irp;
+
+    IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
+
+    Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+       // free the allocated structures only if the instance is still bound to the adapter
+       if(Open->Bound == TRUE){
+               
+               // Free the filter if it's present
+               if(Open->bpfprogram != NULL)
+                       ExFreePool(Open->bpfprogram);
+
+               // Free the jitted filter if it's present
+               if(Open->Filter != NULL)
+                       BPF_Destroy_JIT_Filter(Open->Filter);
+               
+               //free the buffer
+               Open->BufSize = 0;
+               if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
+               
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+               
+               NdisFreePacketPool(Open->PacketPool);
+               
+               Irp=Open->OpenCloseIrp;
+               
+               // Free the string with the name of the dump file
+               if(Open->DumpFileName.Buffer!=NULL)
+                       ExFreePool(Open->DumpFileName.Buffer);
+
+               ExFreePool(Open->ReadEventName.Buffer);
+               ExFreePool(Open);
+               
+               // Complete the request only if the instance is still bound to the adapter
+               Irp->IoStatus.Status = STATUS_SUCCESS;
+               Irp->IoStatus.Information = 0;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+       }
+       else
+               NdisSetEvent(&Open->IOEvent);
+
+       // Decrease the counter of open instances
+       NdisAcquireSpinLock(&Opened_Instances_Lock);
+       n_Opened_Instances--;
+       NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+       IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+       if(n_Opened_Instances == 0){
+               // Force a synchronization at the next NPF_Open().
+               // This hopefully avoids the synchronization issues caused by hibernation or standby.
+               TIME_DESYNCHRONIZE(&G_Start_Time);
+       }
+
+       return;
+
+}
+//-------------------------------------------------------------------
+
+#ifdef NDIS50
+NDIS_STATUS
+NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
+{
+    IF_LOUD(DbgPrint("NPF: PowerChange\n");)
+
+       TIME_DESYNCHRONIZE(&G_Start_Time);
+
+       TIME_SYNCHRONIZE(&G_Start_Time);
+
+       return STATUS_SUCCESS;
+}
+#endif
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_BindAdapter(
+    OUT PNDIS_STATUS            Status,
+    IN  NDIS_HANDLE             BindContext,
+    IN  PNDIS_STRING            DeviceName,
+    IN  PVOID                   SystemSpecific1,
+    IN  PVOID                   SystemSpecific2
+    )
+{
+       IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_UnbindAdapter(
+    OUT PNDIS_STATUS        Status,
+    IN  NDIS_HANDLE         ProtocolBindingContext,
+    IN  NDIS_HANDLE         UnbindContext
+    )
+{
+    POPEN_INSTANCE   Open =(POPEN_INSTANCE)ProtocolBindingContext;
+       NDIS_STATUS              lStatus;
+
+       IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
+
+       // Reset the buffer size. This tells the dump thread to stop.
+       Open->BufSize=0;
+
+       NdisResetEvent(&Open->IOEvent);
+
+       // This open instance is no more bound to the adapter, set Bound to False
+    InterlockedExchange( (PLONG) &Open->Bound, FALSE );
+
+       // Awake a possible pending read on this instance
+       if(Open->mode & MODE_DUMP)
+               NdisSetEvent(&Open->DumpEvent);
+       else
+               KeSetEvent(Open->ReadEvent,0,FALSE);
+
+       // If this instance is in dump mode, complete the dump and close the file
+       if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
+               NPF_CloseDumpFile(Open);
+
+       // Destroy the read Event
+       ZwClose(Open->ReadEventHandle);
+
+    //  close the adapter
+    NdisCloseAdapter(
+        &lStatus,
+        Open->AdapterHandle
+           );
+
+    if (lStatus != NDIS_STATUS_PENDING) {
+
+        NPF_CloseAdapterComplete(
+            Open,
+            lStatus
+            );
+
+               *Status = NDIS_STATUS_SUCCESS;
+        return;
+
+    }
+
+       *Status = NDIS_STATUS_SUCCESS;
+    return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_ResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
+
+{
+    POPEN_INSTANCE      Open;
+    PIRP                Irp;
+
+    PLIST_ENTRY         ResetListEntry;
+
+    IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
+
+    Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+
+    //
+    //  remove the reset IRP from the list
+    //
+    ResetListEntry=ExInterlockedRemoveHeadList(
+                       &Open->ResetIrpList,
+                       &Open->RequestSpinLock
+                       );
+
+#if DBG
+    if (ResetListEntry == NULL) {
+        DbgBreakPoint();
+        return;
+    }
+#endif
+
+    Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
+
+    return;
+
+}
diff --git a/drivers/net/npf/packet.c b/drivers/net/npf/packet.c
new file mode 100644 (file)
index 0000000..17acc0b
--- /dev/null
@@ -0,0 +1,1388 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "ntddpack.h"
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "win_bpf_filter_init.h"
+
+#include "tme.h"
+
+#if DBG
+// Declare the global debug flag for this driver.
+//ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT;
+
+#endif
+
+PDEVICE_EXTENSION GlobalDeviceExtension;
+
+////////////////////////////////////////////////////////////////////////////////
+#define ROBERTS_PATCH
+#ifdef ROBERTS_PATCH
+
+#define NDIS_STRING_CONST(x)   {sizeof(L##x)-2, sizeof(L##x), L##x}
+
+//void __moddi3(void) {}
+//void __divdi3(void) {}
+
+#endif // ROBERTS_PATCH
+////////////////////////////////////////////////////////////////////////////////
+//
+// Global strings
+//
+NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
+NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
+NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
+NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+                                                               L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
+NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+                                                               L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
+
+
+/// Global variable that points to the names of the bound adapters
+WCHAR* bindP = NULL;
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+extern NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//
+//  Packet Driver's entry routine.
+//
+NTSTATUS
+#ifdef __GNUC__
+STDCALL
+#endif
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegistryPath
+    )
+{
+
+    NDIS_PROTOCOL_CHARACTERISTICS  ProtocolChar;
+    UNICODE_STRING MacDriverName;
+    UNICODE_STRING UnicodeDeviceName;
+    PDEVICE_OBJECT DeviceObject = NULL;
+    PDEVICE_EXTENSION DeviceExtension = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS ErrorCode = STATUS_SUCCESS;
+    NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
+    ULONG          DevicesCreated=0;
+    PWSTR          BindString;
+    PWSTR          ExportString;
+    PWSTR          BindStringSave;
+    PWSTR          ExportStringSave;
+    NDIS_HANDLE    NdisProtocolHandle;
+       WCHAR* bindT;
+       PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
+       UNICODE_STRING macName;
+       
+       // This driver at the moment works only on single processor machines
+       if(NdisSystemProcessorCount() != 1){
+               return STATUS_IMAGE_MP_UP_MISMATCH;
+       }
+
+    IF_LOUD(DbgPrint("Packet: DriverEntry\n");)
+
+       RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+#ifdef NDIS50
+    ProtocolChar.MajorNdisVersion            = 5;
+#else
+    ProtocolChar.MajorNdisVersion            = 3;
+#endif
+    ProtocolChar.MinorNdisVersion            = 0;
+#ifndef __GNUC__
+    ProtocolChar.Reserved                    = 0;
+#else
+    ProtocolChar.u1.Reserved                 = 0;
+#endif
+    ProtocolChar.OpenAdapterCompleteHandler  = NPF_OpenAdapterComplete;
+    ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+#ifndef __GNUC__
+    ProtocolChar.SendCompleteHandler         = NPF_SendComplete;
+    ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+#else
+    ProtocolChar.u2.SendCompleteHandler         = NPF_SendComplete;
+    ProtocolChar.u3.TransferDataCompleteHandler = NPF_TransferDataComplete;
+#endif
+    ProtocolChar.ResetCompleteHandler        = NPF_ResetComplete;
+    ProtocolChar.RequestCompleteHandler      = NPF_RequestComplete;
+#ifndef __GNUC__
+    ProtocolChar.ReceiveHandler              = NPF_tap;
+#else
+    ProtocolChar.u4.ReceiveHandler           = NPF_tap;
+#endif
+    ProtocolChar.ReceiveCompleteHandler      = NPF_ReceiveComplete;
+    ProtocolChar.StatusHandler               = NPF_Status;
+    ProtocolChar.StatusCompleteHandler       = NPF_StatusComplete;
+#ifdef NDIS50
+    ProtocolChar.BindAdapterHandler          = NPF_BindAdapter;
+    ProtocolChar.UnbindAdapterHandler        = NPF_UnbindAdapter;
+    ProtocolChar.PnPEventHandler             = NPF_PowerChange;
+    ProtocolChar.ReceivePacketHandler        = NULL;
+#endif
+    ProtocolChar.Name                        = ProtoName;
+
+    NdisRegisterProtocol(
+        &Status,
+        &NdisProtocolHandle,
+        &ProtocolChar,
+        sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+    if (Status != NDIS_STATUS_SUCCESS) {
+
+        IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
+
+        return Status;
+
+    }
+       
+    NdisAllocateSpinLock(&Opened_Instances_Lock);
+
+    // Set up the device driver entry points.
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = NPF_Close;
+    DriverObject->MajorFunction[IRP_MJ_READ]   = NPF_Read;
+    DriverObject->MajorFunction[IRP_MJ_WRITE]  = NPF_Write;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = NPF_IoControl;
+    DriverObject->DriverUnload = NPF_Unload;
+
+/*
+    //  Get the name of the Packet driver and the name of the NIC driver
+    //  to bind to from the registry
+    Status=NPF_ReadRegistry(
+               &BindString,
+               &ExportString,
+               RegistryPath
+               );
+
+    if (Status != STATUS_SUCCESS) {
+
+               IF_LOUD(DbgPrint("Trying dynamic binding\n");)  
+ */
+               bindP = getAdaptersList();
+
+               if (bindP == NULL) {
+                       IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
+
+                       tcpBindingsP = getTcpBindings();
+                       
+                       if (tcpBindingsP == NULL){
+                               IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
+                               goto RegistryError;
+                       }
+                       
+                       bindP = (WCHAR*)tcpBindingsP;
+                       bindT = (WCHAR*)(tcpBindingsP->Data);
+        } else {
+                       bindT = bindP;
+               }
+
+               for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) {
+                       RtlInitUnicodeString(&macName, bindT);
+                       createDevice(DriverObject, &macName, NdisProtocolHandle);
+               }
+
+               return STATUS_SUCCESS;
+/*
+    }
+    BindStringSave   = BindString;
+    ExportStringSave = ExportString;
+    //
+    //  create a device object for each entry
+    //
+    while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
+        //
+        //  Create a counted unicode string for both null terminated strings
+        //
+        RtlInitUnicodeString(
+            &MacDriverName,
+            BindString);
+        RtlInitUnicodeString(
+            &UnicodeDeviceName,
+            ExportString);
+        //
+        //  Advance to the next string of the MULTI_SZ string
+        //
+        BindString   += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
+        ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
+        IF_LOUD(DbgPrint("NPF: DeviceName=%ws  MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
+        //
+        //  Create the device object
+        //
+        Status = IoCreateDevice(
+                    DriverObject,
+                    sizeof(DEVICE_EXTENSION),
+                    &UnicodeDeviceName,
+                    FILE_DEVICE_PROTOCOL,
+                    0,
+                    FALSE,
+                    &DeviceObject);
+        if (Status != STATUS_SUCCESS) {
+            IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
+            break;
+        }
+        DevicesCreated++;
+        DeviceObject->Flags |= DO_DIRECT_IO;
+        DeviceExtension  =  (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+        DeviceExtension->DeviceObject = DeviceObject;
+        //
+        //  Save the the name of the MAC driver to open in the Device Extension
+        //
+        DeviceExtension->AdapterName=MacDriverName;
+        if (DevicesCreated == 1) {
+            DeviceExtension->BindString   = NULL;
+            DeviceExtension->ExportString = NULL;
+        }
+        DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
+    }
+    if (DevicesCreated > 0) {
+        //
+        //  Managed to create at least one device.
+        //
+        IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
+        return STATUS_SUCCESS;
+    }
+    ExFreePool(BindStringSave);
+    ExFreePool(ExportStringSave);
+ */
+
+RegistryError:
+    IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
+    NdisDeregisterProtocol(
+        &Status,
+        NdisProtocolHandle
+        );
+
+    Status=STATUS_UNSUCCESSFUL;
+
+    return(Status);
+
+}
+
+//-------------------------------------------------------------------
+
+PWCHAR getAdaptersList(void)
+{
+       PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+       OBJECT_ATTRIBUTES objAttrs;
+       NTSTATUS status;
+       HANDLE keyHandle;
+       UINT BufPos=0;
+       
+#define NPF_TAG_DEVICENAME  TAG('0', 'P', 'W', 'A')
+       PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, NPF_TAG_DEVICENAME);
+       
+       if (DeviceNames == NULL) {
+               IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
+                       return NULL;
+       }
+       
+       InitializeObjectAttributes(&objAttrs, &AdapterListKey,
+               OBJ_CASE_INSENSITIVE, NULL, NULL);
+       status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+       if (!NT_SUCCESS(status)) {
+
+        //IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+        IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, AdapterListKey.Buffer);)
+
+    } else { //OK
+               ULONG resultLength;
+               KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+               CHAR AdapInfo[1024];
+               UINT i=0;
+               
+               IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
+                       
+                       // Scan the list of the devices
+                       while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) {
+                               WCHAR ExportKeyName [512];
+                               PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
+                               UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+                               PWCHAR LinkageKeyPrefix = L"\\Linkage";
+                               UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
+                               NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
+                               PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
+                               UNICODE_STRING AdapterKeyName;
+                               HANDLE ExportKeyHandle;
+                               KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+                               ULONG resultLength;
+                               
+                               RtlCopyMemory(ExportKeyName,
+                                       ExportKeyPrefix,
+                                       ExportKeyPrefixSize);
+                               
+                               RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
+                                       tInfo->Name,
+                                       tInfo->NameLength+2);
+                               
+                               RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
+                                       LinkageKeyPrefix,
+                                       LinkageKeyPrefixSize);
+                               
+                               IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
+                                                                               
+                               RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
+                               
+                               InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
+                                       OBJ_CASE_INSENSITIVE, NULL, NULL);
+                               
+                               status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
+                               
+                               if (!NT_SUCCESS(status)) {
+                                       DbgPrint("OpenKey Failed, %d!\n",status);
+                                       i++;
+                                       continue;
+                               }
+                               
+                               status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+                                       KeyValuePartialInformation, &valueInfo,
+                                       sizeof(valueInfo), &resultLength);
+                               
+                               if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+                                       IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+                } else { // We know how big it needs to be.
+                                       ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+#define NPF_TAG_KEYVALUE  TAG('1', 'P', 'W', 'A')
+                                       PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =     (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE);
+                                       if (valueInfoP != NULL) {
+                                               status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+                                                       KeyValuePartialInformation,
+                                                       valueInfoP,
+                                                       valueInfoLength, &resultLength);
+                                               if (!NT_SUCCESS(status)) {
+                                                       IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
+                        } else {
+                                                       IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
+                                                               RtlCopyMemory((PCHAR)DeviceNames+BufPos,
+                                                               valueInfoP->Data,
+                                                               valueInfoP->DataLength);
+                                                       BufPos+=valueInfoP->DataLength-2;
+                                               }
+                                               
+                                               ExFreePool(valueInfoP);
+                    } else {
+                                               IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
+                                       }
+                                       
+                               }
+                               
+                               // terminate the buffer
+                               DeviceNames[BufPos/2]=0;
+                               DeviceNames[BufPos/2+1]=0;
+                               
+                               ZwClose (ExportKeyHandle);
+                               i++;
+                               
+                       }
+                       
+                       ZwClose (keyHandle);
+                       
+       }
+       if(BufPos==0){
+               ExFreePool(DeviceNames);
+               return NULL;
+       }
+       return DeviceNames;
+}
+
+//-------------------------------------------------------------------
+
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
+{
+  PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+  OBJECT_ATTRIBUTES objAttrs;
+  NTSTATUS status;
+  HANDLE keyHandle;
+
+  InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
+                             OBJ_CASE_INSENSITIVE, NULL, NULL);
+  status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+  if (!NT_SUCCESS(status)) {
+    IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+  } else {
+    ULONG resultLength;
+    KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+    IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
+
+    status = ZwQueryValueKey(keyHandle, &bindValueName,
+                             KeyValuePartialInformation, &valueInfo,
+                             sizeof(valueInfo), &resultLength);
+    if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+      IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+    } else {                      // We know how big it needs to be.
+      ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+#define NPF_TAG_KEYVALUE2  TAG('2', 'P', 'W', 'A')
+      PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
+        (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE2);
+      
+         if (valueInfoP != NULL) {
+        status = ZwQueryValueKey(keyHandle, &bindValueName,
+                                 KeyValuePartialInformation,
+                                 valueInfoP,
+                                 valueInfoLength, &resultLength);
+      
+               if (!NT_SUCCESS(status)) {
+          IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
+        }
+        else if (valueInfoLength != resultLength) {
+          IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
+                     "but previous len = %u\n",
+                     resultLength, valueInfoLength);)
+        }
+        else if (valueInfoP->Type != REG_MULTI_SZ) {
+          IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
+                     valueInfoP->Type);)
+        }
+        else {                  // It's OK
+#if DBG
+          ULONG i;
+          WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
+          IF_LOUD(DbgPrint("\n\nBind value:\n");)
+          for (i = 0; *dataP != UNICODE_NULL; i++) {
+            UNICODE_STRING macName;
+            RtlInitUnicodeString(&macName, dataP);
+            IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
+            dataP +=
+              (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+          }
+#endif // DBG
+          result = valueInfoP;
+        }
+      }
+    }
+    ZwClose(keyHandle);
+  }
+  return result;
+}
+
+//-------------------------------------------------------------------
+
+BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
+                     IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
+{
+    NTSTATUS status;
+    PDEVICE_OBJECT devObjP;
+    UNICODE_STRING deviceName;
+       UNICODE_STRING deviceSymLink;
+
+       IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
+    if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
+                       devicePrefix.Length) < devicePrefix.Length) {
+               return FALSE;
+    }
+
+    deviceName.Length = 0;
+    deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
+#define NPF_TAG_DEVICENAMEBUF  TAG('3', 'P', 'W', 'A')
+    deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, NPF_TAG_DEVICENAMEBUF);
+       if (deviceName.Buffer == NULL)
+               return FALSE;
+
+       deviceSymLink.Length = 0;
+       deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length 
+               + symbolicLinkPrefix.Length 
+               + NPF_Prefix.Length 
+               + sizeof(UNICODE_NULL));
+
+#define NPF_TAG_SYMLINKBUF  TAG('3', 'P', 'W', 'A')
+       deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, NPF_TAG_SYMLINKBUF);
+
+       if (deviceSymLink.Buffer  == NULL)
+       {
+               ExFreePool(deviceName.Buffer);
+               return FALSE;
+       }
+
+    RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
+    RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
+    RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
+                             devicePrefix.Length / sizeof(WCHAR));
+    
+       RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
+       RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
+       RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
+               devicePrefix.Length / sizeof(WCHAR));
+
+       IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
+    
+       status = IoCreateDevice(adriverObjectP, 
+        sizeof(PDEVICE_EXTENSION),
+        &deviceName, 
+        FILE_DEVICE_TRANSPORT,
+        0,
+        FALSE,
+        &devObjP);
+
+    if (NT_SUCCESS(status)) {
+        PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
+               IF_LOUD(DbgPrint("Device created successfully\n"););
+
+        devObjP->Flags |= DO_DIRECT_IO;
+        RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
+               devExtP->NdisProtocolHandle=aProtoHandle;
+
+               IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
+
+               if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS) {
+                       IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
+
+                       ExFreePool(deviceName.Buffer);
+                       ExFreePool(deviceSymLink.Buffer);
+
+                       devExtP->ExportString = NULL;
+
+                       return FALSE;
+    }
+
+               IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
+
+               devExtP->ExportString = deviceSymLink.Buffer;
+
+        ExFreePool(deviceName.Buffer);
+
+               return TRUE;
+    }
+  
+       else 
+       {
+               IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+               ExFreePool(deviceName.Buffer);
+               ExFreePool(deviceSymLink.Buffer);
+               
+               return FALSE;
+       }
+}
+
+//-------------------------------------------------------------------
+
+VOID STDCALL
+NPF_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+    PDEVICE_OBJECT     DeviceObject;
+    PDEVICE_OBJECT     OldDeviceObject;
+    PDEVICE_EXTENSION  DeviceExtension;
+       
+    NDIS_HANDLE        NdisProtocolHandle;
+    NDIS_STATUS        Status;
+       
+       NDIS_STRING                SymLink;
+
+    IF_LOUD(DbgPrint("NPF: Unload\n"););
+
+       DeviceObject    = DriverObject->DeviceObject;
+
+    while (DeviceObject != NULL) {
+        OldDeviceObject=DeviceObject;
+               
+        DeviceObject=DeviceObject->NextDevice;
+
+               DeviceExtension = OldDeviceObject->DeviceExtension;
+
+        NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
+
+               IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
+                       DeviceExtension->AdapterName.Buffer,
+                       NdisProtocolHandle,
+                       DeviceObject,
+                       OldDeviceObject););
+
+               if (DeviceExtension->ExportString)
+               {
+                       RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
+               
+                       IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
+
+                       IoDeleteSymbolicLink(&SymLink);
+                       ExFreePool(DeviceExtension->ExportString);
+               }
+
+        IoDeleteDevice(OldDeviceObject);
+    }
+
+       NdisDeregisterProtocol(
+        &Status,
+        NdisProtocolHandle
+        );
+
+       // Free the adapters names
+       ExFreePool( bindP );
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+    POPEN_INSTANCE      Open;
+    PIO_STACK_LOCATION  IrpSp;
+    PLIST_ENTRY         RequestListEntry;
+    PINTERNAL_REQUEST   pRequest;
+    ULONG               FunctionCode;
+    NDIS_STATUS                Status;
+    PLIST_ENTRY         PacketListEntry;
+       UINT                            i;
+       PUCHAR                          tpointer;
+       ULONG                           dim,timeout;
+       PUCHAR                          prog;
+       PPACKET_OID_DATA    OidData;
+       int                                     *StatsBuf;
+    PNDIS_PACKET        pPacket;
+       ULONG                           mode;
+       PWSTR                           DumpNameBuff;
+       PUCHAR                          TmpBPFProgram;
+       INT                                     WriteRes;
+       BOOLEAN                         SyncWrite = FALSE;
+       struct bpf_insn         *initprogram;
+       ULONG                           insns;
+       ULONG                           cnt;
+       BOOLEAN                         IsExtendedFilter=FALSE;
+
+    IF_LOUD(DbgPrint("NPF: IoControl\n");)
+               
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+    Open=IrpSp->FileObject->FsContext;
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    IF_LOUD(DbgPrint("NPF: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
+               
+
+       switch (FunctionCode){
+               
+       case BIOCGSTATS: //function to get the capture stats
+               
+               if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){                       
+                       EXIT_FAILURE(0);
+               }
+
+               *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
+               *(((PUINT)Irp->UserBuffer)) = Open->Received;
+               *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
+               *(((PUINT)Irp->UserBuffer)+2) = 0;              // Not yet supported
+               
+               EXIT_SUCCESS(4*sizeof(INT));
+               
+               break;
+               
+       case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
+               if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){                    
+                       EXIT_FAILURE(0);
+               }
+
+               RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
+
+               EXIT_SUCCESS(26);
+
+               break;
+
+       case BIOCSENDPACKETSSYNC:
+
+               SyncWrite = TRUE;
+
+       case BIOCSENDPACKETSNOSYNC:
+
+               WriteRes = NPF_BufferedWrite(Irp,
+                       (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+                       IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+                       SyncWrite);
+
+               if( WriteRes != -1)
+               {
+                       EXIT_SUCCESS(WriteRes);
+               }
+               
+               EXIT_FAILURE(WriteRes);
+
+               break;
+
+       case BIOCSETF:  
+               
+               // Free the previous buffer if it was present
+               if(Open->bpfprogram!=NULL){
+                       TmpBPFProgram=Open->bpfprogram;
+                       Open->bpfprogram = NULL;
+                       ExFreePool(TmpBPFProgram);
+               }
+               
+               if (Open->Filter!=NULL)
+               {
+                       JIT_BPF_Filter *OldFilter=Open->Filter;
+                       Open->Filter=NULL;
+                       BPF_Destroy_JIT_Filter(OldFilter);
+               }
+        
+               // Get the pointer to the new program
+               prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
+               
+               if(prog==NULL){
+                       IF_LOUD(DbgPrint("0001");)
+                       
+                       EXIT_FAILURE(0);
+               }
+               
+               insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
+               
+               //count the number of operative instructions
+               for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
+               
+               IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
+
+               if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0) 
+               {
+                       IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
+       
+                       IsExtendedFilter=TRUE;
+
+                       initprogram=&((struct bpf_insn*)prog)[cnt+1];
+                       
+                       if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
+                       {
+                       
+                               IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
+                               
+                               EXIT_FAILURE(0);
+                       }
+               }
+
+               //the NPF processor has been initialized, we have to validate the operative instructions
+               insns=cnt;
+               
+               if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
+               {
+                       IF_LOUD(DbgPrint("Error validating program");)
+                       //FIXME: the machine has been initialized(?), but the operative code is wrong. 
+                       //we have to reset the machine!
+                       //something like: reallocate the mem_ex, and reset the tme_core
+                       EXIT_FAILURE(0);
+               }
+               
+               // Allocate the memory to contain the new filter program
+               // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
+#define NPF_TAG_BPFPROG  TAG('4', 'P', 'W', 'A')
+               TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), NPF_TAG_BPFPROG);
+               if (TmpBPFProgram==NULL){
+                       IF_LOUD(DbgPrint("Error - No memory for filter");)
+                       // no memory
+                       EXIT_FAILURE(0);
+               }
+               
+               //copy the program in the new buffer
+               RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
+               Open->bpfprogram=TmpBPFProgram;
+               
+               // Create the new JIT filter function
+               if(!IsExtendedFilter)
+                       if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL) {
+                       IF_LOUD(DbgPrint("Error jittering filter");)
+                       EXIT_FAILURE(0);
+               }
+
+               //return
+               Open->Bhead = 0;
+               Open->Btail = 0;
+               (INT)Open->BLastByte = -1;
+               Open->Received = 0;             
+               Open->Dropped = 0;
+               Open->Accepted = 0;
+
+               EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+               
+               break;          
+               
+       case BIOCSMODE:  //set the capture mode
+               
+               mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               if(mode == MODE_CAPT){
+                       Open->mode=MODE_CAPT;
+                       
+                       EXIT_SUCCESS(0);
+               }
+               else if (mode==MODE_MON){
+                       Open->mode=MODE_MON;
+
+                       EXIT_SUCCESS(0);
+               }       
+               else{
+                       if(mode & MODE_STAT){
+                               Open->mode = MODE_STAT;
+                               Open->Nbytes.QuadPart=0;
+                               Open->Npackets.QuadPart=0;
+                               
+                               if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
+                               
+                       }
+                       
+                       if(mode & MODE_DUMP){
+                               
+                               Open->mode |= MODE_DUMP;
+                               Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
+                               
+                       }       
+                       EXIT_SUCCESS(0);
+               }
+               
+               EXIT_FAILURE(0);
+               
+               break;
+
+       case BIOCSETDUMPFILENAME:
+
+               if(Open->mode & MODE_DUMP)
+               {
+                       
+                       // Close current dump file
+                       if(Open->DumpFileHandle != NULL){
+                               NPF_CloseDumpFile(Open);
+                               Open->DumpFileHandle = NULL;
+                       }
+                       
+                       if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
+                               EXIT_FAILURE(0);
+                       }
+                       
+                       // Allocate the buffer that will contain the string
+#define NPF_TAG_DUMPNAMEBUF  TAG('5', 'P', 'W', 'A')
+                       DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, NPF_TAG_DUMPNAMEBUF);
+                       if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
+                               IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
+                                       EXIT_FAILURE(0);
+                       }
+                       
+                       // Copy the buffer
+                       RtlCopyBytes((PVOID)DumpNameBuff, 
+                               Irp->AssociatedIrp.SystemBuffer, 
+                               IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+                       
+                       // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system 
+                       ((SHORT*)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
+                       
+                       // Create the unicode string
+                       RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
+                       
+                       IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
+                               Open->DumpFileName.Buffer,
+                               IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+                               
+                       // Try to create the file
+                       if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
+                               NT_SUCCESS( NPF_StartDump(Open))){
+                               
+                               EXIT_SUCCESS(0);
+                       }
+               }
+               
+               EXIT_FAILURE(0);
+               
+               break;
+                               
+       case BIOCSETDUMPLIMITS:
+
+               Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+               Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
+
+               IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
+
+               EXIT_SUCCESS(0);
+
+               break;
+
+       case BIOCISDUMPENDED:
+               if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){                   
+                       EXIT_FAILURE(0);
+               }
+
+               *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+               EXIT_SUCCESS(4);
+
+               break;
+
+       case BIOCSETBUFFERSIZE:
+               
+               // Get the number of bytes to allocate
+               dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+               // Free the old buffer
+               tpointer = Open->Buffer;
+               if(tpointer != NULL){
+                       Open->BufSize = 0;
+                       Open->Buffer = NULL;
+                       ExFreePool(tpointer);
+               }
+               // Allocate the new buffer
+               if(dim!=0){
+#define NPF_TAG_TPOINTER  TAG('6', 'P', 'W', 'A')
+                       tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, NPF_TAG_TPOINTER);
+                       if (tpointer==NULL)     {
+                               // no memory
+                               Open->BufSize = 0;
+                               Open->Buffer = NULL;
+                               EXIT_FAILURE(0);
+                       }
+               }
+               else
+                       tpointer = NULL;
+
+               Open->Buffer = tpointer;
+               Open->Bhead = 0;
+               Open->Btail = 0;
+               (INT)Open->BLastByte = -1;
+               
+               Open->BufSize = (UINT)dim;
+               EXIT_SUCCESS(dim);
+               
+               break;
+               
+       case BIOCSRTIMEOUT: //set the timeout on the read calls
+               
+               timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               if((int)timeout==-1)
+                       Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
+               else {
+                       Open->TimeOut.QuadPart=(LONGLONG)timeout;
+                       Open->TimeOut.QuadPart*=10000;
+                       Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
+               }
+
+               //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
+               EXIT_SUCCESS(timeout);
+               
+               break;
+               
+       case BIOCSWRITEREP: //set the writes repetition number
+               
+               Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               EXIT_SUCCESS(Open->Nwrites);
+               
+               break;
+
+       case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
+
+               Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               EXIT_SUCCESS(Open->MinToCopy);
+               
+               break;
+               
+       case IOCTL_PROTOCOL_RESET:
+               
+        IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
+
+               IoMarkIrpPending(Irp);
+               Irp->IoStatus.Status = STATUS_SUCCESS;
+
+               ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
+        NdisReset(&Status,Open->AdapterHandle);
+        if (Status != NDIS_STATUS_PENDING) {
+            IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
+                               NPF_ResetComplete(Open,Status);
+        }
+               
+               break;
+               
+               
+       case BIOCSETOID:
+       case BIOCQUERYOID:
+               
+               // Extract a request from the list of free ones
+               RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
+               if (RequestListEntry == NULL)
+               {
+                       EXIT_FAILURE(0);
+               }
+
+               pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
+               pRequest->Irp=Irp;
+               pRequest->Internal = FALSE;
+
+        
+               //
+        //  See if it is an Ndis request
+        //
+        OidData=Irp->AssociatedIrp.SystemBuffer;
+               
+        if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
+            &&
+            (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
+            &&
+            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
+            &&
+            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
+                       
+            IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
+                               
+                               //
+                               //  The buffer is valid
+                               //
+                               if (FunctionCode == BIOCSETOID){
+                                       
+                                       pRequest->Request.RequestType=NdisRequestSetInformation;
+                                       pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
+                                       
+                                       pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
+                                       pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
+                               } else{
+                                       pRequest->Request.RequestType=NdisRequestQueryInformation;
+                                       pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
+                                       
+                                       pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
+                                       pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
+                                       
+                               }
+
+                               NdisResetEvent(&Open->IOEvent);
+                               //
+                               //  submit the request
+                               //
+                               NdisRequest(
+                                       &Status,
+                                       Open->AdapterHandle,
+                                       &pRequest->Request
+                                       );
+                               
+        } else {
+            //
+            //  buffer too small
+            //
+            Status=NDIS_STATUS_FAILURE;
+            pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
+            pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
+                       
+        }
+               
+        if (Status != NDIS_STATUS_PENDING) {
+            IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
+                               
+                       NPF_RequestComplete(Open, &pRequest->Request, Status);
+            return Status;
+                       
+        }
+
+               NdisWaitEvent(&Open->IOEvent, 5000);
+
+               return(Open->IOStatus);
+               
+               break;
+               
+               
+       default:
+               
+               EXIT_FAILURE(0);
+       }
+       
+       return Status;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_RequestComplete(
+    IN NDIS_HANDLE   ProtocolBindingContext,
+    IN PNDIS_REQUEST NdisRequest,
+    IN NDIS_STATUS   Status
+    )
+
+{
+    POPEN_INSTANCE      Open;
+    PIO_STACK_LOCATION  IrpSp;
+    PIRP                Irp;
+    PINTERNAL_REQUEST   pRequest;
+    UINT                FunctionCode;
+       KIRQL                           OldIrq;
+
+    PPACKET_OID_DATA    OidData;
+
+    IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
+
+    Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+    pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
+    Irp=pRequest->Irp;
+
+       if(pRequest->Internal == TRUE){
+
+               // Put the request in the list of the free ones
+               ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+               
+           if(Status != NDIS_STATUS_SUCCESS)
+                       Open->MaxFrameSize = 1514;      // Assume Ethernet
+
+               // We always return success, because the adapter has been already opened
+               Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+               Irp->IoStatus.Information = 0;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+               return;
+       }
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+
+    OidData=Irp->AssociatedIrp.SystemBuffer;
+
+    if (FunctionCode == BIOCSETOID) {
+
+        OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
+
+    } else {
+
+        if (FunctionCode == BIOCQUERYOID) {
+
+            OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
+
+                   IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
+        }
+
+    }
+
+    Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
+
+    IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+    ExInterlockedInsertTailList(
+        &Open->RequestList,
+        &pRequest->ListElement,
+        &Open->RequestSpinLock);
+
+    Irp->IoStatus.Status = Status;
+
+       Open->IOStatus = Status;
+
+       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+       // Unlock the caller
+       NdisSetEvent(&Open->IOEvent);
+
+    return;
+
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_Status(
+    IN NDIS_HANDLE   ProtocolBindingContext,
+    IN NDIS_STATUS   Status,
+    IN PVOID         StatusBuffer,
+    IN UINT          StatusBufferSize
+    )
+
+{
+
+    IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
+    return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_StatusComplete(
+    IN NDIS_HANDLE  ProtocolBindingContext
+    )
+
+{
+
+    IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
+
+    return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_ReadRegistry(
+    IN  PWSTR              *MacDriverName,
+    IN  PWSTR              *PacketDriverName,
+    IN  PUNICODE_STRING     RegistryPath
+    )
+
+{
+    NTSTATUS   Status;
+
+    RTL_QUERY_REGISTRY_TABLE ParamTable[4];
+
+    PWSTR      Bind       = L"Bind";
+    PWSTR      Export     = L"Export";
+    PWSTR      Parameters = L"Parameters";
+    PWSTR      Linkage    = L"Linkage";
+
+    PWCHAR     Path;
+
+#define NPF_TAG_PATH  TAG('7', 'P', 'W', 'A')
+    Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), NPF_TAG_PATH);
+
+    if (Path == NULL) {
+               IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlZeroMemory(
+        Path,
+        RegistryPath->Length+sizeof(WCHAR)
+        );
+
+    RtlCopyMemory(
+        Path,
+        RegistryPath->Buffer,
+        RegistryPath->Length
+        );
+
+    IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
+
+    RtlZeroMemory(
+        ParamTable,
+        sizeof(ParamTable)
+        );
+
+
+
+    //
+    //  change to the linkage key
+    //
+    //ParamTable[0].QueryRoutine = NULL;
+    ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine;
+    ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+    ParamTable[0].Name = Linkage;
+
+
+    //
+    //  Get the name of the mac driver we should bind to
+    //
+
+    ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
+    ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+                          RTL_QUERY_REGISTRY_NOEXPAND;
+
+    ParamTable[1].Name = Bind;
+    ParamTable[1].EntryContext = (PVOID)MacDriverName;
+    ParamTable[1].DefaultType = REG_MULTI_SZ;
+
+    //
+    //  Get the name that we should use for the driver object
+    //
+
+    ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
+    ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+                          RTL_QUERY_REGISTRY_NOEXPAND;
+
+    ParamTable[2].Name = Export;
+    ParamTable[2].EntryContext = (PVOID)PacketDriverName;
+    ParamTable[2].DefaultType = REG_MULTI_SZ;
+
+
+    Status=RtlQueryRegistryValues(
+               RTL_REGISTRY_ABSOLUTE,
+               Path,
+               ParamTable,
+               NULL,
+               NULL
+               );
+
+    if (Status != STATUS_SUCCESS) {
+               // insert hard coded parameters here while registry on ROS is not working...
+               IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
+
+        *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+               //memcpy(*MacDriverName,    L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+               memcpy(*MacDriverName,    L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+               
+        *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+               memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
+               Status = STATUS_SUCCESS;
+
+       }
+
+    ExFreePool(Path);
+    return Status;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_QueryRegistryRoutine(
+    IN PWSTR     ValueName,
+    IN ULONG     ValueType,
+    IN PVOID     ValueData,
+    IN ULONG     ValueLength,
+    IN PVOID     Context,
+    IN PVOID     EntryContext
+    )
+
+{
+
+    PUCHAR       Buffer;
+
+    IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
+
+    if (ValueType != REG_MULTI_SZ) {
+
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+
+    }
+
+#define NPF_TAG_REGBUF  TAG('8', 'P', 'W', 'A')
+    Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, NPF_TAG_REGBUF);
+
+    if (Buffer==NULL) {
+
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    RtlCopyMemory(
+        Buffer,
+        ValueData,
+        ValueLength
+        );
+
+    *((PUCHAR *)EntryContext)=Buffer;
+
+    return STATUS_SUCCESS;
+
+}
diff --git a/drivers/net/npf/packet.h b/drivers/net/npf/packet.h
new file mode 100644 (file)
index 0000000..062a790
--- /dev/null
@@ -0,0 +1,959 @@
+/*
+ * Copyright (c) 1999, 2000
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions 
+ *  @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#define NTKERNEL    ///< Forces the compilation of the jitter with kernel calls 
+
+#ifdef __GNUC__
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#define UNICODE_NULL ((WCHAR)0) // winnt
+#include "win_bpf.h"
+#include <internal/ps.h>
+#endif
+
+#include "jitter.h"
+#include "tme.h"
+
+#define  MAX_REQUESTS   32 ///< Maximum number of simultaneous IOCTL requests.
+
+#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))  ///< Alignment macro. Rounds up to the next 
+                                                                                ///< even multiple of Packet_ALIGNMENT. 
+
+
+/***************************/
+/*         IOCTLs          */
+/***************************/
+
+/*!
+  \brief IOCTL code: set kernel buffer size.
+
+  This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
+  When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one 
+  and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently 
+  buffered packets are lost.
+*/
+#define  BIOCSETBUFFERSIZE 9592
+
+/*!
+  \brief IOCTL code: set packet filtering program.
+
+  This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the 
+  bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE, 
+  the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the 
+  OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to 
+  every incoming packet. This command also empties the circular buffer used by current instance 
+  to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
+*/
+#define  BIOCSETF 9030
+
+/*!
+  \brief IOCTL code: get the capture stats
+
+  This command returns to the application the number of packets received and the number of packets dropped by 
+  an instance of the driver.
+*/
+#define  BIOCGSTATS 9031
+
+/*!
+  \brief IOCTL code: set the read timeout
+
+  This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define  BIOCSRTIMEOUT 7416
+
+/*!
+  \brief IOCTL code: set working mode
+
+  This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
+  buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
+  statistical mode or #MODE_DUMP for dump mode.
+*/
+#define  BIOCSMODE 7412
+
+/*!
+  \brief IOCTL code: set number of physical repetions of every packet written by the app
+
+  Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites 
+  member, and is used to implement the 'multiple write' feature of the driver.
+*/
+#define  BIOCSWRITEREP 7413
+
+/*!
+  \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
+
+  This command sets the OPEN_INSTANCE::MinToCopy member.
+*/
+#define  BIOCSMINTOCOPY 7414
+
+/*!
+  \brief IOCTL code: set an OID value
+
+  This IOCTL is used to perform an OID set operation on the NIC driver. 
+*/
+#define  BIOCSETOID 2147483648UL
+
+/*!
+  \brief IOCTL code: get an OID value
+
+  This IOCTL is used to perform an OID get operation on the NIC driver. 
+*/
+#define  BIOCQUERYOID 2147483652UL
+
+/*!
+  \brief IOCTL code: set the name of a the file used by kernel dump mode
+
+  This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
+  The dump thread uses it to copy the content of the circular buffer to file.
+  If a file was already opened, the driver closes it before opening the new one.
+*/
+#define  BIOCSETDUMPFILENAME 9029
+
+/*!
+  \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
+
+  Command used by the application to retrieve the name of the global event associated with a NPF instance.
+  The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
+*/
+#define  BIOCGEVNAME 7415
+
+/*!
+  \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
+
+  Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+  a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as 
+  possible. The NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define  BIOCSENDPACKETSNOSYNC 9032
+
+/*!
+  \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
+
+  Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+  a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets 
+  are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
+  packet. NPF_BufferedWrite() function is invoked to send the packets. 
+*/
+#define  BIOCSENDPACKETSSYNC 9033
+
+/*!
+  \brief IOCTL code: Set the dump file limits.
+
+  This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
+  driver works in dump mode.
+*/
+#define  BIOCSETDUMPLIMITS 9034
+
+/*!
+  \brief IOCTL code: Get the status of the kernel dump process.
+
+  This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
+  (amount of bytes or number of packets) has been reached.
+*/
+#define BIOCISDUMPENDED 7411
+
+// Working modes
+#define MODE_CAPT 0x0       ///< Capture working mode
+#define MODE_STAT 0x1       ///< Statistical working mode
+#define MODE_MON  0x2       ///< Kernel monitoring mode
+#define MODE_DUMP 0x10      ///< Kernel dump working mode
+
+
+#define IMMEDIATE 1         ///< Immediate timeout. Forces a read call to return immediately.
+
+
+// The following definitions are used to provide compatibility 
+// of the dump files with the ones of libpcap
+#define TCPDUMP_MAGIC 0xa1b2c3d4    ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MAJOR 2        ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MINOR 4        ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+
+/*!
+  \brief Header of a libpcap dump file.
+
+  Used when a driver instance is set in dump mode to create a libpcap-compatible file.
+*/
+struct packet_file_header 
+{
+    UINT magic;             ///< Libpcap magic number
+    USHORT version_major;   ///< Libpcap major version
+    USHORT version_minor;   ///< Libpcap minor version
+    UINT thiszone;          ///< Gmt to local correction
+    UINT sigfigs;           ///< Accuracy of timestamps
+    UINT snaplen;           ///< Length of the max saved portion of each packet
+    UINT linktype;          ///< Data link type (DLT_*). See win_bpf.h for details.
+};
+
+/*!
+  \brief Header associated to a packet in the driver's buffer when the driver is in dump mode.
+  Similar to the bpf_hdr structure, but simpler.
+*/
+struct sf_pkthdr {
+    struct timeval  ts;         ///< time stamp
+    UINT            caplen;     ///< Length of captured portion. The captured portion can be different from 
+                                ///< the original packet, because it is possible (with a proper filter) to 
+                                ///< instruct the driver to capture only a portion of the packets. 
+    UINT            len;        ///< Length of the original packet (off wire).
+};
+
+/*!
+  \brief Stores an OID request.
+  
+  This structure is used by the driver to perform OID query or set operations on the underlying NIC driver. 
+  The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level 
+  applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure.
+  This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and
+  maintaining information about the IRPs to complete.
+*/
+typedef struct _INTERNAL_REQUEST {
+    LIST_ENTRY      ListElement;        ///< Used to handle lists of requests.
+    PIRP            Irp;                ///< Irp that performed the request
+    BOOLEAN         Internal;           ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
+    NDIS_REQUEST    Request;            ///< The structure with the actual request, that will be passed to NdisRequest().
+} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
+
+/*!
+  \brief Contains a NDIS packet.
+  
+  The driver uses this structure to wrap a NDIS_PACKET  structure.
+  This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and
+  maintaining information about the IRPs to complete.
+*/
+typedef struct _PACKET_RESERVED {
+    LIST_ENTRY      ListElement;        ///< Used to handle lists of packets.
+    PIRP            Irp;                ///< Irp that performed the request
+    PMDL            pMdl;               ///< MDL mapping the buffer of the packet.
+    BOOLEAN         FreeBufAfterWrite;  ///< True if the memory buffer associated with the packet must be freed 
+                                        ///< after a call to NdisSend().
+}  PACKET_RESERVED, *PPACKET_RESERVED;
+
+#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
+
+/*!
+  \brief Port device extension.
+  
+  Structure containing some data relative to every adapter on which NPF is bound.
+*/
+typedef struct _DEVICE_EXTENSION {
+    NDIS_HANDLE    NdisProtocolHandle;  ///< NDIS handle of NPF.
+    NDIS_STRING    AdapterName;         ///< Name of the adapter.
+    PWSTR          ExportString;        ///< Name of the exported device, i.e. name that the applications will use 
+                                        ///< to open this adapter through WinPcap.
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*!
+  \brief Contains the state of a running instance of the NPF driver.
+  
+  This is the most important structure of NPF: it is used by almost all the functions of the driver. An
+  _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
+  to the driver.
+*/
+typedef struct _OPEN_INSTANCE
+{
+    PDEVICE_EXTENSION   DeviceExtension;    ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
+                                            ///< the instance is bound.
+    NDIS_HANDLE         AdapterHandle;      ///< NDIS idetifier of the adapter used by this instance.
+    UINT                Medium;             ///< Type of physical medium the underlying NDIS driver uses. See the
+                                            ///< documentation of NdisOpenAdapter in the MS DDK for details.
+    NDIS_HANDLE         PacketPool;         ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
+    PIRP                OpenCloseIrp;       ///< Pointer used to store the open/close IRP requests and provide them to the 
+                                            ///< callbacks of NDIS.
+    KSPIN_LOCK          RequestSpinLock;    ///< SpinLock used to synchronize the OID requests.
+    LIST_ENTRY          RequestList;        ///< List of pending OID requests.
+    LIST_ENTRY          ResetIrpList;       ///< List of pending adapter reset requests.
+    INTERNAL_REQUEST    Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
+    PMDL                BufferMdl;          ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
+    PKEVENT             ReadEvent;          ///< Pointer to the event on which the read calls on this instance must wait.
+    HANDLE              ReadEventHandle;    ///< Handle of the event on which the read calls on this instance must wait.
+    UNICODE_STRING      ReadEventName;      ///< Name of the event on which the read calls on this instance must wait.
+                                            ///< The event is created with a name, so it can be used at user level to know when it 
+                                            ///< is possible to access the driver without being blocked. This fiels stores the name 
+                                            ///< that and is used by the BIOCGEVNAME IOCTL call.
+    INT                 Received;           ///< Number of packets received by current instance from its opening, i.e. number of 
+                                            ///< packet received by the network adapter since the beginning of the 
+                                            ///< capture/monitoring/dump session.
+    INT                 Dropped;            ///< Number of packet that current instance had to drop, from its opening. A packet 
+                                            ///< is dropped if there is no more space to store it in the circular buffer that the 
+                                            ///< driver associates to current instance.
+    INT                 Accepted;           ///< Number of packet that current capture instance acepted, from its opening. A packet 
+                                            ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
+                                            ///< ones that reach the application.
+    PUCHAR              bpfprogram;         ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
+                                            ///< This code is used only in particular situations (for example when the packet received
+                                            ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
+                                            ///< the filtering routine created by the JIT compiler and pointed by the next field 
+                                            ///< is used. See \ref NPF for details on the filtering process.
+    JIT_BPF_Filter      *Filter;            ///< Pointer to the native filtering function created by the jitter. 
+                                            ///< See BPF_jitter() for details.
+    PUCHAR              Buffer;             ///< Pointer to the circular buffer associated with every driver instance. It contains the 
+                                            ///< data that will be passed to the application. See \ref NPF for details.
+    UINT                Bhead;              ///< Head of the circular buffer.
+    UINT                Btail;              ///< Tail of the circular buffer.
+    UINT                BufSize;            ///< Size of the circular buffer.
+    UINT                BLastByte;          ///< Position of the last valid byte in the circular buffer.
+    PMDL                TransferMdl;        ///< MDL used to map the portion of the buffer that will contain an incoming packet. 
+                                            ///< Used by NdisTransferData().
+    NDIS_SPIN_LOCK      BufLock;            ///< SpinLock that protects the access tho the circular buffer variables.
+    UINT                MinToCopy;          ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
+                                            ///< BIOCSMINTOCOPY IOCTL.
+    LARGE_INTEGER       TimeOut;            ///< Timeout after which a read is released, also if the amount of data in the buffer is 
+                                            ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
+                                            
+    int                 mode;               ///< Working mode of the driver. See PacketSetMode() for details.
+    LARGE_INTEGER       Nbytes;             ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
+    LARGE_INTEGER       Npackets;           ///< Number of packets accepted by the filter when this instance is in statistical mode.
+    NDIS_SPIN_LOCK      CountersLock;       ///< SpinLock that protects the statistical mode counters.
+    UINT                Nwrites;            ///< Number of times a single write must be physically repeated. See \ref NPF for an 
+                                            ///< explanation
+    UINT                Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
+    NDIS_EVENT          WriteEvent;         ///< Event used to synchronize the multiple write process.
+    NDIS_EVENT          IOEvent;            ///< Event used to synchronize I/O requests with the callback structure of NDIS.
+    NDIS_STATUS         IOStatus;           ///< Maintains the status of and OID request call, that will be passed to the application.
+    BOOLEAN             Bound;              ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
+                                            ///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
+    HANDLE              DumpFileHandle;     ///< Handle of the file used in dump mode.
+    PFILE_OBJECT        DumpFileObject;     ///< Pointer to the object of the file used in dump mode.
+    PKTHREAD            DumpThreadObject;   ///< Pointer to the object of the thread used in dump mode.
+    HANDLE              DumpThreadHandle;   ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
+    NDIS_EVENT          DumpEvent;          ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
+    LARGE_INTEGER       DumpOffset;         ///< Current offset in the dump file.
+    UNICODE_STRING      DumpFileName;       ///< String containing the name of the dump file.
+    UINT                MaxDumpBytes;       ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it 
+                                            ///< will be closed. A value of 0 means unlimited size.
+    UINT                MaxDumpPacks;       ///< Maximum number of packets that will be saved in the dump file. If this number of 
+                                            ///< packets is reached the dump will be closed. A value of 0 means unlimited number of 
+                                            ///< packets.
+    BOOLEAN             DumpLimitReached;   ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is 
+                                            ///< reached.
+    MEM_TYPE            mem_ex;             ///< Memory used by the TME virtual co-processor
+    TME_CORE            tme;                ///< Data structure containing the virtualization of the TME co-processor
+    NDIS_SPIN_LOCK      machine_lock;       ///< SpinLock that protects the mem_ex buffer
+    UINT                MaxFrameSize;       ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the 
+                                            ///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
+} OPEN_INSTANCE, *POPEN_INSTANCE;
+
+
+#define TRANSMIT_PACKETS 256    ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
+                                ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
+
+
+/// Macro used in the I/O routines to return the control to user-mode with a success status.
+#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
+    Irp->IoStatus.Status = STATUS_SUCCESS;\
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+    return STATUS_SUCCESS;\
+
+/// Macro used in the I/O routines to return the control to user-mode with a failure status.
+#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
+    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+    return STATUS_UNSUCCESSFUL;\
+
+/**
+ *  @}
+ */
+
+
+/***************************/
+/*       Prototypes        */
+/***************************/
+
+/** @defgroup NPF_code NPF functions 
+ *  @{
+ */
+
+
+/*!
+  \brief The initialization routine of the driver.
+  \param DriverObject The driver object of NPF created by the system.
+  \param RegistryPath The registry path containing the keys related to the driver.
+  \return A string containing a list of network adapters.
+
+  DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
+  by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver, 
+  performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
+  callbacks, creates the devices, defines NPF as a protocol inside NDIS.
+*/ 
+//NTSTATUS
+//DriverEntry(
+//    IN PDRIVER_OBJECT DriverObject,
+//    IN PUNICODE_STRING RegistryPath
+//    );
+
+/*!
+  \brief Returns the list of the MACs available on the system.
+  \return A string containing a list of network adapters.
+
+  The list of adapters is retrieved from the 
+  SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key. 
+  NPF tries to create its bindings from this list. In this way it is possible to be loaded
+  and unloaded dynamically without passing from the control panel.
+*/
+PWCHAR getAdaptersList(VOID);
+
+/*!
+  \brief Returns the MACs that bind to TCP/IP.
+  \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
+
+  If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
+*/
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
+
+/*!
+  \brief Creates a device for a given MAC.
+  \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
+  \param amacNameP The name of the network interface that the device will point.
+  \param aProtoHandle NDIS protocol handle of NPF.
+  \return If the function succeeds, the return value is nonzero.
+
+  NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
+  information about the original device. In this way, when the user opens the new device, NPF will be able to
+  determine the correct adapter to use.
+*/
+BOOLEAN createDevice(
+    IN OUT PDRIVER_OBJECT adriverObjectP,
+    IN PUNICODE_STRING amacNameP,
+    NDIS_HANDLE aProtoHandle);
+
+/*!
+  \brief Opens a new instance of the driver.
+  \param DeviceObject Pointer to the device object utilized by the user.
+  \param Irp Pointer to the IRP containing the user request.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  This function is called by the OS when a new instance of the driver is opened, i.e. when a user application 
+  performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
+  and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the 
+  adapter with a call to NdisOpenAdapter.
+*/
+NTSTATUS STDCALL
+NPF_Open(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+/*!
+  \brief Ends the opening of an adapter.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param Status Status of the opening operation performed by NDIS.
+  \param OpenErrorStatus not used by NPF.
+
+  Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished an open operation that was previously started by NPF_Open().
+*/
+VOID
+NPF_OpenAdapterComplete(
+    IN NDIS_HANDLE  ProtocolBindingContext,
+    IN NDIS_STATUS  Status,
+    IN NDIS_STATUS  OpenErrorStatus
+    );
+
+/*!
+  \brief Closes an instance of the driver.
+  \param DeviceObject Pointer to the device object utilized by the user.
+  \param Irp Pointer to the IRP containing the user request.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  This function is called when a running instance of the driver is closed by the user with a CloseHandle(). 
+  It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the 
+  instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter. 
+*/
+NTSTATUS STDCALL
+NPF_Close(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+/*!
+  \brief Ends the closing of an adapter.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param Status Status of the close operation performed by NDIS.
+
+  Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished a close operation that was previously started by NPF_Close().
+*/
+VOID
+NPF_CloseAdapterComplete(
+    IN NDIS_HANDLE  ProtocolBindingContext,
+    IN NDIS_STATUS  Status
+    );
+
+/*!
+  \brief Callback invoked by NDIS when a packet arrives from the network.
+  \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies 
+   the NPF instance to which the packets are destined.
+  \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request. 
+   This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
+  \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
+  \param HeaderBufferSize Size in bytes of the header.
+  \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's 
+   data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
+   since only a portion can be available at this time. The remaining portion can be obtained with the
+   NdisTransferData() NDIS function.
+  \param LookaheadBufferSize Size in bytes of the lookahead buffer.
+  \param PacketSize Total size of the incoming packet, excluded the header.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of 
+  the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in 
+  statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
+  along with the filtering ones, that is executed for every incoming packet, therefore it is carefully 
+  optimized.
+*/
+NDIS_STATUS
+NPF_tap(
+    IN NDIS_HANDLE ProtocolBindingContext,
+    IN NDIS_HANDLE MacReceiveContext,
+    IN PVOID HeaderBuffer,
+    IN UINT HeaderBufferSize,
+    IN PVOID LookAheadBuffer,
+    IN UINT LookaheadBufferSize,
+    IN UINT PacketSize
+    );
+
+/*!
+  \brief Ends the transfer of a packet.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
+  \param Status Status of the transfer operation.
+  \param BytesTransferred Amount of bytes transferred.
+
+  Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
+*/
+VOID
+NPF_TransferDataComplete(
+    IN NDIS_HANDLE ProtocolBindingContext,
+    IN PNDIS_PACKET Packet,
+    IN NDIS_STATUS Status,
+    IN UINT BytesTransferred
+    );
+
+/*!
+  \brief Callback function that signals the end of a packet reception.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+
+  does nothing in NPF
+*/
+VOID
+NPF_ReceiveComplete(IN NDIS_HANDLE  ProtocolBindingContext);
+
+/*!
+  \brief Handles the IOCTL calls.
+  \param DeviceObject Pointer to the device object utilized by the user.
+  \param Irp Pointer to the IRP containing the user request.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
+  using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
+  The following commands are recognized: 
+  - #BIOCSETBUFFERSIZE 
+  - #BIOCSETF 
+  - #BIOCGSTATS 
+  - #BIOCSRTIMEOUT
+  - #BIOCSMODE 
+  - #BIOCSWRITEREP 
+  - #BIOCSMINTOCOPY 
+  - #BIOCSETOID 
+  - #BIOCQUERYOID 
+  - #BIOCSETDUMPFILENAME
+  - #BIOCGEVNAME
+  - #BIOCSENDPACKETSSYNC
+  - #BIOCSENDPACKETSNOSYNC
+*/
+NTSTATUS STDCALL
+NPF_IoControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+
+/*!
+  \brief Ends an OID request.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param pRequest Pointer to the completed OID request. 
+  \param Status Status of the operation.
+
+  Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished an OID request operation that was previously started by NPF_IoControl().
+*/
+VOID
+NPF_RequestComplete(
+    IN NDIS_HANDLE   ProtocolBindingContext,
+    IN PNDIS_REQUEST pRequest,
+    IN NDIS_STATUS   Status
+    );
+
+/*!
+  \brief Writes a raw packet to the network.
+  \param DeviceObject Pointer to the device object on which the user wrote the packet.
+  \param Irp Pointer to the IRP containing the user request.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
+  be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
+  delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure 
+  associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
+  packet can be sent for performance reasons.
+*/
+NTSTATUS STDCALL
+NPF_Write(
+            IN PDEVICE_OBJECT DeviceObject,
+            IN PIRP Irp
+            );
+
+
+/*!
+  \brief Writes a buffer of raw packets to the network.
+  \param Irp Pointer to the IRP containing the user request.
+  \param UserBuff Pointer to the buffer containing the packets to send.
+  \param UserBuffSize Size of the buffer with the packets.
+  \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+          error occurred during the send. The error can be caused by an adapter problem or by an
+          inconsistent/bogus user buffer.
+
+  This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
+  The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
+  sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
+  When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
+  This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision 
+  of some microseconds (depending on the precision of the performance counter of the machine).
+  If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
+*/
+
+INT NPF_BufferedWrite(IN PIRP Irp, 
+                        IN PCHAR UserBuff, 
+                        IN ULONG UserBuffSize,
+                        BOOLEAN sync);
+
+/*!
+  \brief Ends a send operation.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet. 
+  \param Status Status of the operation.
+
+  Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished an OID request operation that was previously started by NPF_Write().
+*/
+VOID
+NPF_SendComplete(
+    IN NDIS_HANDLE   ProtocolBindingContext,
+    IN PNDIS_PACKET  pPacket,
+    IN NDIS_STATUS   Status
+    );
+
+/*!
+  \brief Ends a reset of the adapter.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param Status Status of the operation.
+
+  Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC 
+  driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET 
+  command.
+*/
+VOID
+NPF_ResetComplete(
+    IN NDIS_HANDLE  ProtocolBindingContext,
+    IN NDIS_STATUS  Status
+    );
+
+/*!
+  \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
+VOID
+NPF_Status(
+    IN NDIS_HANDLE   ProtocolBindingContext,
+    IN NDIS_STATUS   Status,
+    IN PVOID         StatusBuffer,
+    IN UINT          StatusBufferSize
+    );
+
+
+/*!
+  \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
+VOID
+NPF_StatusComplete(IN NDIS_HANDLE  ProtocolBindingContext);
+
+/*!
+  \brief Function called by the OS when NPF is unloaded.
+  \param DriverObject The driver object of NPF created by the system.
+
+  This is the last function executed when the driver is unloaded from the system. It frees global resources,
+  delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
+  service (from control panel or with a console 'net stop npf').
+*/
+VOID STDCALL
+NPF_Unload(IN PDRIVER_OBJECT DriverObject);
+
+
+/*!
+  \brief Function that serves the user's reads.
+  \param DeviceObject Pointer to the device used by the user.
+  \param Irp Pointer to the IRP containing the user request.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
+  kernel buffer to the user buffer associated with Irp.
+  First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance. 
+  - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
+  NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
+  user is not blocking.
+  - If the buffer contains less than MinToCopy bytes, the application's request isn't 
+  satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net 
+  or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
+  - If the instance is in statistical mode or in dump mode, the application's request is blocked until the 
+  timeout kept in OPEN_INSTANCE::TimeOut expires.
+*/
+NTSTATUS STDCALL
+NPF_Read(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+/*!
+  \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
+
+  Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_ReadRegistry(
+    IN  PWSTR              *MacDriverName,
+    IN  PWSTR              *PacketDriverName,
+    IN  PUNICODE_STRING     RegistryPath
+    );
+
+/*!
+  \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver 
+  is manually installed via the control panel.
+
+  Normally not used in recent versions of NPF.
+*/
+NTSTATUS STDCALL
+NPF_QueryRegistryRoutine(
+    IN PWSTR     ValueName,
+    IN ULONG     ValueType,
+    IN PVOID     ValueData,
+    IN ULONG     ValueLength,
+    IN PVOID     Context,
+    IN PVOID     EntryContext
+    );
+
+/*!
+  \brief Callback for NDIS BindAdapterHandler. Not used by NPF.
+  
+  Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
+*/
+VOID NPF_BindAdapter(
+    OUT PNDIS_STATUS            Status,
+    IN  NDIS_HANDLE             BindContext,
+    IN  PNDIS_STRING            DeviceName,
+    IN  PVOID                   SystemSpecific1,
+    IN  PVOID                   SystemSpecific2
+    );
+
+/*!
+  \brief Callback for NDIS UnbindAdapterHandler.
+  \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
+  \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
+  
+  Function called by NDIS when a new adapter is removed from the machine without shutting it down.
+  NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
+  associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
+  is in dump mode.
+*/
+VOID
+NPF_UnbindAdapter(
+    OUT PNDIS_STATUS        Status,
+    IN  NDIS_HANDLE         ProtocolBindingContext,
+    IN  NDIS_HANDLE         UnbindContext
+    );
+
+/*!
+  \brief Validates a filtering program arriving from the user-level app.
+  \param f The filter.
+  \param len Its length, in pseudo instructions.
+  \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
+  \return true if f is a valid filter program..
+  
+  The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily 
+  crash the system.
+  This function returns true if f is a valid filter program. The constraints are that each jump be forward and 
+  to a valid code.  The code must terminate with either an accept or reject. 
+*/
+int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
+
+/*!
+  \brief The filtering pseudo-machine interpreter.
+  \param pc The filter.
+  \param p Pointer to a memory buffer containing the packet on which the filter will be executed.
+  \param wirelen Original length of the packet.
+  \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+  has not yet finished), bpf_filter can be executed on a portion of the packet.
+  \param mem_ex The extended memory.
+  \param tme The virtualization of the TME co-processor
+  \param time_ref Data structure needed by the TME co-processor to timestamp data
+  \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+   the whole packet must be kept.
+  
+  \note this function is not used in normal situations, because the jitter creates a native filtering function
+  that is faster than the interpreter.
+*/
+UINT bpf_filter(register struct bpf_insn *pc,
+                register UCHAR *p,
+                UINT wirelen,
+                register UINT buflen,
+                PMEM_TYPE mem_ex,
+                PTME_CORE tme,
+                struct time_conv *time_ref);
+
+/*!
+  \brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(), 
+  but works correctly also if the MAC header and the data of the packet are in two different buffers.
+  \param pc The filter.
+  \param p Pointer to a memory buffer containing the MAC header of the packet.
+  \param pd Pointer to a memory buffer containing the data of the packet.
+  \param wirelen Original length of the packet.
+  \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+  has not yet finished), bpf_filter can be executed on a portion of the packet.
+  \param mem_ex The extended memory.
+  \param tme The virtualization of the TME co-processor
+  \param time_ref Data structure needed by the TME co-processor to timestamp data
+  \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+   the whole packet must be kept.
+  
+  This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
+*/
+UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+                               register UCHAR *p,
+                               register UCHAR *pd,
+                               register int headersize,
+                               UINT wirelen,
+                               register UINT buflen,
+                               PMEM_TYPE mem_ex,
+                               PTME_CORE tme,
+                               struct time_conv *time_ref);
+
+/*!
+  \brief Creates the file that will receive the packets when the driver is in dump mode.
+  \param Open The NPF instance that opens the file.
+  \param fileName Pointer to a UNICODE string containing the name of the file.
+  \param append Boolean value that specifies if the data must be appended to the file.
+  \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
+
+/*!
+  \brief Starts dump to file.
+  \param Open The NPF instance that opens the file.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  This function performs two operations. First, it writes the libpcap header at the beginning of the file.
+  Second, it starts the thread that asynchronously dumps the network data to the file.
+*/
+NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
+
+/*!
+  \brief The dump thread.
+  \param Open The NPF instance that creates the thread.
+
+  This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower 
+  priority than the TAP.
+*/
+VOID NPF_DumpThread(POPEN_INSTANCE Open);
+
+/*!
+  \brief Saves the content of the packet buffer to the file associated with current instance.
+  \param Open The NPF instance that creates the thread.
+
+  Used by NPF_DumpThread() and NPF_CloseDumpFile().
+*/
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
+
+/*!
+  \brief Writes a block of packets on the dump file.
+  \param FileObject The file object that will receive the packets.
+  \param Offset The offset in the file where the packets will be put.
+  \param Length The amount of bytes to write.
+  \param Mdl MDL mapping the memory buffer that will be written to disk.
+  \param IoStatusBlock Used by the function to return the status of the operation.
+  \return The status of the operation. See ntstatus.h in the DDK.
+
+  NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
+  of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
+*/
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+                                PLARGE_INTEGER Offset,
+                                ULONG Length,
+                                PMDL Mdl,
+                                PIO_STATUS_BLOCK IoStatusBlock);
+
+
+
+/*!
+  \brief Closes the dump file associated with an instance of the driver.
+  \param Open The NPF instance that closes the file.
+  \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
+
+/*!
+  \brief Returns the amount of bytes present in the packet buffer.
+  \param Open The NPF instance that closes the file.
+*/
+UINT GetBuffOccupation(POPEN_INSTANCE Open);
+
+/*!
+  \brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
+
+  \param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig 
+  events.
+  \param pNetPnPEvent Pointer to the PnP event
+
+  If there is a power state change, the driver is forced to resynchronize the global timer.
+  This hopefully avoids the synchronization issues caused by hibernation or standby.
+  This function is excluded from the NT4 driver, where PnP is not supported
+*/
+#ifdef NDIS50
+NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
+#endif
+
+/**
+ *  @}
+ */
+
+/**
+ *  @}
+ */
+
+#endif  /*main ifndef/define*/
diff --git a/drivers/net/npf/read.c b/drivers/net/npf/read.c
new file mode 100644 (file)
index 0000000..7541744
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+
+#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
+#define NdisZeroMappedMemory(Destination,Length)               RtlZeroMemory(Destination,Length)
+#define NdisReinitializePacket(Packet)                                                                         \
+{                                                                                                                                                      \
+       (Packet)->Private.Head = (PNDIS_BUFFER)NULL;                                                    \
+       (Packet)->Private.ValidCounts = FALSE;                                                                  \
+}
+
+
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+#include "tme.h"
+#include "time_calls.h"
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+//-------------------------------------------------------------------
+
+UINT GetBuffOccupation(POPEN_INSTANCE Open)
+{
+       UINT Occupation;
+
+       NdisAcquireSpinLock( &Open->BufLock );
+       
+       if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
+       else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
+
+       NdisReleaseSpinLock( &Open->BufLock );
+
+       return Occupation;
+}
+
+//-------------------------------------------------------------------
+
+void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT  *Bhead)
+{
+ULONG WordLength;
+UINT n,i,NBlocks;
+
+       WordLength=Length>>2;
+       NBlocks=WordLength>>8;
+       
+       for(n=0;n<NBlocks;n++){
+               for(i=0;i<256;i++){
+                       *((PULONG)Destination)++=*((PULONG)Source)++;
+               }
+       *Bhead+=1024;
+       }
+
+       n=WordLength-(NBlocks<<8);
+       for(i=0;i<n;i++){
+               *((PULONG)Destination)++=*((PULONG)Source)++;
+       }
+       *Bhead+=n<<2;
+       
+       n=Length-(WordLength<<2);
+       for(i=0;i<n;i++){
+               *((PUCHAR)Destination)++=*((PUCHAR)Source)++;
+       }
+       *Bhead+=n;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+    POPEN_INSTANCE      Open;
+    PIO_STACK_LOCATION  IrpSp;
+    PUCHAR                             packp;
+       ULONG                           Input_Buffer_Length;
+       UINT                            Thead;
+       UINT                            Ttail;
+       UINT                            TLastByte;
+       PUCHAR                          CurrBuff;
+       LARGE_INTEGER           CapTime;
+       LARGE_INTEGER           TimeFreq;
+       struct bpf_hdr          *header;
+       KIRQL                           Irql;
+       PUCHAR                          UserPointer;
+       ULONG                           bytecopy;
+       UINT                            SizeToCopy;
+       UINT                            PktLen;
+
+       IF_LOUD(DbgPrint("NPF: Read\n");)
+               
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    Open=IrpSp->FileObject->FsContext;
+       
+       if( Open->Bound == FALSE ){
+               // The Network adapter was removed.
+               EXIT_FAILURE(0);
+       }
+       
+       if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){  
+               // this instance is in dump mode, but the dump file has still not been opened
+               EXIT_FAILURE(0);
+       }
+
+       //See if the buffer is full enough to be copied
+       if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
+       {
+               //wait until some packets arrive or the timeout expires         
+               if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+                       KeWaitForSingleObject(Open->ReadEvent,
+                               UserRequest,
+                               KernelMode,
+                               TRUE,
+                               (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+               KeClearEvent(Open->ReadEvent);
+               
+               if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
+                       CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+                       
+                       //fill the bpf header for this packet
+                       header=(struct bpf_hdr*)CurrBuff;
+                       GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+                       if(Open->mode & MODE_DUMP){
+                               *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+                               header->bh_caplen=24;
+                               header->bh_datalen=24;
+                               Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+                       }
+                       else{
+                               header->bh_caplen=16;
+                               header->bh_datalen=16;
+                               header->bh_hdrlen=sizeof(struct bpf_hdr);
+                               Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+                       }
+
+                       *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+                       *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+                       
+                       //reset the countetrs
+                       NdisAcquireSpinLock( &Open->CountersLock );
+                       Open->Npackets.QuadPart=0;
+                       Open->Nbytes.QuadPart=0;
+                       NdisReleaseSpinLock( &Open->CountersLock );
+                       
+                       Irp->IoStatus.Status = STATUS_SUCCESS;
+                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                       
+                       return STATUS_SUCCESS;
+               }
+               
+               if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
+               {   
+                       PTME_DATA data;
+                       ULONG cnt;
+                       ULONG block_size;
+                       PUCHAR tmp;
+
+                       UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+                       
+                       if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
+                       {       
+                               EXIT_FAILURE(0);
+                       }
+                       
+                       header=(struct bpf_hdr*)UserPointer;
+       
+                       GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+                       
+                       header->bh_hdrlen=sizeof(struct bpf_hdr);
+                       
+
+                       //moves user memory pointer
+                       UserPointer+=sizeof(struct bpf_hdr);
+                       
+                       //calculus of data to be copied
+                       //if the user buffer is smaller than data to be copied,
+                       //only some data will be copied
+                       data=&Open->tme.block_data[Open->tme.active_read];
+
+                       if (data->last_read.tv_sec!=0)
+                               data->last_read=header->bh_tstamp;
+                       
+
+                       bytecopy=data->block_size*data->filled_blocks;
+                       
+                       if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
+                               bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
+                       else 
+                               bytecopy=data->filled_blocks;
+
+                       tmp=data->shared_memory_base_address;
+                       block_size=data->block_size;
+                       
+                       for (cnt=0;cnt<bytecopy;cnt++)
+                       {
+                               NdisAcquireSpinLock(&Open->machine_lock);
+                               RtlCopyMemory(UserPointer,tmp,block_size);
+                               NdisReleaseSpinLock(&Open->machine_lock);
+                               tmp+=block_size;
+                               UserPointer+=block_size;
+                       }
+                                               
+                       bytecopy*=block_size;
+
+                       header->bh_caplen=bytecopy;
+                       header->bh_datalen=header->bh_caplen;
+
+                       EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+               }
+
+               if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
+                       // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+                       // We must awake the application, returning an empty buffer.
+               {
+                       EXIT_SUCCESS(0);
+               }
+                               
+       }
+
+       //
+       // The buffer if full enough to be copied,
+       //
+       NdisAcquireSpinLock( &Open->BufLock );
+       
+       Thead = Open->Bhead;
+       Ttail = Open->Btail;
+       TLastByte = Open->BLastByte;
+
+       //get the address of the buffer
+       CurrBuff=Open->Buffer;
+       
+       NdisReleaseSpinLock( &Open->BufLock );
+       
+       Input_Buffer_Length=IrpSp->Parameters.Read.Length;
+       packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+       
+
+       //
+       //fill the application buffer
+       //
+       if(Ttail > Thead){      //first of all see if it we can copy all the buffer in one time
+               if((Ttail-Thead)<Input_Buffer_Length){
+                       KeResetEvent(Open->ReadEvent);
+
+                       PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
+                       EXIT_SUCCESS(Ttail-Thead);
+               }
+       }
+       else if((TLastByte - Thead) < Input_Buffer_Length){
+               PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
+
+               NdisAcquireSpinLock( &Open->BufLock );
+               
+               Open->BLastByte = Open->Btail;
+               Open->Bhead = 0;
+
+               NdisReleaseSpinLock( &Open->BufLock );
+               
+               EXIT_SUCCESS(TLastByte-Thead);
+       }
+       
+       //the buffer must be scannned to determine the number of bytes to copy
+       SizeToCopy = 0;
+       while(TRUE){
+               if(Thead + SizeToCopy == Ttail)
+                       break;
+
+               if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
+
+                       PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+                       // Reset the buffer
+                       NdisAcquireSpinLock( &Open->BufLock );
+                       (INT)Open->BLastByte = -1;
+                       Open->Bhead = 0;                        
+                       NdisReleaseSpinLock( &Open->BufLock );
+
+                       EXIT_SUCCESS(SizeToCopy);
+               }
+
+               // Get the size of the next packet in the buffer
+               PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
+
+               // The length is aligned to 32-bit boundary
+               PktLen = Packet_WORDALIGN(PktLen);
+
+               if(SizeToCopy + PktLen > Input_Buffer_Length)
+                       break;
+               
+               SizeToCopy += PktLen;
+       }
+
+       PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+       EXIT_SUCCESS(SizeToCopy);
+
+}
+
+//-------------------------------------------------------------------
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+                        IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
+                        IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+    POPEN_INSTANCE      Open;
+    PNDIS_PACKET        pPacketb;
+    ULONG               SizeToTransfer;
+    NDIS_STATUS         Status;
+    UINT                BytesTransfered;
+    ULONG               BufferLength;
+    PMDL                pMdl;
+       LARGE_INTEGER           CapTime;
+       LARGE_INTEGER           TimeFreq;
+       struct bpf_hdr          *header;
+       PUCHAR                          CurrBuff;
+       UINT                            Thead;
+       UINT                            Ttail;
+       UINT                            TLastByte;
+       UINT                            fres;
+       UINT                            maxbufspace;
+       USHORT                          NPFHdrSize;
+       UINT                            BufOccupation;
+       BOOLEAN                         ResetBuff = FALSE;
+
+    IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+    IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n", 
+       HeaderBufferSize,
+       LookAheadBuffer,
+       LookaheadBufferSize,
+       PacketSize);)
+
+       Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+       Open->Received++;               // Number of packets received by filter ++
+
+       BufOccupation = GetBuffOccupation(Open);        // Get the full buffer space
+
+       if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
+               // Heuristic that drops the packet also if it possibly fits in the buffer.
+               // It allows to avoid filtering in critical situations when CPU is very important.
+               Open->Dropped++;
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       NdisAcquireSpinLock(&Open->machine_lock);
+       
+       //
+       //Check if the lookahead buffer follows the mac header.
+       //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+       //executed on the packet.
+       //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+       //things like this) bpf_filter_with_2_buffers() is executed.
+       //
+       if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+               fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+                                                                          HeaderBuffer,
+                                                                          LookAheadBuffer,
+                                                                          HeaderBufferSize,
+                                                                          PacketSize+HeaderBufferSize,
+                                                                          LookaheadBufferSize+HeaderBufferSize,
+                                                                          &Open->mem_ex,
+                                                                          &Open->tme,
+                                                                          &G_Start_Time);
+       
+       
+       else 
+               if(Open->Filter != NULL)
+               {
+                       if (Open->bpfprogram != NULL)
+                       {
+                               fres=Open->Filter->Function(HeaderBuffer,
+                                                                       PacketSize+HeaderBufferSize,
+                                                                       LookaheadBufferSize+HeaderBufferSize);
+               
+                               // Restore the stack. 
+                               // I ignore the reason, but this instruction is needed only at kernel level
+#ifndef __GNUC__
+                               _asm add esp,12         
+#else
+                asm("add $0x12,%esp;");
+#endif
+                       }
+                       else
+                               fres = -1;
+               }
+               else
+                       fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+                               HeaderBuffer,
+                                               PacketSize+HeaderBufferSize,
+                                               LookaheadBufferSize+HeaderBufferSize,
+                                               &Open->mem_ex,
+                                               &Open->tme,
+                                               &G_Start_Time);
+
+       NdisReleaseSpinLock(&Open->machine_lock);
+       
+       if(Open->mode==MODE_MON)
+       // we are in monitor mode
+       {
+               if (fres==1) 
+                       KeSetEvent(Open->ReadEvent,0,FALSE);
+               return NDIS_STATUS_NOT_ACCEPTED;
+
+       }
+
+       if(fres==0)
+               // Packet not accepted by the filter, ignore it.
+               return NDIS_STATUS_NOT_ACCEPTED;
+
+       //if the filter returns -1 the whole packet must be accepted
+       if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize; 
+
+       if(Open->mode & MODE_STAT){
+       // we are in statistics mode
+               NdisAcquireSpinLock( &Open->CountersLock );
+
+               Open->Npackets.QuadPart++;
+               
+               if(PacketSize+HeaderBufferSize<60)
+                       Open->Nbytes.QuadPart+=60;
+               else
+                       Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+               // add preamble+SFD+FCS to the packet
+               // these values must be considered because are not part of the packet received from NDIS
+               Open->Nbytes.QuadPart+=12;
+
+               NdisReleaseSpinLock( &Open->CountersLock );
+               
+               if(!(Open->mode & MODE_DUMP)){
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+       }
+
+       if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
+       
+       if(Open->mode & MODE_DUMP && Open->MaxDumpPacks &&      (UINT)Open->Accepted > Open->MaxDumpPacks){
+               // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+               Open->DumpLimitReached = TRUE; // This stops the thread
+               // Awake the dump thread
+               NdisSetEvent(&Open->DumpEvent);
+
+               // Awake the application
+               KeSetEvent(Open->ReadEvent,0,FALSE);
+
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       // Calculate the correct size for the header associated with the packet
+       NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
+       NdisAcquireSpinLock( &Open->BufLock );
+
+       Thead=Open->Bhead;
+       Ttail=Open->Btail;
+       TLastByte = Open->BLastByte;
+
+       NdisReleaseSpinLock( &Open->BufLock );
+       
+       maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
+
+       if(Ttail+maxbufspace >= Open->BufSize){
+               if(Thead <= maxbufspace)
+               {
+                       Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               else{
+                       Ttail=0;
+                       ResetBuff = TRUE;
+               }
+       }
+       
+       if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
+       {
+               Open->Dropped++;
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+       
+       CurrBuff=Open->Buffer+Ttail;
+
+       if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+       {
+               //  Allocate an MDL to map the portion of the buffer following the header
+               pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
+                       maxbufspace,
+                       FALSE,
+                       FALSE,
+                       NULL);
+
+               if (pMdl == NULL)
+               {
+                       // Unable to map the memory: packet lost
+                       IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
+                               Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               MmBuildMdlForNonPagedPool(pMdl);
+               
+               //allocate the packet from NDIS
+               NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
+               if (Status != NDIS_STATUS_SUCCESS)
+               {
+                       IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+                       IoFreeMdl(pMdl);
+                       Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               //link the buffer to the packet
+               NdisChainBufferAtFront(pPacketb,pMdl);
+               
+               BufferLength=fres-HeaderBufferSize;
+               //Find out how much to transfer
+               SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
+               
+               //copy the ethernet header into buffer
+               NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
+               
+               //Copy the look ahead buffer
+               if(LookaheadBufferSize)
+               {
+                       NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
+                               LookAheadBuffer, 
+                               (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
+                       
+                       SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
+                               SizeToTransfer - LookaheadBufferSize : 0;
+               }
+               
+               Open->TransferMdl=pMdl;
+               
+               if(SizeToTransfer)
+               {
+                       //Call the Mac to transfer the packet
+                       NdisTransferData(&Status,
+                               Open->AdapterHandle,
+                               MacReceiveContext,
+                               LookaheadBufferSize,
+                               SizeToTransfer,
+                               pPacketb,
+                               &BytesTransfered);
+               }
+               else{
+                       BytesTransfered = 0;
+               }
+               
+       }
+       else
+       {
+       // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
+       // This allows us to avoid the allocation of the MDL and the NDIS packet as well
+       RtlCopyMemory((CurrBuff) + NPFHdrSize,
+               HeaderBuffer,
+               HeaderBufferSize + LookaheadBufferSize);
+
+               BytesTransfered = 0;
+
+               Open->TransferMdl = NULL;
+               Status = NDIS_STATUS_SUCCESS;
+       }
+
+       if (Status != NDIS_STATUS_FAILURE)
+       {
+
+               Open->Accepted++;               // Increase the accepted packets counter
+
+               if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
+                       fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
+               
+               //
+               // Build the header
+               //
+               header=(struct bpf_hdr*)CurrBuff;
+               GET_TIME(&header->bh_tstamp,&G_Start_Time);
+               header->bh_caplen=fres;
+               header->bh_datalen=PacketSize+HeaderBufferSize;
+               if(Open->mode==MODE_CAPT){
+                       header->bh_hdrlen=NPFHdrSize;
+                       // Don't align if the packet goes to disk
+                       Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
+               }
+               else
+                       Ttail+=fres+NPFHdrSize;
+               
+               //update the buffer     
+               NdisAcquireSpinLock( &Open->BufLock );
+               
+               if(ResetBuff){
+                       Open->BLastByte = Open->Btail;
+               }
+               Open->Btail=Ttail;
+               
+               NdisReleaseSpinLock( &Open->BufLock );
+       }
+
+       if (Status != NDIS_STATUS_PENDING){
+
+               if( Open->TransferMdl != NULL)
+                       // Complete the request and free the buffers
+                       NPF_TransferDataComplete(Open,pPacketb,Status,fres);
+               else{
+                       // Unfreeze the consumer
+                       if(GetBuffOccupation(Open)>Open->MinToCopy){
+                               if(Open->mode & MODE_DUMP){
+                                       NdisSetEvent(&Open->DumpEvent);
+                               }
+                               else
+                                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+                       }
+                       
+               }
+       }
+       
+       return NDIS_STATUS_SUCCESS;
+       
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+                                 IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+    POPEN_INSTANCE      Open;
+
+    IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+    
+       Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+       IoFreeMdl(Open->TransferMdl);
+       //recylcle the packet
+       NdisReinitializePacket(pPacket);
+       //Put the packet on the free queue
+       NdisFreePacket(pPacket);
+       // Unfreeze the consumer
+       if(GetBuffOccupation(Open)>Open->MinToCopy){
+               if(Open->mode & MODE_DUMP){
+                       NdisSetEvent(&Open->DumpEvent);
+               }
+               else
+                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+       }
+       return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+    IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+    return;
+}
diff --git a/drivers/net/npf/resource.h b/drivers/net/npf/resource.h
new file mode 100644 (file)
index 0000000..d704eca
--- /dev/null
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by NPF.RC
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/drivers/net/npf/tcp_session.c b/drivers/net/npf/tcp_session.c
new file mode 100644 (file)
index 0000000..4eb6410
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/tcp_session.h>
+#else
+#include <tme/tme.h>
+#include <tme/tcp_session.h>
+#endif
+
+#endif
+
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+
+{
+
+       uint32 next_status;  
+       uint32 direction=ULONG_AT(mem_data,12);
+       uint8 flags=mem_ex->buffer[25];
+       tcp_data *session=(tcp_data*)(block+data->key_len*4);
+       
+       session->last_timestamp=session->timestamp_block;
+       session->timestamp_block.tv_sec=0x7fffffff;
+       
+       if (direction==session->direction)
+       {
+               session->pkts_cln_to_srv++;
+               session->bytes_cln_to_srv+=pkt_size;
+       }
+       else
+       {
+               session->pkts_srv_to_cln++;
+               session->bytes_srv_to_cln+=pkt_size;
+       }
+       /* we use only thes four flags, we don't need PSH or URG */
+       flags&=(ACK|FIN|SYN|RST);
+       
+       switch (session->status)
+       {
+       case ERROR_TCP:
+               next_status=ERROR_TCP;
+               break;
+       
+       case UNKNOWN:
+               if (flags==SYN)
+               {
+                       if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
+                       {
+
+                               next_status=ERROR_TCP;
+                               break;
+                       }
+                       next_status=SYN_RCV;
+                       session->syn_timestamp=session->last_timestamp;
+
+                       session->direction=direction;
+                       session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+               }
+               else
+                       next_status=UNKNOWN;
+               break;
+
+       case SYN_RCV:
+               if ((flags&RST)&&(direction!=session->direction))
+               {
+                       next_status=CLOSED_RST;
+                       break;
+               }
+               if ((flags==SYN)&&(direction==session->direction))
+               {       /* two syns... */
+                       next_status=SYN_RCV;
+                       session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+                       break;
+               }
+                                               
+               if ((flags==(SYN|ACK))&&(direction!=session->direction))
+               {               
+                       if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
+                       {
+                               next_status=ERROR_TCP;
+                               break;
+                       }
+                       next_status=SYN_ACK_RCV;
+                       
+                       session->syn_ack_timestamp=session->last_timestamp;
+
+                       session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
+                       session->ack_cln=session->seq_n_0_cln+1;
+               }
+               else
+               {
+                       next_status=ERROR_TCP;
+               }
+               break;
+
+       case SYN_ACK_RCV:
+               if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
+               {
+                       next_status=CLOSED_RST;
+                       session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
+                       break;
+               }
+               
+               if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
+               {
+                       if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
+                       {
+                               next_status=ERROR_TCP;
+                               break;
+                       }
+                       next_status=ESTABLISHED;
+                       session->ack_srv=session->seq_n_0_srv+1;
+                       break;
+               }
+               if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
+               {
+                       next_status=SYN_ACK_RCV;
+                       break;
+               }
+
+               next_status=ERROR_TCP;
+               break;
+       
+       case ESTABLISHED:
+               if (flags&SYN)
+               {
+                       if ((flags&ACK)&&
+                               (direction!=session->direction)&&
+                               ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
+                               )
+                       {       /* SYN_ACK duplicato */
+                               next_status=ESTABLISHED;
+                               break;
+                       }
+                       
+                       if ((!(flags&ACK))&&
+                               (direction==session->direction)&&
+                               (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
+                               (ULONG_AT(mem_ex->buffer,20)==0)
+                               )
+                       {       /* syn duplicato */
+                               next_status=ESTABLISHED;
+                               break;
+                       }
+                                               
+                       next_status=ERROR_TCP;
+                       break;
+               }
+               if (flags&ACK)
+                       if (direction==session->direction)
+                       {
+                               uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+                               if (new_ack-session->ack_srv<MAX_WINDOW)
+                                       session->ack_srv=new_ack;
+                       }
+                       else
+                       {
+                               uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+                               if (new_ack-session->ack_cln<MAX_WINDOW)
+                                       session->ack_cln=new_ack;
+                       }
+               if (flags&RST)
+               {
+                       next_status=CLOSED_RST;
+                       break;
+               }
+               if (flags&FIN)
+                       if (direction==session->direction)
+                       {   /* an hack to make all things work */
+                               session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+                               next_status=FIN_CLN_RCV;
+                               break;
+                       }
+                       else
+                       {
+                               session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+                               next_status=FIN_SRV_RCV;
+                               break;
+                       }
+               next_status=ESTABLISHED;
+               break;
+       
+       case CLOSED_RST:
+               next_status=CLOSED_RST;
+               break;
+       
+       case FIN_SRV_RCV:       
+               if (flags&SYN)
+               {
+                       next_status=ERROR_TCP;
+                       break;
+               }
+                       
+               next_status=FIN_SRV_RCV;
+               
+               if (flags&ACK)
+               {
+                       uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+                       if (direction!=session->direction)
+                               if ((new_ack-session->ack_cln)<MAX_WINDOW)
+                                       session->ack_cln=new_ack;
+               }
+               
+               if (flags&RST)
+                       next_status=CLOSED_RST;
+               else
+                       if ((flags&FIN)&&(direction==session->direction))
+                       {
+                               session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+                               next_status=CLOSED_FIN;
+                       }
+
+               break;
+
+       case FIN_CLN_RCV:
+               if (flags&SYN)
+               {
+                       next_status=ERROR_TCP;
+                       break;
+               }
+                       
+               next_status=FIN_CLN_RCV;
+               
+               if (flags&ACK)
+               {
+                       uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+                       if (direction==session->direction)
+                               if (new_ack-session->ack_srv<MAX_WINDOW)
+                                       session->ack_srv=new_ack;
+               }
+               
+               if (flags&RST)
+                       next_status=CLOSED_RST;
+               else
+                       if ((flags&FIN)&&(direction!=session->direction))
+                       {
+                               session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+                               next_status=CLOSED_FIN;
+                       }
+
+               break;
+
+       case CLOSED_FIN:
+                       next_status=CLOSED_FIN;
+               break;
+       default:
+               next_status=ERROR_TCP;
+
+       }
+
+       session->status=next_status;
+       
+       if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
+               session->timestamp_block=session->last_timestamp;
+       
+       return TME_SUCCESS;
+}
\ No newline at end of file
diff --git a/drivers/net/npf/tcp_session.h b/drivers/net/npf/tcp_session.h
new file mode 100644 (file)
index 0000000..6262e79
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define UNKNOWN         0
+#define SYN_RCV         1
+#define SYN_ACK_RCV     2
+#define ESTABLISHED     3
+#define CLOSED_RST      4
+#define FIN_CLN_RCV     5
+#define FIN_SRV_RCV     6
+#define CLOSED_FIN      7
+#define ERROR_TCP       8
+#define FIRST_IS_CLN    0
+#define FIRST_IS_SRV    0xffffffff
+#define FIN_CLN         1
+#define FIN_SRV         2
+
+#define MAX_WINDOW 65536
+
+typedef struct __tcp_data
+{
+    struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
+    struct timeval syn_timestamp;
+    struct timeval last_timestamp;
+    struct timeval syn_ack_timestamp;
+    uint32 direction;
+    uint32 seq_n_0_srv;
+    uint32 seq_n_0_cln;
+    uint32 ack_srv; /* acknowledge of (data sent by server) */
+    uint32 ack_cln; /* acknowledge of (data sent by client) */
+    uint32 status;
+    uint32 pkts_cln_to_srv;
+    uint32 pkts_srv_to_cln;
+    uint32 bytes_srv_to_cln;
+    uint32 bytes_cln_to_srv;
+    uint32 close_state;
+}
+     tcp_data;
+
+#define FIN     1
+#define SYN     2
+#define RST     4
+#define PSH     8
+#define ACK     16
+#define URG     32
+
+#define TCP_SESSION                     0x00000800
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/time_calls.c b/drivers/net/npf/time_calls.c
new file mode 100644 (file)
index 0000000..0e42697
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "win_bpf.h"
+#include "time_calls.h"
+
+
+void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+       data->reference = 0;
+       data->start.tv_sec = 0;
+       data->start.tv_usec = 0;
+}
+
+#ifdef KQPC_TS
+
+/* KeQueryPerformanceCounter TimeStamps */
+
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+       struct timeval tmp;
+       LARGE_INTEGER SystemTime;
+       LARGE_INTEGER i;
+       ULONG tmp2;
+       LARGE_INTEGER TimeFreq,PTime;
+
+       if (data->reference!=0)
+               return;
+       
+       // get the absolute value of the system boot time.   
+       PTime=KeQueryPerformanceCounter(&TimeFreq);
+       KeQuerySystemTime(&SystemTime);
+#ifndef __GNUC__
+       tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
+       tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
+       tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+       tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+#else
+    // TODO FIXME:
+#endif
+       if (tmp.tv_usec<0) {
+               tmp.tv_sec--;
+               tmp.tv_usec+=1000000;
+       }
+       data->start=tmp;
+       data->reference=1;
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+       dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+       LARGE_INTEGER PTime, TimeFreq;
+       LONG tmp;
+
+       PTime=KeQueryPerformanceCounter(&TimeFreq);
+#ifndef __GNUC__
+       tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+       dst->tv_sec=data->start.tv_sec+tmp;
+       dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+#else
+    // TODO FIXME:
+#endif
+       if (dst->tv_usec>=1000000) {
+               dst->tv_sec++;
+               dst->tv_usec-=1000000;
+       }
+}
+
+#else /*KQPC_TS*/
+
+/*RDTSC timestamps*/
+
+/* callers must be at IRQL=PASSIVE_LEVEL */
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+       struct timeval tmp;
+       LARGE_INTEGER system_time;
+       ULONGLONG curr_ticks;
+       KIRQL old;
+       LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+       ULONGLONG start_ticks,stop_ticks;
+       ULONGLONG delta,delta2;
+       KEVENT event;
+       LARGE_INTEGER i;
+       ULONGLONG reference;
+
+       if (data->reference!=0)
+               return;
+       
+       KeInitializeEvent(&event,NotificationEvent,FALSE);
+       i.QuadPart=-3500000;
+       KeRaiseIrql(HIGH_LEVEL,&old);
+       start_kqpc=KeQueryPerformanceCounter(&start_freq);
+#ifndef __GNUC__
+       __asm
+       {
+               push eax
+               push edx
+               push ecx
+               rdtsc
+               lea ecx, start_ticks
+               mov [ecx+4], edx
+               mov [ecx], eax
+               pop ecx
+               pop edx
+               pop eax
+       }
+#else
+       asm("push %%eax;"
+               "push %%edx;"
+               "push %%ecx;"
+               "rdtsc;"
+               "lea %0,%%ecx;"
+               "mov %%edx,(%%ecx+4);"
+               "mov %%eax,(%%ecx);"
+               "pop %%ecx;"
+               "pop %%edx;"
+               "pop %%eax;"
+        :"=c"(start_ticks): );
+#endif
+       KeLowerIrql(old);
+    KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+       KeRaiseIrql(HIGH_LEVEL,&old);
+       stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+#ifndef __GNUC__
+       __asm
+       {
+               push eax
+               push edx
+               push ecx
+               rdtsc
+               lea ecx, stop_ticks
+               mov [ecx+4], edx
+               mov [ecx], eax
+               pop ecx
+               pop edx
+               pop eax
+       }
+#else
+       asm("push %%eax;"
+               "push %%edx;"
+               "push %%ecx;"
+               "rdtsc;"
+               "lea %0,%%ecx;"
+               "mov %%edx,(%%ecx+4);"
+               "mov %%eax,(%%ecx);"
+               "pop %%ecx;"
+               "pop %%edx;"
+               "pop %%eax;"
+        :"=c"(stop_ticks): );
+#endif
+       KeLowerIrql(old);
+       delta=stop_ticks-start_ticks;
+       delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+       if (delta>10000000000) {
+               delta/=16;
+               delta2/=16;
+       }
+       reference=delta*(start_freq.QuadPart)/delta2;
+       data->reference=reference/1000;
+       if (reference%1000>500) 
+               data->reference++;
+       data->reference*=1000;
+       reference=data->reference;
+       KeQuerySystemTime(&system_time);
+#ifndef __GNUC__
+       __asm
+       {
+               push eax
+               push edx
+               push ecx
+               rdtsc
+               lea ecx, curr_ticks
+               mov [ecx+4], edx
+               mov [ecx], eax
+               pop ecx
+               pop edx
+               pop eax
+       }
+#else
+       asm("push %%eax;"
+               "push %%edx;"
+               "push %%ecx;"
+               "rdtsc;"
+               "lea %0,%%ecx;"
+               "mov %%edx,(%%ecx+4);"
+               "mov %%eax,(%%ecx);"
+               "pop %%ecx;"
+               "pop %%edx;"
+               "pop %%eax;"
+        :"=c"(curr_ticks): );
+#endif
+       tmp.tv_sec=-(LONG)(curr_ticks/reference);
+       tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+       system_time.QuadPart-=116444736000000000;
+       tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+       tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+       if (tmp.tv_usec<0) {
+               tmp.tv_sec--;
+               tmp.tv_usec+=1000000;
+       }
+       data->start=tmp;
+       IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+       dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+       ULONGLONG tmp;
+#ifndef __GNUC__
+       __asm
+       {
+               push eax
+               push edx
+               push ecx
+               rdtsc
+               lea ecx, tmp
+               mov [ecx+4], edx
+               mov [ecx], eax
+               pop ecx
+               pop edx
+               pop eax
+       }
+#else
+       asm("push %%eax;"
+               "push %%edx;"
+               "push %%ecx;"
+               "rdtsc;"
+               "lea %0,%%ecx;"
+               "mov %%edx,(%%ecx+4);"
+               "mov %%eax,(%%ecx);"
+               "pop %%ecx;"
+               "pop %%edx;"
+               "pop %%eax;"
+        :"=c"(tmp): );
+#endif
+       if (data->reference==0) {
+               return;
+       }
+       dst->tv_sec=(LONG)(tmp/data->reference);
+       dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+       dst->tv_sec+=data->start.tv_sec;
+       dst->tv_usec+=data->start.tv_usec;
+       if (dst->tv_usec>=1000000) {
+               dst->tv_sec++;
+               dst->tv_usec-=1000000;
+       }
+}
+
+#endif /*KQPC_TS*/
diff --git a/drivers/net/npf/time_calls.h b/drivers/net/npf/time_calls.h
new file mode 100644 (file)
index 0000000..04731cf
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+
+/*!
+  \brief A microsecond precise timestamp.
+
+  included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet. 
+*/
+
+struct timeval {
+        long    tv_sec;         ///< seconds
+        long    tv_usec;        ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv {
+    ULONGLONG reference;
+    struct timeval start;
+};
+
+#ifdef __GNUC__
+
+void TIME_DESYNCHRONIZE(struct time_conv *data);
+VOID TIME_SYNCHRONIZE(struct time_conv *data);
+void FORCE_TIME(struct timeval *src, struct time_conv *dest);
+void GET_TIME(struct timeval *dst, struct time_conv *data);
+
+#else /* __GNUC__ */
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+    data->reference = 0;
+    data->start.tv_sec = 0;
+    data->start.tv_usec = 0;
+}
+
+#ifdef KQPC_TS
+
+/* KeQueryPerformanceCounter TimeStamps */
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+    struct timeval tmp;
+    LARGE_INTEGER SystemTime;
+    LARGE_INTEGER i;
+    ULONG tmp2;
+    LARGE_INTEGER TimeFreq,PTime;
+
+    if (data->reference!=0)
+        return;
+    
+    // get the absolute value of the system boot time.   
+    PTime=KeQueryPerformanceCounter(&TimeFreq);
+    KeQuerySystemTime(&SystemTime);
+    tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
+    tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
+    tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+    tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+    if (tmp.tv_usec<0) {
+        tmp.tv_sec--;
+        tmp.tv_usec+=1000000;
+    }
+    data->start=tmp;
+    data->reference=1;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+    LARGE_INTEGER PTime, TimeFreq;
+    LONG tmp;
+
+    PTime=KeQueryPerformanceCounter(&TimeFreq);
+    tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+    dst->tv_sec=data->start.tv_sec+tmp;
+    dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+    if (dst->tv_usec>=1000000) {
+        dst->tv_sec++;
+        dst->tv_usec-=1000000;
+    }
+}
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+    dest->start=*src;
+}
+
+#else
+
+/*RDTSC timestamps*/
+
+/* callers must be at IRQL=PASSIVE_LEVEL */
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+    struct timeval tmp;
+    LARGE_INTEGER system_time;
+    ULONGLONG curr_ticks;
+    KIRQL old;
+    LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+    ULONGLONG start_ticks,stop_ticks;
+    ULONGLONG delta,delta2;
+    KEVENT event;
+    LARGE_INTEGER i;
+    ULONGLONG reference;
+
+    if (data->reference!=0)
+        return;
+    
+    KeInitializeEvent(&event,NotificationEvent,FALSE);
+    i.QuadPart=-3500000;
+    KeRaiseIrql(HIGH_LEVEL,&old);
+    start_kqpc=KeQueryPerformanceCounter(&start_freq);
+#ifndef __GNUC__
+    __asm
+    {
+        push eax
+        push edx
+        push ecx
+        rdtsc
+        lea ecx, start_ticks
+        mov [ecx+4], edx
+        mov [ecx], eax
+        pop ecx
+        pop edx
+        pop eax
+    }
+#else
+#endif
+    KeLowerIrql(old);
+    KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+    KeRaiseIrql(HIGH_LEVEL,&old);
+    stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+#ifndef __GNUC__
+    __asm
+    {
+        push eax
+        push edx
+        push ecx
+        rdtsc
+        lea ecx, stop_ticks
+        mov [ecx+4], edx
+        mov [ecx], eax
+        pop ecx
+        pop edx
+        pop eax
+    }
+#else
+#endif
+    KeLowerIrql(old);
+    delta=stop_ticks-start_ticks;
+    delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+    if (delta>10000000000) {
+        delta/=16;
+        delta2/=16;
+    }
+    reference=delta*(start_freq.QuadPart)/delta2;
+    data->reference=reference/1000;
+    if (reference%1000>500) 
+        data->reference++;
+    data->reference*=1000;
+    reference=data->reference;
+    KeQuerySystemTime(&system_time);
+#ifndef __GNUC__
+    __asm
+    {
+        push eax
+        push edx
+        push ecx
+        rdtsc
+        lea ecx, curr_ticks
+        mov [ecx+4], edx
+        mov [ecx], eax
+        pop ecx
+        pop edx
+        pop eax
+    }
+#else
+#endif
+    tmp.tv_sec=-(LONG)(curr_ticks/reference);
+    tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+    system_time.QuadPart-=116444736000000000;
+    tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+    tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+    if (tmp.tv_usec<0) {
+        tmp.tv_sec--;
+        tmp.tv_usec+=1000000;
+    }
+    data->start=tmp;
+    IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+    dest->start=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+    ULONGLONG tmp;
+#ifndef __GNUC__
+    __asm
+    {
+        push eax
+        push edx
+        push ecx
+        rdtsc
+        lea ecx, tmp
+        mov [ecx+4], edx
+        mov [ecx], eax
+        pop ecx
+        pop edx
+        pop eax
+    }
+#else
+#endif
+    if (data->reference==0) {
+        return;
+    }
+    dst->tv_sec=(LONG)(tmp/data->reference);
+    dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+    dst->tv_sec+=data->start.tv_sec;
+    dst->tv_usec+=data->start.tv_usec;
+    if (dst->tv_usec>=1000000) {
+        dst->tv_sec++;
+        dst->tv_usec-=1000000;
+    }
+}
+
+#endif /*KQPC_TS*/
+
+#endif /*WIN_NT_DRIVER*/
+
+#endif /* __GNUC__ */
+
+#endif /*_time_calls*/
diff --git a/drivers/net/npf/tme.c b/drivers/net/npf/tme.c
new file mode 100644 (file)
index 0000000..87ed7dc
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/tme.h>
+#endif
+
+/* resizes extended memory */ 
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
+{
+       uint8 *tmp;
+       
+       if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
+               return TME_ERROR;  /* awfully never reached!!!! */
+
+       tmp=mem_ex->buffer;
+       mem_ex->buffer=NULL;
+       FREE_MEMORY(tmp);
+
+       ALLOCATE_MEMORY(tmp,uint8,size);
+       if (tmp==NULL)
+               return TME_ERROR; /* no memory */
+                       
+       mem_ex->size=size;
+       mem_ex->buffer=tmp;
+       return TME_SUCCESS;
+
+}
+
+/* activates a block of the TME */
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block)  
+{
+
+       if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+               return TME_ERROR;
+       tme->active=block;
+       tme->working=block;
+       return TME_SUCCESS;
+
+}
+
+/* simply inserts default values in a TME block      */
+/* it DOESN'T initialize the block in the core!!     */
+/* FIXME default values are defined at compile time, */
+/* it will be useful to store them in the registry   */
+uint32 init_tme_block(TME_CORE *tme, uint32 block)
+{
+       
+       TME_DATA *data;
+       if (block>=MAX_TME_DATA_BLOCKS)
+               return TME_ERROR;
+       data=&(tme->block_data[block]);
+       tme->working=block;
+
+       ZERO_MEMORY(data,sizeof(TME_DATA));
+
+       /* entries in LUT     */
+       data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
+       /* blocks             */
+       data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
+       /* block size         */
+       data->block_size=TME_BLOCK_SIZE_DEFAULT;
+       /* lookup function    */
+       data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
+       /* rehashing value    */
+       data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
+       /* out lut function   */
+       data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
+       /* default function   */
+       data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
+       /* extra segment size */
+       data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
+       
+
+       data->enable_deletion=FALSE;
+       data->last_read.tv_sec=0;
+       data->last_read.tv_usec=0;
+       return TME_SUCCESS;
+
+}
+/* it validates a TME block and          */
+/* (on OK) inserts the block in the core */
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
+{
+       uint32 required_memory;
+       uint8 *base=mem_ex_offset+mem_ex->buffer;
+       TME_DATA *data;
+       
+       /* FIXME soluzione un po' posticcia... */
+       if (mem_ex_offset==0)
+               return TME_ERROR;
+
+       if (block>=MAX_TME_DATA_BLOCKS)
+               return TME_ERROR;
+       data=&tme->block_data[block];
+       
+       if (data->lut_entries==0)
+               return TME_ERROR;
+
+       if (data->key_len==0)
+               return TME_ERROR;
+
+       if (data->shared_memory_blocks==0)
+               return TME_ERROR;
+
+       if (data->block_size==0)
+               return TME_ERROR;
+
+       /* checks if the lookup function is valid       */
+       if (data->lookup_code==NULL)
+               return TME_ERROR;
+
+       /* checks if the out lut exec function is valid */
+       if (exec_fcn_mapper(data->out_lut_exec)==NULL)
+               return TME_ERROR;
+
+       /* checks if the default exec function is valid */
+       if (exec_fcn_mapper(data->default_exec)==NULL)
+               return TME_ERROR;
+
+       /* let's calculate memory needed                */
+       required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
+       required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
+       required_memory+=data->extra_segment_size; /*extra segment*/
+
+       if (required_memory>(mem_ex->size-mem_ex_offset))
+               return TME_ERROR;  /*not enough memory*/
+
+       /* the TME block can be initialized             */
+       ZERO_MEMORY(base,required_memory);
+       
+       data->lut_base_address=base;
+       
+       data->shared_memory_base_address=
+               data->lut_base_address+
+               data->lut_entries*sizeof(RECORD);
+
+       data->extra_segment_base_address=
+               data->shared_memory_base_address+
+               data->block_size*data->shared_memory_blocks;
+       data->filled_blocks=1;
+       VALIDATE(tme->validated_blocks,block);
+       tme->active=block;
+       tme->working=block;
+       return TME_SUCCESS;
+}
+                                                                                                                        
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
+{
+       if (tme->active==TME_NONE_ACTIVE)
+               return TME_FALSE;
+       
+       return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
+{
+       
+       exec_fcn tmp;
+       TME_DATA *data;
+       uint8 *block;
+       uint8 *mem_data;
+
+       if (tme->active==TME_NONE_ACTIVE)
+               return TME_ERROR;
+
+       data=&tme->block_data[tme->active];
+       
+       if (data->last_found==NULL)
+       {       /*out lut exec */
+               tmp=exec_fcn_mapper(data->out_lut_exec);
+               block=data->shared_memory_base_address;
+       }
+       else
+       {   /*checks if last_found is valid */
+               if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
+                       return TME_ERROR;
+               else
+               {
+                       tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
+                       if (tmp==NULL)
+                               return TME_ERROR;
+                       block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
+                       if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
+                               return TME_ERROR;
+               }
+       }
+       
+       if (offset>=mem_ex->size)
+               return TME_ERROR;
+       
+       mem_data=mem_ex->buffer+offset;
+       
+       return tmp(block,pkt_size,data,mem_ex,mem_data);
+}
+
+/*resets all the TME core*/
+uint32 reset_tme(TME_CORE *tme)
+{
+       if (tme==NULL)
+               return TME_ERROR;
+       ZERO_MEMORY(tme, sizeof(TME_CORE));     
+       return TME_SUCCESS;
+}
+       
+/* returns a register value of the active TME block   */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
+{
+       switch(rgstr)
+       {
+       case TME_LUT_ENTRIES:
+               *rval=data->lut_entries;
+               return TME_SUCCESS;
+       case TME_MAX_FILL_STATE:
+               *rval=data->max_fill_state;
+               return TME_SUCCESS;
+       case TME_REHASHING_VALUE:
+               *rval=data->rehashing_value;
+               return TME_SUCCESS;
+       case TME_KEY_LEN:
+               *rval=data->key_len;
+               return TME_SUCCESS;
+       case TME_SHARED_MEMORY_BLOCKS:
+               *rval=data->shared_memory_blocks;
+               return TME_SUCCESS;
+       case TME_FILLED_ENTRIES:
+               *rval=data->filled_entries;
+               return TME_SUCCESS;
+       case TME_BLOCK_SIZE:
+               *rval=data->block_size;
+               return TME_SUCCESS;
+       case TME_EXTRA_SEGMENT_SIZE:
+               *rval=data->extra_segment_size;
+               return TME_SUCCESS;
+       case TME_FILLED_BLOCKS:
+               *rval=data->filled_blocks;
+               return TME_SUCCESS;
+       case TME_DEFAULT_EXEC:
+               *rval=data->default_exec;
+               return TME_SUCCESS;
+       case TME_OUT_LUT_EXEC:
+               *rval=data->out_lut_exec;
+               return TME_SUCCESS;
+       case TME_SHARED_MEMORY_BASE_ADDRESS:
+               *rval=data->shared_memory_base_address-mem_ex->buffer;
+               return TME_SUCCESS;
+       case TME_LUT_BASE_ADDRESS:
+               *rval=data->lut_base_address-mem_ex->buffer;
+               return TME_SUCCESS;
+       case TME_EXTRA_SEGMENT_BASE_ADDRESS:
+               *rval=data->extra_segment_base_address-mem_ex->buffer;
+               return TME_SUCCESS;
+       case TME_LAST_FOUND_BLOCK:
+               if (data->last_found==NULL)
+                       *rval=0;
+               else
+                       *rval=data->last_found-mem_ex->buffer;
+               return TME_SUCCESS;
+
+       default:
+               return TME_ERROR;
+       }
+}
+
+/* sets a register value in the active block          */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
+{      /* very very very dangerous!!!!!!!!!!! */
+       lut_fcn tmp;
+       switch(rgstr)
+       {
+       case TME_MAX_FILL_STATE:
+               data->max_fill_state=value;
+               return TME_SUCCESS;
+       case TME_REHASHING_VALUE:
+               data->rehashing_value=value;
+               return TME_SUCCESS;
+       case TME_FILLED_ENTRIES: 
+               data->filled_entries=value;
+               return TME_SUCCESS;
+       case TME_FILLED_BLOCKS:  
+               if (value<=data->shared_memory_blocks)
+               {
+                       data->filled_blocks=value;
+                       return TME_SUCCESS;
+               }
+               else
+                       return TME_ERROR;
+       case TME_DEFAULT_EXEC:  
+               data->default_exec=value;
+               return TME_SUCCESS;
+       case TME_OUT_LUT_EXEC:
+               data->out_lut_exec=value;
+               return TME_SUCCESS;
+       case TME_LOOKUP_CODE:
+               tmp=lut_fcn_mapper(value);
+               if (tmp==NULL)
+                       return TME_ERROR;
+               else
+                       data->lookup_code=tmp;
+               return TME_SUCCESS;
+       default:
+               break;
+       }
+
+       if (init)
+               switch (rgstr)
+               {
+
+               case TME_LUT_ENTRIES: 
+                       data->lut_entries=value;
+                       return TME_SUCCESS;
+               case TME_KEY_LEN: 
+                       data->key_len=value;
+                       return TME_SUCCESS;
+               case TME_SHARED_MEMORY_BLOCKS: 
+                       data->shared_memory_blocks=value;
+                       return TME_SUCCESS;
+               case TME_BLOCK_SIZE:  
+                       data->block_size=value;
+                       return TME_SUCCESS;
+               case TME_EXTRA_SEGMENT_SIZE: 
+                       data->extra_segment_size=value;
+                       return TME_SUCCESS;
+               default:
+                       return TME_ERROR;
+               }
+       else
+               return TME_ERROR;
+
+}
+
+/* chooses the TME block for read */
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)  
+{
+
+       if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+               return TME_ERROR;
+       tme->active_read=block;
+       return TME_SUCCESS;
+
+}
+
+/* chooses if the autodeletion must be used */
+uint32 set_autodeletion(TME_DATA *data, uint32 value)
+{
+       if (value==0)  /* no autodeletion */
+               data->enable_deletion=FALSE;
+       else
+               data->enable_deletion=TRUE;
+
+       return TME_SUCCESS;
+}
\ No newline at end of file
diff --git a/drivers/net/npf/tme.h b/drivers/net/npf/tme.h
new file mode 100644 (file)
index 0000000..4140f9f
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+
+#include "ntddk.h"
+#include "memory_t.h"
+#include "time_calls.h"
+#endif /*WIN_NT_DRIVER*/
+
+#ifdef WIN32
+#include "memory_t.h"
+#include "time_calls.h"
+#endif /*WIN32*/
+
+
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/time_calls.h>
+#else
+#include <tme/time_calls.h>
+#endif
+
+#endif
+
+/* error codes */
+#define     TME_ERROR           0   
+#define     TME_SUCCESS         1
+#define     TME_TRUE            2
+#define     TME_FALSE           3
+
+/* some constants */
+#define     DEFAULT_MEM_EX_SIZE     65536
+#define     MAX_TME_DATA_BLOCKS     4
+#define     TME_NONE_ACTIVE         0xffffffff
+#define     DELTA_READ              2  /* secs */
+
+#define     TME_LUT_ENTRIES                 0x00000000  
+#define     TME_MAX_FILL_STATE              0x00000001  /*potrebbe servire per un thread a passive level!?!?! */
+#define     TME_REHASHING_VALUE             0x00000002  
+#define     TME_KEY_LEN                     0x00000003
+#define     TME_SHARED_MEMORY_BLOCKS        0x00000004
+#define     TME_FILLED_ENTRIES              0x00000005
+#define     TME_BLOCK_SIZE                  0x00000006
+#define     TME_EXTRA_SEGMENT_SIZE          0x00000007
+#define     TME_LOOKUP_CODE                 0x00000008
+#define     TME_OUT_LUT_EXEC                0x00000009
+#define     TME_FILLED_BLOCKS               0x0000000a
+#define     TME_DEFAULT_EXEC                0x0000000b
+#define     TME_LUT_BASE_ADDRESS            0x0000000c
+#define     TME_SHARED_MEMORY_BASE_ADDRESS  0x0000000d
+#define     TME_EXTRA_SEGMENT_BASE_ADDRESS  0x0000000e
+#define     TME_LAST_FOUND                  0x0000000f   /* contains the offset of the last found entry */
+#define     TME_LAST_FOUND_BLOCK            0x00000010
+/* TME default values */
+#define     TME_LUT_ENTRIES_DEFAULT             32007
+#define     TME_REHASHING_VALUE_DEFAULT         1
+#define     TME_SHARED_MEMORY_BLOCKS_DEFAULT    16000
+#define     TME_BLOCK_SIZE_DEFAULT              64
+#define     TME_EXTRA_SEGMENT_SIZE_DEFAULT      0
+#define     TME_LOOKUP_CODE_DEFAULT             0
+#define     TME_OUT_LUT_EXEC_DEFAULT            0
+#define     TME_DEFAULT_EXEC_DEFAULT            0
+#define     TME_MAX_FILL_STATE_DEFAULT          15000
+
+#define IS_VALIDATED(src,index) (src&(1<<index))
+
+#define VALIDATE(src,index) src|=(1<<index);
+
+
+#define FORCE_NO_DELETION(timestamp)  (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
+
+/* TME callback prototypes */
+#ifndef __GNUC__
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+#else
+typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+#endif
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+    uint32 block;
+    uint32 exec_fcn;
+}
+    RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+    uint32 lut_entries;
+    uint32 max_fill_state;
+    uint32 rehashing_value;
+    uint32 key_len;
+    uint32 shared_memory_blocks;
+    uint32 filled_entries;
+    uint32 block_size;
+    uint32 extra_segment_size;
+    uint32 filled_blocks;
+    lut_fcn lookup_code;
+    uint32 default_exec;
+    uint32 out_lut_exec;
+    uint8 *lut_base_address;
+    uint8 *shared_memory_base_address;
+    uint8 *extra_segment_base_address;
+    struct timeval last_read;
+    uint32  enable_deletion;
+    uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+    uint32      working;
+    uint32      active;
+    uint32      validated_blocks;
+    TME_DATA    block_data[MAX_TME_DATA_BLOCKS];
+    uint32      active_read;
+    
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+    struct timeval *ts=(struct timeval*)timestamp;
+
+    if (data->enable_deletion==FALSE)
+        return FALSE;
+    if (data->filled_entries<data->max_fill_state)
+        return FALSE;
+    if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
+        return TRUE;
+    return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/valid_insns.h b/drivers/net/npf/valid_insns.h
new file mode 100644 (file)
index 0000000..20b115d
--- /dev/null
@@ -0,0 +1,73 @@
+u_short valid_instructions[]=
+       {
+               BPF_RET|BPF_K,
+               BPF_RET|BPF_A,
+               BPF_LD|BPF_IMM,
+               BPF_LDX|BPF_IMM,
+               BPF_LD|BPF_MEM,
+               BPF_LDX|BPF_MEM,
+               BPF_LD|BPF_MEM_EX_IMM|BPF_B,
+               BPF_LD|BPF_MEM_EX_IMM|BPF_H,
+               BPF_LD|BPF_MEM_EX_IMM|BPF_W,
+               BPF_LD|BPF_MEM_EX_IND|BPF_B,
+               BPF_LD|BPF_MEM_EX_IND|BPF_H,
+               BPF_LD|BPF_MEM_EX_IND|BPF_W,
+               BPF_LD|BPF_W|BPF_ABS,
+               BPF_LD|BPF_H|BPF_ABS,
+               BPF_LD|BPF_B|BPF_ABS,
+               BPF_LDX|BPF_W|BPF_ABS,
+               BPF_LDX|BPF_H|BPF_ABS,
+               BPF_LDX|BPF_B|BPF_ABS,
+               BPF_LD|BPF_W|BPF_LEN,
+               BPF_LDX|BPF_W|BPF_LEN,
+               BPF_LD|BPF_W|BPF_IND,
+               BPF_LD|BPF_H|BPF_IND,
+               BPF_LD|BPF_B|BPF_IND,
+               BPF_LDX|BPF_MSH|BPF_B,
+               BPF_ST,
+               BPF_STX,
+               BPF_ST|BPF_MEM_EX_IMM|BPF_B,
+               BPF_STX|BPF_MEM_EX_IMM|BPF_B,
+               BPF_ST|BPF_MEM_EX_IMM|BPF_W,
+               BPF_STX|BPF_MEM_EX_IMM|BPF_W,
+               BPF_ST|BPF_MEM_EX_IMM|BPF_H,
+               BPF_STX|BPF_MEM_EX_IMM|BPF_H,
+               BPF_ST|BPF_MEM_EX_IND|BPF_B,
+               BPF_ST|BPF_MEM_EX_IND|BPF_W,
+               BPF_ST|BPF_MEM_EX_IND|BPF_H,
+               BPF_JMP|BPF_JA,
+               BPF_JMP|BPF_JGT|BPF_K,
+               BPF_JMP|BPF_JGE|BPF_K,
+               BPF_JMP|BPF_JEQ|BPF_K,
+               BPF_JMP|BPF_JSET|BPF_K,
+               BPF_JMP|BPF_JGT|BPF_X,
+               BPF_JMP|BPF_JGE|BPF_X,
+               BPF_JMP|BPF_JEQ|BPF_X,
+               BPF_JMP|BPF_JSET|BPF_X,
+               BPF_ALU|BPF_ADD|BPF_X,
+               BPF_ALU|BPF_SUB|BPF_X,
+               BPF_ALU|BPF_MUL|BPF_X,
+               BPF_ALU|BPF_DIV|BPF_X,
+               BPF_ALU|BPF_AND|BPF_X,
+               BPF_ALU|BPF_OR|BPF_X,
+               BPF_ALU|BPF_LSH|BPF_X,
+               BPF_ALU|BPF_RSH|BPF_X,
+               BPF_ALU|BPF_ADD|BPF_K,
+               BPF_ALU|BPF_SUB|BPF_K,
+               BPF_ALU|BPF_MUL|BPF_K,
+               BPF_ALU|BPF_DIV|BPF_K,
+               BPF_ALU|BPF_AND|BPF_K,
+               BPF_ALU|BPF_OR|BPF_K,
+               BPF_ALU|BPF_LSH|BPF_K,
+               BPF_ALU|BPF_RSH|BPF_K,
+               BPF_ALU|BPF_NEG,
+               BPF_MISC|BPF_TAX,
+               BPF_MISC|BPF_TXA,
+               BPF_MISC|BPF_TME|BPF_LOOKUP,
+               BPF_MISC|BPF_TME|BPF_EXECUTE,
+               BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
+               BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
+               BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
+       };
+
+#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
diff --git a/drivers/net/npf/win_bpf.h b/drivers/net/npf/win_bpf.h
new file mode 100644 (file)
index 0000000..7dc5f14
--- /dev/null
@@ -0,0 +1,325 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *  The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)bpf.h       7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header$ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+typedef UCHAR u_char;
+typedef USHORT u_short;
+typedef ULONG u_int;
+typedef LONG bpf_int32;
+typedef ULONG bpf_u_int32;
+typedef ULONG u_int32;
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+#include "time_calls.h"
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+    u_short code;
+    u_char  jt;
+    u_char  jf;
+    bpf_int32 k;
+};
+
+/*
+ *  Structure for BIOCSETF.
+ */
+struct bpf_program {
+    u_int bf_len;
+    struct bpf_insn *bf_insns;
+};
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+    u_int bs_recv;      /* number of packets received */
+    u_int bs_drop;      /* number of packets dropped */
+};
+
+/*
+ * Struct return by BIOCVERSION.  This represents the version number of 
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded.  Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+    u_short bv_major;
+    u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+    struct timeval  bh_tstamp;  /* time stamp */
+    bpf_u_int32 bh_caplen;  /* length of captured portion */
+    bpf_u_int32 bh_datalen; /* original length of packet */
+    u_short     bh_hdrlen;  /* length of bpf header (this struct
+                       plus alignment padding) */
+};
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a <net/bpf.h> should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL    0   /* no link-layer encapsulation */
+#define DLT_EN10MB  1   /* Ethernet (10Mb) */
+#define DLT_EN3MB   2   /* Experimental Ethernet (3Mb) */
+#define DLT_AX25    3   /* Amateur Radio AX.25 */
+#define DLT_PRONET  4   /* Proteon ProNET Token Ring */
+#define DLT_CHAOS   5   /* Chaos */
+#define DLT_IEEE802 6   /* IEEE 802 Networks */
+#define DLT_ARCNET  7   /* ARCNET */
+#define DLT_SLIP    8   /* Serial Line IP */
+#define DLT_PPP     9   /* Point-to-point Protocol */
+#define DLT_FDDI    10  /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11  /* LLC/SNAP encapsulated atm */
+#define DLT_RAW     12  /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#define DLT_SLIP_BSDOS  15  /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS   16  /* BSD/OS Point-to-point Protocol */
+
+#define DLT_ATM_CLIP    19  /* Linux Classical-IP over ATM */
+
+/*
+ * This value is defined by NetBSD; other platforms should refrain from
+ * using it for other purposes, so that NetBSD savefiles with a link
+ * type of 50 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL  50  /* PPP over serial with HDLC encapsulation */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC  104 /* Cisco HDLC */
+#define DLT_CHDLC   DLT_C_HDLC
+
+/*
+ * Reserved for future use.
+ * Do not pick other numerical value for these unless you have also
+ * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
+ * which will arrange that capture files for these DLT_ types have
+ * the same "network" value on all platforms, regardless of what
+ * value is chosen for their DLT_ type (thus allowing captures made
+ * on one platform to be read on other platforms, even if the two
+ * platforms don't use the same numerical values for all DLT_ types).
+ */
+#define DLT_IEEE802_11  105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here.  If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 for any purpose.
+ */
+#define DLT_LOOP    108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL   113
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define     BPF_LD      0x00
+#define     BPF_LDX     0x01
+#define     BPF_ST      0x02
+#define     BPF_STX     0x03
+#define     BPF_ALU     0x04
+#define     BPF_JMP     0x05
+#define     BPF_RET     0x06
+#define     BPF_MISC    0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code)  ((code) & 0x18)
+#define     BPF_W       0x00
+#define     BPF_H       0x08
+#define     BPF_B       0x10
+#define BPF_MODE(code)  ((code) & 0xe0)
+#define     BPF_IMM     0x00
+#define     BPF_ABS     0x20
+#define     BPF_IND     0x40
+#define     BPF_MEM     0x60
+#define     BPF_LEN     0x80
+#define     BPF_MSH     0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code)    ((code) & 0xf0)
+#define     BPF_ADD     0x00
+#define     BPF_SUB     0x10
+#define     BPF_MUL     0x20
+#define     BPF_DIV     0x30
+#define     BPF_OR      0x40
+#define     BPF_AND     0x50
+#define     BPF_LSH     0x60
+#define     BPF_RSH     0x70
+#define     BPF_NEG     0x80
+#define     BPF_JA      0x00
+#define     BPF_JEQ     0x10
+#define     BPF_JGT     0x20
+#define     BPF_JGE     0x30
+#define     BPF_JSET    0x40
+#define BPF_SRC(code)   ((code) & 0x08)
+#define     BPF_K       0x00
+#define     BPF_X       0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code)  ((code) & 0x18)
+#define     BPF_A       0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define     BPF_TAX     0x00
+#define     BPF_TXA     0x80
+
+/* TME instructions */
+#define     BPF_TME                 0x08
+
+#define     BPF_LOOKUP              0x90   
+#define     BPF_EXECUTE             0xa0
+#define     BPF_INIT                0xb0
+#define     BPF_VALIDATE            0xc0
+#define     BPF_SET_ACTIVE          0xd0
+#define     BPF_RESET               0xe0
+#define     BPF_SET_MEMORY          0x80
+#define     BPF_GET_REGISTER_VALUE  0x70
+#define     BPF_SET_REGISTER_VALUE  0x60
+#define     BPF_SET_WORKING         0x50
+#define     BPF_SET_ACTIVE_READ     0x40
+#define     BPF_SET_AUTODELETION    0x30
+#define     BPF_SEPARATION          0xff
+
+#define     BPF_MEM_EX_IMM  0xc0
+#define     BPF_MEM_EX_IND  0xe0
+/*used for ST */
+#define     BPF_MEM_EX      0xc0
+
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#endif
diff --git a/drivers/net/npf/win_bpf_filter.c b/drivers/net/npf/win_bpf_filter.c
new file mode 100644 (file)
index 0000000..76dee6e
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *
+ * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+       @(#)bpf.c       7.5 (Berkeley) 7/15/91
+*/
+
+#include "tme.h"
+#include "win_bpf.h"
+
+#include "debug.h"
+
+#include "valid_insns.h"
+
+#define EXTRACT_SHORT(p)\
+       ((u_short)\
+               ((u_short)*((u_char *)p+0)<<8|\
+                (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+               ((u_int32)*((u_char *)p+0)<<24|\
+                (u_int32)*((u_char *)p+1)<<16|\
+                (u_int32)*((u_char *)p+2)<<8|\
+                (u_int32)*((u_char *)p+3)<<0)
+
+
+u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
+       register struct bpf_insn *pc;
+       register u_char *p;
+       u_int wirelen;
+       register u_int buflen;
+       PMEM_TYPE mem_ex;
+       PTME_CORE tme;
+       struct time_conv *time_ref;
+
+{
+       register u_int32 A, X;
+       register int k;
+       u_int32 j,tmp;
+       u_short tmp2;
+       
+       int32 mem[BPF_MEMWORDS];
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (u_int)-1;
+       A = 0;
+       X = 0;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+               
+                       return 0;
+
+               case BPF_RET|BPF_K:
+                       return (u_int)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (u_int)A;
+
+               case BPF_LD|BPF_W|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(int32) > buflen) {
+                               return 0;
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(short) > buflen) {
+                               return 0;
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_LEN:
+                       A = wirelen;
+                       continue;
+
+               case BPF_LDX|BPF_W|BPF_LEN:
+                       X = wirelen;
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(int32) > buflen) {
+                               return 0;
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(short) > buflen) {
+                               return 0;
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_IND:
+                       k = X + pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LDX|BPF_MSH|BPF_B:
+                       k = pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+                       X = (p[pc->k] & 0xf) << 2;
+                       continue;
+
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+                       
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+/* LD NO PACKET INSTRUCTIONS */
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+                       A= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+                       X= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+                       A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+                       X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+                       A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+                       X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+                       continue;
+                       
+               case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+                       k = X + pc->k;
+                       if ((int32)k>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A= mem_ex->buffer[k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+                       k = X + pc->k;
+                       if ((int32)(k+1)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+                       k = X + pc->k;
+                       if ((int32)(k+3)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+                       continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+/* STORE INSTRUCTIONS */
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)A;
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)X;
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=A;
+                       *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=X;
+                       *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16)A;
+                       *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16)X;
+                       *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+                       mem_ex->buffer[pc->k+X]=(uint8)A;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+                       tmp=A;
+                       *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+                       tmp2=(uint16)A;
+                       *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+                       continue;
+/* END STORE INSTRUCTIONS */
+
+               case BPF_JMP|BPF_JA:
+                       pc += pc->k;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       (int)A = -((int)A);
+                       continue;
+
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+
+/* TME INSTRUCTIONS */
+               case BPF_MISC|BPF_TME|BPF_LOOKUP:
+                       j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+                       if (j==TME_ERROR)
+                               return 0;       
+                       pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_EXECUTE:
+                       if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+                       if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+                       if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+                               return 0;
+                       A=j;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+                       if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+                               return 0;
+                       continue;
+/* END TME INSTRUCTIONS */
+
+               }
+       }
+}
+
+//-------------------------------------------------------------------
+
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
+       register struct bpf_insn *pc;
+       register u_char *p;
+       register u_char *pd;
+       register int headersize; 
+       u_int wirelen;
+       register u_int buflen;
+       PMEM_TYPE mem_ex;
+       PTME_CORE tme;
+       struct time_conv *time_ref;
+{
+       register u_int32 A, X;
+       register int k;
+       int32 mem[BPF_MEMWORDS];
+       u_int32 j,tmp;
+       u_short tmp2;
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (u_int)-1;
+       A = 0;
+       X = 0;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+               
+                       return 0;
+
+               case BPF_RET|BPF_K:
+                       return (u_int)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (u_int)A;
+
+               case BPF_LD|BPF_W|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(int32) > buflen) {
+                               return 0;
+                       }
+                       
+                       if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
+                       else if(k + 2 == headersize){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)p+k+1)<<16|
+                                       (u_int32)*((u_char *)p+k+2)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize);
+                       }
+                       else if(k == headersize-1){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)p+k+1)<<16|
+                                       (u_int32)*((u_char *)pd+k-headersize)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize+1);
+                       }
+                       else if(k == headersize){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+                                       (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize+3);
+                       }
+                       A = EXTRACT_LONG(&pd[k-headersize]);
+                       
+                       continue;
+                       
+               case BPF_LD|BPF_H|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(short) > buflen) {
+                               return 0;
+                       }
+                       
+                       if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
+                       else if(k == headersize){
+                               A=(u_short)*((u_char *)p+k)<<8|
+                                       (u_short)*((u_char *)pd+k-headersize);
+                       }
+                       A = EXTRACT_SHORT(&pd[k-headersize]);
+                       
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+
+                       if(k<headersize) A = p[k];
+                        else A = pd[k-headersize];
+
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_LEN:
+                       A = wirelen;
+                       continue;
+
+               case BPF_LDX|BPF_W|BPF_LEN:
+                       X = wirelen;
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(int32) > buflen) {
+                               return 0;
+                       }
+
+                       if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
+                       else if(k + (int)sizeof(int32) == headersize+2){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)p+k+1)<<16|
+                                       (u_int32)*((u_char *)p+k+2)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize);
+                       }
+                       else if(k + (int)sizeof(int32) == headersize+3){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)p+k+1)<<16|
+                                       (u_int32)*((u_char *)pd+k-headersize)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize+1);
+                       }
+                       else if(k + (int)sizeof(int32) == headersize+4){
+                               A=(u_int32)*((u_char *)p+k)<<24|
+                                       (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+                                       (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+                                       (u_int32)*((u_char *)pd+k-headersize+3);
+                       }
+                       A = EXTRACT_LONG(&pd[k-headersize]);
+                       
+                       continue;
+                       
+               case BPF_LD|BPF_H|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(short) > buflen) {
+                               return 0;
+                       }
+                       
+                       if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
+                       else if(k == headersize){
+                               A=(u_short)*((u_char *)p+k)<<8|
+                                       (u_short)*((u_char *)pd+k-headersize);
+                       }
+                       A = EXTRACT_SHORT(&pd[k-headersize]);
+
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_IND:
+                       k = X + pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+
+                       if(k<headersize) A = p[k];
+                        else A = pd[k-headersize];
+
+                       continue;
+
+               case BPF_LDX|BPF_MSH|BPF_B:
+                       k = pc->k;
+                       if ((int)k >= (int)buflen) {
+                               return 0;
+                       }
+                       
+                       if((pc->k)<headersize) X = (p[pc->k] & 0xf) << 2;
+                        else X = (pd[(pc->k)-headersize] & 0xf) << 2;
+
+                       continue;
+
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+                       
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+/* LD NO PACKET INSTRUCTIONS */
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+                       A= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+                       X= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+                       A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+                       X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+                       A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+                       X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+                       continue;
+                       
+               case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+                       k = X + pc->k;
+                       if ((int32)k>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A= mem_ex->buffer[k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+                       k = X + pc->k;
+                       if ((int32)(k+1)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+                       k = X + pc->k;
+                       if ((int32)(k+3)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+                       continue;
+/* END LD NO PACKET INSTRUCTIONS */
+               
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+
+/* STORE INSTRUCTIONS */
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)A;
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)X;
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=A;
+                       *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=X;
+                       *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16)A;
+                       *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16)X;
+                       *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+                       mem_ex->buffer[pc->k+X]=(uint8)A;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+                       tmp=A;
+                       *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+                       tmp2=(uint16)A;
+                       *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+                       continue;
+/* END STORE INSTRUCTIONS */
+               
+               
+               
+               case BPF_JMP|BPF_JA:
+                       pc += pc->k;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       (int)A = -((int)A);
+                       continue;
+
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+
+/* TME INSTRUCTIONS */
+               case BPF_MISC|BPF_TME|BPF_LOOKUP:
+                       j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+                       if (j==TME_ERROR)
+                               return 0;       
+                       pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_EXECUTE:
+                       if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+                       if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+                       if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+                               return 0;
+                       A=j;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+                       if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+                               return 0;
+                       continue;
+/* END TME INSTRUCTIONS */
+
+               }
+       }
+}
+
+int32
+bpf_validate(f, len,mem_ex_size)
+       struct bpf_insn *f;
+       int32 len;
+       uint32 mem_ex_size;     
+{
+       register int32 i,j;
+       register struct bpf_insn *p;
+       int32 flag;
+               
+       for (i = 0; i < len; ++i) {
+               /*
+                * Check that that jumps are forward, and within 
+                * the code block.
+                */
+               
+               p = &f[i];
+
+               IF_LOUD(DbgPrint("Validating program");)
+               
+               flag=0;
+               for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
+                       if (p->code==valid_instructions[j])
+                               flag=1;
+               if (flag==0)
+                       return 0;
+
+               IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
+               
+               if (BPF_CLASS(p->code) == BPF_JMP) {
+                       register int32 from = i + 1;
+
+                       if (BPF_OP(p->code) == BPF_JA) {
+                               if (from + p->k >= len)
+                                       return 0;
+                       }
+                       else if (from + p->jt >= len || from + p->jf >= len)
+                               return 0;
+               }
+
+               IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
+       
+               /*
+                * Check that memory operations use valid addresses.
+                */
+               if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) ||
+                    (BPF_CLASS(p->code) == BPF_LD && 
+                     (p->code & 0xe0) == BPF_MEM)) &&
+                         (p->k >= BPF_MEMWORDS || p->k < 0))
+                       return 0;
+               
+               IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");)
+                       
+               /*
+                * Check if key stores use valid addresses 
+                */ 
+               if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM)
+           switch (BPF_SIZE(p->code))
+               {
+                       case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0;
+                       case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0;
+                       case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0;
+               }
+
+               IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");)
+
+               /*
+                * Check for constant division by 0.
+                */
+               if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+                       return 0;
+       }
+       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
\ No newline at end of file
diff --git a/drivers/net/npf/win_bpf_filter_init.c b/drivers/net/npf/win_bpf_filter_init.c
new file mode 100644 (file)
index 0000000..51fb5d4
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *
+ * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tme.h"
+#include "win_bpf.h"
+
+/*
+ * Initialize the filter machine
+ */
+uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
+{
+       register uint32 A, X;
+       int32 mem[BPF_MEMWORDS];
+       register int32 k;
+       uint32 *tmp;
+       uint16 *tmp2;
+       uint32 j;
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+                return (uint32)-1;
+       A = 0;
+       X = 0;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+                       return 0;
+
+/* RET INSTRUCTIONS */
+               case BPF_RET|BPF_K:
+                       return (uint32)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (uint32)A;
+/* END RET INSTRUCTIONS */
+
+/* LD NO PACKET INSTRUCTIONS */
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+                       
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+                       A= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+                       X= mem_ex->buffer[pc->k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp2
+                               xor eax, eax
+                               mov ax, [ebx]
+                               bswap eax
+                               mov A, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp2): );
+#endif
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp2
+                               xor eax, eax
+                               mov ax, [ebx]
+                               bswap eax
+                               mov X, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(X),"=c"(tmp2): );
+#endif
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp
+                               mov eax, [ebx]
+                               bswap eax
+                               mov A, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp): );
+#endif
+                       continue;
+
+               case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp
+                               mov eax, [ebx]
+                               bswap eax
+                               mov X, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(X),"=c"(tmp): );
+#endif
+                       continue;
+                       
+               case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+                       k = X + pc->k;
+                       if ((int32)k>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       A= mem_ex->buffer[k];
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+                       k = X + pc->k;
+                       if ((int32)(k+1)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       tmp2=(uint16*)&mem_ex->buffer[k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp2
+                               xor eax, eax
+                               mov ax, [ebx]
+                               bswap eax
+                               mov A, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp2): );
+#endif
+                       continue;
+
+               case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+                       k = X + pc->k;
+                       if ((int32)(k+3)>= (int32)mem_ex->size) {
+                               return 0;
+                       }
+                       tmp=(uint32*)&mem_ex->buffer[k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx,tmp
+                               mov eax, [ebx]
+                               bswap eax
+                               mov A, eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp): );
+#endif
+                       continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+/* STORE INSTRUCTIONS */
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)A;
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+                       mem_ex->buffer[pc->k]=(uint8)X;
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp
+                               mov eax, A
+                               bswap eax
+                               mov [ebx], eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp): );
+#endif
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+                       tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp
+                               mov eax, X
+                               bswap eax
+                               mov [ebx], eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(X),"=c"(tmp): );
+#endif
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp2
+                               mov eax, A
+                               xchg ah, al
+                               mov [ebx], ax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp2): );
+#endif
+                       continue;
+
+               case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+                       tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp2
+                               mov eax, X
+                               xchg ah, al
+                               mov [ebx], ax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(X),"=c"(tmp2): );
+#endif
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+                       mem_ex->buffer[pc->k+X]=(uint8)A;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+                       tmp=(uint32*)&mem_ex->buffer[pc->k+X];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp
+                               mov eax, A
+                               bswap eax
+                               mov [ebx], eax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp): );
+#endif
+                       continue;
+
+               case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+                       tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
+#ifndef __GNUC__
+                       __asm
+                       {
+                               push eax
+                               push ebx
+                               mov ebx, tmp2
+                               mov eax, A
+                               xchg ah, al
+                               mov [ebx], ax
+                               pop ebx
+                               pop eax
+                       }
+#else
+                       asm("push %%eax;"
+                               "push %%ebx;"
+                               "mov %1,%%ebx;"
+                               "xor %%eax, %%eax;"
+                               "mov (%%ebx), %%ax;"
+                               "bswap %%eax;"
+                               "mov %%eax, %0;"
+                               "pop %%ebx;"
+                               "pop %%eax;"
+                :"=a"(A),"=c"(tmp2): );
+#endif
+                       continue;
+/* END STORE INSTRUCTIONS */
+
+/* JUMP INSTRUCTIONS */
+               case BPF_JMP|BPF_JA:
+                       pc += pc->k;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+/* END JUMP INSTRUCTIONS */
+
+/* ARITHMETIC INSTRUCTIONS */
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       (int32)A = -((int32)A);
+                       continue;
+/* ARITHMETIC INSTRUCTIONS */
+
+/* MISC INSTRUCTIONS */
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+/* END MISC INSTRUCTIONS */
+
+/* TME INSTRUCTIONS */
+               case BPF_MISC|BPF_TME|BPF_LOOKUP:
+                       j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+                       if (j==TME_ERROR)
+                               return 0;       
+                       pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_EXECUTE:
+                       if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_INIT:
+                       if (init_tme_block(tme,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+                       
+               case BPF_MISC|BPF_TME|BPF_VALIDATE:
+                       if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
+                       if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+                       if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
+                       if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+                               return 0;
+                       continue;
+               case BPF_MISC|BPF_TME|BPF_SET_WORKING:
+                       if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
+                               return 0;
+                       tme->working=pc->k;
+                       continue;
+
+
+
+               case BPF_MISC|BPF_TME|BPF_RESET:
+                       if (reset_tme(tme)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+                       if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+                               return 0;
+                       A=j;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+                       if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
+                               return 0;
+                       continue;
+
+               case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
+                       set_autodeletion(&tme->block_data[tme->working],pc->k);
+                       continue;
+                       
+/* END TME INSTRUCTIONS */
+
+               }
+       }
+}
+
diff --git a/drivers/net/npf/win_bpf_filter_init.h b/drivers/net/npf/win_bpf_filter_init.h
new file mode 100644 (file)
index 0000000..8b06af7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2001
+ *  Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef __FILTER_INIT
+#define __FILTER_INIT
+
+#include "tme.h"
+
+#define INIT_OK     1
+#define INIT_ERROR  0
+
+uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
+
+#endif
\ No newline at end of file
diff --git a/drivers/net/npf/write.c b/drivers/net/npf/write.c
new file mode 100644 (file)
index 0000000..c3c5eb5
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#define NdisReinitializePacket(Packet)                                                                         \
+{                                                                                                                                                      \
+       (Packet)->Private.Head = (PNDIS_BUFFER)NULL;                                                    \
+       (Packet)->Private.ValidCounts = FALSE;                                                                  \
+}
+
+#endif
+
+#include "debug.h"
+#include "packet.h"
+
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Write(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    )
+
+{
+    POPEN_INSTANCE             Open;
+    PIO_STACK_LOCATION IrpSp;
+    PNDIS_PACKET               pPacket;
+       UINT                            i;
+    NDIS_STATUS                    Status;
+
+       IF_LOUD(DbgPrint("NPF_Write\n");)
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+    Open=IrpSp->FileObject->FsContext;
+
+       IF_LOUD(DbgPrint("Max frame size = %d\n", Open->MaxFrameSize);)
+
+
+       if(IrpSp->Parameters.Write.Length == 0 ||       // Check that the buffer provided by the user is not empty
+               Open->MaxFrameSize == 0 ||      // Check that the MaxFrameSize is correctly initialized
+               IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
+       {
+               IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
+
+        Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+        IoCompleteRequest (Irp, IO_NO_INCREMENT);
+        return NDIS_STATUS_SUCCESS;
+       }
+
+
+    IoMarkIrpPending(Irp);
+
+       Open->Multiple_Write_Counter=Open->Nwrites;
+
+       NdisResetEvent(&Open->WriteEvent);
+
+
+       for(i=0;i<Open->Nwrites;i++){
+               
+               //  Try to get a packet from our list of free ones
+               NdisAllocatePacket(
+                       &Status,
+                       &pPacket,
+                       Open->PacketPool
+                       );
+               
+               if (Status != NDIS_STATUS_SUCCESS) {
+                       
+                       //  No free packets
+                       Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+                       IoCompleteRequest (Irp, IO_NO_INCREMENT);
+                       return STATUS_INSUFFICIENT_RESOURCES;
+               }
+               
+               // The packet has a buffer that needs not to be freed after every single write
+               RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
+
+               // Save the IRP associated with the packet
+               RESERVED(pPacket)->Irp=Irp;
+               
+               //  Attach the writes buffer to the packet
+               NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
+               
+               //  Call the MAC
+               NdisSend(
+                       &Status,
+                       Open->AdapterHandle,
+                       pPacket);
+
+               if (Status != NDIS_STATUS_PENDING) {
+                       //  The send didn't pend so call the completion handler now
+                       NPF_SendComplete(
+                               Open,
+                               pPacket,
+                               Status
+                               );
+                       
+               }
+               
+               if(i%100==99){
+                       NdisWaitEvent(&Open->WriteEvent,1000);  
+                       NdisResetEvent(&Open->WriteEvent);
+               }
+       }
+       
+    return(STATUS_PENDING);
+
+}
+
+
+//-------------------------------------------------------------------
+
+INT
+NPF_BufferedWrite(
+       IN PIRP Irp, 
+       IN PCHAR UserBuff, 
+       IN ULONG UserBuffSize, 
+       BOOLEAN Sync)
+{
+    POPEN_INSTANCE             Open;
+    PIO_STACK_LOCATION IrpSp;
+    PNDIS_PACKET               pPacket;
+       UINT                            i;
+    NDIS_STATUS                    Status;
+       LARGE_INTEGER           StartTicks, CurTicks, TargetTicks;
+       LARGE_INTEGER           TimeFreq;
+       struct timeval          BufStartTime;
+       struct sf_pkthdr        *winpcap_hdr;
+       PMDL                            TmpMdl;
+       PCHAR                           CurPos;
+       PCHAR                           EndOfUserBuff = UserBuff + UserBuffSize;
+       
+    IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
+               
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+       
+    Open=IrpSp->FileObject->FsContext;
+       
+       // Security check on the length of the user buffer
+       if(UserBuff==0)
+       {
+               return 0;
+       }
+               
+       // Check that the MaxFrameSize is correctly initialized
+       if(Open->MaxFrameSize == 0)
+       {
+               IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
+
+               return 0;
+       }
+
+       
+       // Start from the first packet
+       winpcap_hdr = (struct sf_pkthdr*)UserBuff;
+       
+       // Retrieve the time references
+       StartTicks = KeQueryPerformanceCounter(&TimeFreq);
+       BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
+       BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
+       
+       // Chech the consistency of the user buffer
+       if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
+       {
+               IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
+
+               return -1;
+       }
+       
+       // Save the current time stamp counter
+       CurTicks = KeQueryPerformanceCounter(NULL);
+       
+       // Main loop: send the buffer to the wire
+       while( TRUE ){
+               
+               if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > Open->MaxFrameSize)
+               {
+                       // Malformed header
+                       IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+                       
+                       return -1;
+               }
+               
+               // Allocate an MDL to map the packet data
+               TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
+                       winpcap_hdr->caplen,
+                       FALSE,
+                       FALSE,
+                       NULL);
+               
+               if (TmpMdl == NULL)
+               {
+                       // Unable to map the memory: packet lost
+                       IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
+
+                       return -1;
+               }
+               
+               MmBuildMdlForNonPagedPool(TmpMdl);      // XXX can this line be removed?
+               
+               // Allocate a packet from our free list
+               NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+               
+               if (Status != NDIS_STATUS_SUCCESS) {
+                       //  No free packets
+                       IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
+
+                       return (PCHAR)winpcap_hdr - UserBuff;
+               }
+               
+               // The packet has a buffer that needs to be freed after every single write
+               RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
+               
+               // Attach the MDL to the packet
+               NdisChainBufferAtFront(pPacket,TmpMdl);
+               
+               // Call the MAC
+               NdisSend( &Status, Open->AdapterHandle, pPacket);
+               
+               if (Status != NDIS_STATUS_PENDING) {
+                       // The send didn't pend so call the completion handler now
+                       NPF_SendComplete(
+                               Open,
+                               pPacket,
+                               Status
+                               );                              
+               }
+               
+               // Step to the next packet in the buffer
+               (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
+               
+               // Check if the end of the user buffer has been reached
+               if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
+               {
+                       IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
+
+                       return (PCHAR)winpcap_hdr - UserBuff;
+               }
+               
+               if( Sync ){
+
+                       // Release the application if it has been blocked for approximately more than 1 seconds
+                       if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
+                       {
+                               IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
+                                       
+                               return (PCHAR)winpcap_hdr - UserBuff;
+                       }
+                       
+#ifndef __GNUC__
+                       // Calculate the time interval to wait before sending the next packet
+            TargetTicks.QuadPart = StartTicks.QuadPart +
+                               (LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
+                               winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
+                               (TimeFreq.QuadPart) / 1000000;
+
+                       // Wait until the time interval has elapsed
+                       while( CurTicks.QuadPart <= TargetTicks.QuadPart )
+                               CurTicks = KeQueryPerformanceCounter(NULL);
+#else
+#endif
+               }
+               
+       }
+                       
+       return (PCHAR)winpcap_hdr - UserBuff;
+               
+}
+
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_SendComplete(
+                                  IN NDIS_HANDLE   ProtocolBindingContext,
+                                  IN PNDIS_PACKET  pPacket,
+                                  IN NDIS_STATUS   Status
+                                  )
+                                  
+{
+       PIRP              Irp;
+       PIO_STACK_LOCATION  irpSp;
+       POPEN_INSTANCE      Open;
+       PMDL TmpMdl;
+       
+       IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
+               
+       Open= (POPEN_INSTANCE)ProtocolBindingContext;
+       
+       if( RESERVED(pPacket)->FreeBufAfterWrite ){
+               // Free the MDL associated with the packet
+               NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+               IoFreeMdl(TmpMdl);
+       }
+       else{
+               if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
+                       NdisSetEvent(&Open->WriteEvent);
+               
+               Open->Multiple_Write_Counter--;
+       }
+       
+       //  recyle the packet
+       NdisReinitializePacket(pPacket);
+       
+       //  Put the packet back on the free list
+       NdisFreePacket(pPacket);
+       
+       if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
+               if(Open->Multiple_Write_Counter==0){
+                       // Release the buffer and awake the application
+                       NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+                       
+                       Irp=RESERVED(pPacket)->Irp;
+                       irpSp = IoGetCurrentIrpStackLocation(Irp);
+
+                       Irp->IoStatus.Status = Status;
+                       Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
+                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                       
+               }
+       }
+
+       return;
+}
+
+
+#ifdef __GNUC__
+/*
+__divdi3()
+{
+    //_alldiv();
+}
+
+//_allmul();
+//_allrem();
+
+*/
+#endif
diff --git a/drivers/net/tcpip/datalink/.cvsignore b/drivers/net/tcpip/datalink/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/include/linux.h b/drivers/net/tcpip/include/linux.h
new file mode 100755 (executable)
index 0000000..86db7ae
--- /dev/null
@@ -0,0 +1,1876 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <ddk/ntddk.h>
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+typedef struct page {
+  int x;
+} mem_map_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* i386 */
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* DMA addresses come in generic and 64-bit flavours.  */
+
+#ifdef CONFIG_HIGHMEM64G
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif
+typedef u64 dma64_addr_t;
+
+
+
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * Those macros may have been defined in <gnu/types.h>. But we always
+ * use the ones here. 
+ */
+#undef __NFDBITS
+#define __NFDBITS      (8 * sizeof(unsigned long))
+
+#undef __FD_SETSIZE
+#define __FD_SETSIZE   1024
+
+#undef __FDSET_LONGS
+#define __FDSET_LONGS  (__FD_SETSIZE/__NFDBITS)
+
+#undef __FDELT
+#define        __FDELT(d)      ((d) / __NFDBITS)
+
+#undef __FDMASK
+#define        __FDMASK(d)     (1UL << ((d) % __NFDBITS))
+
+typedef struct {
+       unsigned long fds_bits [__FDSET_LONGS];
+} __kernel_fd_set;
+
+/* Type of a signal handler.  */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key.  */
+typedef int __kernel_key_t;
+
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long  __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long           __kernel_off_t;
+typedef int            __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int   __kernel_size_t;
+typedef int            __kernel_ssize_t;
+typedef int            __kernel_ptrdiff_t;
+typedef long           __kernel_time_t;
+typedef long           __kernel_suseconds_t;
+typedef long           __kernel_clock_t;
+typedef int            __kernel_daddr_t;
+typedef char *         __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long      __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+       int     val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+       int     __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(fd,fdsetp) \
+               __asm__ __volatile__("btsl %1,%0": \
+                       "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_CLR
+#define __FD_CLR(fd,fdsetp) \
+               __asm__ __volatile__("btrl %1,%0": \
+                       "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_ISSET
+#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+               unsigned char __result; \
+               __asm__ __volatile__("btl %1,%2 ; setb %0" \
+                       :"=q" (__result) :"r" ((int) (fd)), \
+                       "m" (*(__kernel_fd_set *) (fdsetp))); \
+               __result; }))
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) \
+do { \
+       int __d0, __d1; \
+       __asm__ __volatile__("cld ; rep ; stosl" \
+                       :"=m" (*(__kernel_fd_set *) (fdsetp)), \
+                         "=&c" (__d0), "=&D" (__d1) \
+                       :"a" (0), "1" (__FDSET_LONGS), \
+                       "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+
+#ifndef __KERNEL_STRICT_NAMES
+
+typedef __kernel_fd_set                fd_set;
+typedef __kernel_dev_t         dev_t;
+typedef __kernel_ino_t         ino_t;
+typedef __kernel_mode_t                mode_t;
+typedef __kernel_nlink_t       nlink_t;
+typedef __kernel_off_t         off_t;
+typedef __kernel_pid_t         pid_t;
+typedef __kernel_daddr_t       daddr_t;
+typedef __kernel_key_t         key_t;
+typedef __kernel_suseconds_t   suseconds_t;
+
+#ifdef __KERNEL__
+typedef __kernel_uid32_t       uid_t;
+typedef __kernel_gid32_t       gid_t;
+typedef __kernel_uid16_t        uid16_t;
+typedef __kernel_gid16_t        gid16_t;
+
+#ifdef CONFIG_UID16
+/* This is defined by include/asm-{arch}/posix_types.h */
+typedef __kernel_old_uid_t     old_uid_t;
+typedef __kernel_old_gid_t     old_gid_t;
+#endif /* CONFIG_UID16 */
+
+/* libc5 includes this file to define uid_t, thus uid_t can never change
+ * when it is included by non-kernel code
+ */
+#else
+typedef __kernel_uid_t         uid_t;
+typedef __kernel_gid_t         gid_t;
+#endif /* __KERNEL__ */
+
+#if defined(__GNUC__)
+typedef __kernel_loff_t                loff_t;
+#endif
+
+/*
+ * The following typedefs are also protected by individual ifdefs for
+ * historical reasons:
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __kernel_size_t                size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __kernel_ssize_t       ssize_t;
+#endif
+
+#ifndef _PTRDIFF_T
+#define _PTRDIFF_T
+typedef __kernel_ptrdiff_t     ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef __kernel_time_t                time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef __kernel_clock_t       clock_t;
+#endif
+
+#ifndef _CADDR_T
+#define _CADDR_T
+typedef __kernel_caddr_t       caddr_t;
+#endif
+
+/* bsd */
+typedef unsigned char          u_char;
+typedef unsigned short         u_short;
+typedef unsigned int           u_int;
+typedef unsigned long          u_long;
+
+/* sysv */
+typedef unsigned char          unchar;
+typedef unsigned short         ushort;
+typedef unsigned int           uint;
+typedef unsigned long          ulong;
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+typedef                __u8            u_int8_t;
+typedef                __s8            int8_t;
+typedef                __u16           u_int16_t;
+typedef                __s16           int16_t;
+typedef                __u32           u_int32_t;
+typedef                __s32           int32_t;
+
+#endif /* !(__BIT_TYPES_DEFINED__) */
+
+typedef                __u8            uint8_t;
+typedef                __u16           uint16_t;
+typedef                __u32           uint32_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef                __u64           uint64_t;
+typedef                __u64           u_int64_t;
+typedef                __s64           int64_t;
+#endif
+
+#endif /* __KERNEL_STRICT_NAMES */
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+struct ustat {
+       __kernel_daddr_t        f_tfree;
+       __kernel_ino_t          f_tinode;
+       char                    f_fname[6];
+       char                    f_fpack[6];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#define __LITTLE_ENDIAN_BITFIELD
+#endif
+
+#if 1 /* swab */
+
+/*
+ * linux/byteorder/swab.h
+ * Byte-swapping, independently from CPU endianness
+ *     swabXX[ps]?(foo)
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ *    separated swab functions from cpu_to_XX,
+ *    to clean up support for bizarre-endian architectures.
+ *
+ * See asm-i386/byteorder.h and suches for examples of how to provide
+ * architecture-dependent optimized versions
+ *
+ */
+
+/* casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#define ___swab16(x) \
+({ \
+       __u16 __x = (x); \
+       ((__u16)( \
+               (((__u16)(__x) & (__u16)0x00ffU) << 8) | \
+               (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
+})
+
+#define ___swab24(x) \
+({ \
+       __u32 __x = (x); \
+       ((__u32)( \
+               ((__x & (__u32)0x000000ffUL) << 16) | \
+                (__x & (__u32)0x0000ff00UL)        | \
+               ((__x & (__u32)0x00ff0000UL) >> 16) )); \
+})
+
+#define ___swab32(x) \
+({ \
+       __u32 __x = (x); \
+       ((__u32)( \
+               (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
+               (((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
+               (((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
+               (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+})
+
+#define ___swab64(x) \
+({ \
+       __u64 __x = (x); \
+       ((__u64)( \
+               (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
+               (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
+               (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+               (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) <<  8) | \
+               (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >>  8) | \
+               (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+               (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+               (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
+})
+
+#define ___constant_swab16(x) \
+       ((__u16)( \
+               (((__u16)(x) & (__u16)0x00ffU) << 8) | \
+               (((__u16)(x) & (__u16)0xff00U) >> 8) ))
+#define ___constant_swab24(x) \
+       ((__u32)( \
+               (((__u32)(x) & (__u32)0x000000ffU) << 16) | \
+               (((__u32)(x) & (__u32)0x0000ff00U)        | \
+               (((__u32)(x) & (__u32)0x00ff0000U) >> 16) ))
+#define ___constant_swab32(x) \
+       ((__u32)( \
+               (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+               (((__u32)(x) & (__u32)0x0000ff00UL) <<  8) | \
+               (((__u32)(x) & (__u32)0x00ff0000UL) >>  8) | \
+               (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+#define ___constant_swab64(x) \
+       ((__u64)( \
+               (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+               (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+               (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+               (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) <<  8) | \
+               (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >>  8) | \
+               (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+               (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+               (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
+
+/*
+ * provide defaults when no architecture-specific optimization is detected
+ */
+#ifndef __arch__swab16
+#  define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
+#endif
+#ifndef __arch__swab24
+#  define __arch__swab24(x) ({ __u32 __tmp = (x) ; ___swab24(__tmp); })
+#endif
+#ifndef __arch__swab32
+#  define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
+#endif
+#ifndef __arch__swab64
+#  define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
+#endif
+
+#ifndef __arch__swab16p
+#  define __arch__swab16p(x) __arch__swab16(*(x))
+#endif
+#ifndef __arch__swab24p
+#  define __arch__swab24p(x) __arch__swab24(*(x))
+#endif
+#ifndef __arch__swab32p
+#  define __arch__swab32p(x) __arch__swab32(*(x))
+#endif
+#ifndef __arch__swab64p
+#  define __arch__swab64p(x) __arch__swab64(*(x))
+#endif
+
+#ifndef __arch__swab16s
+#  define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
+#endif
+#ifndef __arch__swab24s
+#  define __arch__swab24s(x) do { *(x) = __arch__swab24p((x)); } while (0)
+#endif
+#ifndef __arch__swab32s
+#  define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
+#endif
+#ifndef __arch__swab64s
+#  define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
+#endif
+
+
+/*
+ * Allow constant folding
+ */
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#  define __swab16(x) \
+(__builtin_constant_p((__u16)(x)) ? \
+ ___swab16((x)) : \
+ __fswab16((x)))
+#  define __swab24(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab24((x)) : \
+ __fswab24((x)))
+#  define __swab32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab32((x)) : \
+ __fswab32((x)))
+#  define __swab64(x) \
+(__builtin_constant_p((__u64)(x)) ? \
+ ___swab64((x)) : \
+ __fswab64((x)))
+#else
+#  define __swab16(x) __fswab16(x)
+#  define __swab24(x) __fswab24(x)
+#  define __swab32(x) __fswab32(x)
+#  define __swab64(x) __fswab64(x)
+#endif /* OPTIMIZE */
+
+
+static __inline__ __const__ __u16 __fswab16(__u16 x)
+{
+       return __arch__swab16(x);
+}
+static __inline__ __u16 __swab16p(__u16 *x)
+{
+       return __arch__swab16p(x);
+}
+static __inline__ void __swab16s(__u16 *addr)
+{
+       __arch__swab16s(addr);
+}
+
+static __inline__ __const__ __u32 __fswab24(__u32 x)
+{
+       return __arch__swab24(x);
+}
+static __inline__ __u32 __swab24p(__u32 *x)
+{
+       return __arch__swab24p(x);
+}
+static __inline__ void __swab24s(__u32 *addr)
+{
+       __arch__swab24s(addr);
+}
+
+static __inline__ __const__ __u32 __fswab32(__u32 x)
+{
+       return __arch__swab32(x);
+}
+static __inline__ __u32 __swab32p(__u32 *x)
+{
+       return __arch__swab32p(x);
+}
+static __inline__ void __swab32s(__u32 *addr)
+{
+       __arch__swab32s(addr);
+}
+
+#ifdef __BYTEORDER_HAS_U64__
+static __inline__ __const__ __u64 __fswab64(__u64 x)
+{
+#  ifdef __SWAB_64_THRU_32__
+       __u32 h = x >> 32;
+        __u32 l = x & ((1ULL<<32)-1);
+        return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
+#  else
+       return __arch__swab64(x);
+#  endif
+}
+static __inline__ __u64 __swab64p(__u64 *x)
+{
+       return __arch__swab64p(x);
+}
+static __inline__ void __swab64s(__u64 *addr)
+{
+       __arch__swab64s(addr);
+}
+#endif /* __BYTEORDER_HAS_U64__ */
+
+#if defined(__KERNEL__)
+#define swab16 __swab16
+#define swab24 __swab24
+#define swab32 __swab32
+#define swab64 __swab64
+#define swab16p __swab16p
+#define swab24p __swab24p
+#define swab32p __swab32p
+#define swab64p __swab64p
+#define swab16s __swab16s
+#define swab24s __swab24s
+#define swab32s __swab32s
+#define swab64s __swab64s
+#endif
+
+#endif /* swab */
+
+
+
+#if 1 /* generic */
+
+/*
+ * linux/byteorder_generic.h
+ * Generic Byte-reordering support
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19970707
+ *    gathered all the good ideas from all asm-foo/byteorder.h into one file,
+ *    cleaned them up.
+ *    I hope it is compliant with non-GCC compilers.
+ *    I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
+ *    because I wasn't sure it would be ok to put it in types.h
+ *    Upgraded it to 2.1.43
+ * Francois-Rene Rideau <fare@tunes.org> 19971012
+ *    Upgraded it to 2.1.57
+ *    to please Linus T., replaced huge #ifdef's between little/big endian
+ *    by nestedly #include'd files.
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ *    Made it to 2.1.71; now a facelift:
+ *    Put files under include/linux/byteorder/
+ *    Split swab from generic support.
+ *
+ * TODO:
+ *   = Regular kernel maintainers could also replace all these manual
+ *    byteswap macros that remain, disseminated among drivers,
+ *    after some grep or the sources...
+ *   = Linus might want to rename all these macros and files to fit his taste,
+ *    to fit his personal naming scheme.
+ *   = it seems that a few drivers would also appreciate
+ *    nybble swapping support...
+ *   = every architecture could add their byteswap macro in asm/byteorder.h
+ *    see how some architectures already do (i386, alpha, ppc, etc)
+ *   = cpu_to_beXX and beXX_to_cpu might some day need to be well
+ *    distinguished throughout the kernel. This is not the case currently,
+ *    since little endian, big endian, and pdp endian machines needn't it.
+ *    But this might be the case for, say, a port of Linux to 20/21 bit
+ *    architectures (and F21 Linux addict around?).
+ */
+
+/*
+ * The following macros are to be defined by <asm/byteorder.h>:
+ *
+ * Conversion of long and short int between network and host format
+ *     ntohl(__u32 x)
+ *     ntohs(__u16 x)
+ *     htonl(__u32 x)
+ *     htons(__u16 x)
+ * It seems that some programs (which? where? or perhaps a standard? POSIX?)
+ * might like the above to be functions, not macros (why?).
+ * if that's true, then detect them, and take measures.
+ * Anyway, the measure is: define only ___ntohl as a macro instead,
+ * and in a separate file, have
+ * unsigned long inline ntohl(x){return ___ntohl(x);}
+ *
+ * The same for constant arguments
+ *     __constant_ntohl(__u32 x)
+ *     __constant_ntohs(__u16 x)
+ *     __constant_htonl(__u32 x)
+ *     __constant_htons(__u16 x)
+ *
+ * Conversion of XX-bit integers (16- 32- or 64-)
+ * between native CPU format and little/big endian format
+ * 64-bit stuff only defined for proper architectures
+ *     cpu_to_[bl]eXX(__uXX x)
+ *     [bl]eXX_to_cpu(__uXX x)
+ *
+ * The same, but takes a pointer to the value to convert
+ *     cpu_to_[bl]eXXp(__uXX x)
+ *     [bl]eXX_to_cpup(__uXX x)
+ *
+ * The same, but change in situ
+ *     cpu_to_[bl]eXXs(__uXX x)
+ *     [bl]eXX_to_cpus(__uXX x)
+ *
+ * See asm-foo/byteorder.h for examples of how to provide
+ * architecture-optimized versions
+ *
+ */
+
+
+#if defined(__KERNEL__)
+/*
+ * inside the kernel, we can use nicknames;
+ * outside of it, we must avoid POSIX namespace pollution...
+ */
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+#endif
+
+
+/*
+ * Handle ntohl and suches. These have various compatibility
+ * issues - like we want to give the prototype even though we
+ * also have a macro for them in case some strange program
+ * wants to take the address of the thing or something..
+ *
+ * Note that these used to return a "long" in libc5, even though
+ * long is often 64-bit these days.. Thus the casts.
+ *
+ * They have to be macros in order to do the constant folding
+ * correctly - if the argument passed into a inline function
+ * it is no longer constant according to gcc..
+ */
+
+#undef ntohl
+#undef ntohs
+#undef htonl
+#undef htons
+
+/*
+ * Do the prototypes. Somebody might want to take the
+ * address or some such sick thing..
+ */
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+extern __u32                   ntohl(__u32);
+extern __u32                   htonl(__u32);
+#else
+extern unsigned long int       ntohl(unsigned long int);
+extern unsigned long int       htonl(unsigned long int);
+#endif
+extern unsigned short int      ntohs(unsigned short int);
+extern unsigned short int      htons(unsigned short int);
+
+
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) && !defined(__STRICT_ANSI__)
+
+#define ___htonl(x) __cpu_to_be32(x)
+#define ___htons(x) __cpu_to_be16(x)
+#define ___ntohl(x) __be32_to_cpu(x)
+#define ___ntohs(x) __be16_to_cpu(x)
+
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+#define htonl(x) ___htonl(x)
+#define ntohl(x) ___ntohl(x)
+#else
+#define htonl(x) ((unsigned long)___htonl(x))
+#define ntohl(x) ((unsigned long)___ntohl(x))
+#endif
+#define htons(x) ___htons(x)
+#define ntohs(x) ___ntohs(x)
+
+#endif /* OPTIMIZE */
+
+#endif /* generic */
+
+
+#define __constant_htonl(x) ___constant_swab32((x))
+#define __constant_ntohl(x) ___constant_swab32((x))
+#define __constant_htons(x) ___constant_swab16((x))
+#define __constant_ntohs(x) ___constant_swab16((x))
+#define __constant_cpu_to_le64(x) ((__u64)(x))
+#define __constant_le64_to_cpu(x) ((__u64)(x))
+#define __constant_cpu_to_le32(x) ((__u32)(x))
+#define __constant_le32_to_cpu(x) ((__u32)(x))
+#define __constant_cpu_to_le24(x) ((__u32)(x))
+#define __constant_le24_to_cpu(x) ((__u32)(x))
+#define __constant_cpu_to_le16(x) ((__u16)(x))
+#define __constant_le16_to_cpu(x) ((__u16)(x))
+#define __constant_cpu_to_be64(x) ___constant_swab64((x))
+#define __constant_be64_to_cpu(x) ___constant_swab64((x))
+#define __constant_cpu_to_be32(x) ___constant_swab32((x))
+#define __constant_be32_to_cpu(x) ___constant_swab32((x))
+#define __constant_cpu_to_be24(x) ___constant_swab24((x))
+#define __constant_be24_to_cpu(x) ___constant_swab24((x))
+#define __constant_cpu_to_be16(x) ___constant_swab16((x))
+#define __constant_be16_to_cpu(x) ___constant_swab16((x))
+#define __cpu_to_le64(x) ((__u64)(x))
+#define __le64_to_cpu(x) ((__u64)(x))
+#define __cpu_to_le32(x) ((__u32)(x))
+#define __le32_to_cpu(x) ((__u32)(x))
+#define __cpu_to_le24(x) ((__u32)(x))
+#define __le24_to_cpu(x) ((__u32)(x))
+#define __cpu_to_le16(x) ((__u16)(x))
+#define __le16_to_cpu(x) ((__u16)(x))
+#define __cpu_to_be64(x) __swab64((x))
+#define __be64_to_cpu(x) __swab64((x))
+#define __cpu_to_be32(x) __swab32((x))
+#define __be32_to_cpu(x) __swab32((x))
+#define __cpu_to_be24(x) __swab24((x))
+#define __be24_to_cpu(x) __swab24((x))
+#define __cpu_to_be16(x) __swab16((x))
+#define __be16_to_cpu(x) __swab16((x))
+#define __cpu_to_le64p(x) (*(__u64*)(x))
+#define __le64_to_cpup(x) (*(__u64*)(x))
+#define __cpu_to_le32p(x) (*(__u32*)(x))
+#define __le32_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_le24p(x) (*(__u32*)(x))
+#define __le24_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_le16p(x) (*(__u16*)(x))
+#define __le16_to_cpup(x) (*(__u16*)(x))
+#define __cpu_to_be64p(x) __swab64p((x))
+#define __be64_to_cpup(x) __swab64p((x))
+#define __cpu_to_be32p(x) __swab32p((x))
+#define __be32_to_cpup(x) __swab32p((x))
+#define __cpu_to_be24p(x) __swab24p((x))
+#define __be24_to_cpup(x) __swab24p((x))
+#define __cpu_to_be16p(x) __swab16p((x))
+#define __be16_to_cpup(x) __swab16p((x))
+#define __cpu_to_le64s(x) do {} while (0)
+#define __le64_to_cpus(x) do {} while (0)
+#define __cpu_to_le32s(x) do {} while (0)
+#define __le32_to_cpus(x) do {} while (0)
+#define __cpu_to_le24s(x) do {} while (0)
+#define __le24_to_cpus(x) do {} while (0)
+#define __cpu_to_le16s(x) do {} while (0)
+#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) __swab64s((x))
+#define __be64_to_cpus(x) __swab64s((x))
+#define __cpu_to_be32s(x) __swab32s((x))
+#define __be32_to_cpus(x) __swab32s((x))
+#define __cpu_to_be24s(x) __swab24s((x))
+#define __be24_to_cpus(x) __swab24s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+
+
+
+
+
+
+
+#if 1
+
+/* Dummy types */
+
+#define ____cacheline_aligned
+
+typedef struct 
+{
+  volatile unsigned int lock;
+} rwlock_t;
+
+typedef struct {
+       volatile unsigned int lock;
+} spinlock_t;
+
+struct task_struct;
+
+
+
+
+
+#if 1 /* atomic */
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK "lock ; "
+#else
+#define LOCK ""
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically reads the value of @v.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+#define atomic_read(v)         ((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ * 
+ * Atomically sets the value of @v to @i.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+#define atomic_set(v,i)                (((v)->counter) = (i))
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically adds @i to @v.  Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+#if 0
+       __asm__ __volatile__(
+               LOCK "addl %1,%0"
+               :"=m" (v->counter)
+               :"ir" (i), "m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically subtracts @i from @v.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+#if 0
+       __asm__ __volatile__(
+               LOCK "subl %1,%0"
+               :"=m" (v->counter)
+               :"ir" (i), "m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
+{
+#if 0
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "subl %2,%0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"ir" (i), "m" (v->counter) : "memory");
+       return c;
+#endif
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically increments @v by 1.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+static __inline__ void atomic_inc(atomic_t *v)
+{
+#if 0
+       __asm__ __volatile__(
+               LOCK "incl %0"
+               :"=m" (v->counter)
+               :"m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically decrements @v by 1.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+static __inline__ void atomic_dec(atomic_t *v)
+{
+#if 0
+       __asm__ __volatile__(
+               LOCK "decl %0"
+               :"=m" (v->counter)
+               :"m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{
+#if 0
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "decl %0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"m" (v->counter) : "memory");
+       return c != 0;
+#else
+  return 1;
+#endif
+}
+
+/**
+ * atomic_inc_and_test - increment and test 
+ * @v: pointer of type atomic_t
+ * 
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+static __inline__ int atomic_inc_and_test(atomic_t *v)
+{
+#if 0
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "incl %0; sete %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"m" (v->counter) : "memory");
+       return c != 0;
+#else
+  return 1;
+#endif
+}
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ * 
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */ 
+static __inline__ int atomic_add_negative(int i, atomic_t *v)
+{
+#if 0
+       unsigned char c;
+
+       __asm__ __volatile__(
+               LOCK "addl %2,%0; sets %1"
+               :"=m" (v->counter), "=qm" (c)
+               :"ir" (i), "m" (v->counter) : "memory");
+       return c;
+#else
+  return 0;
+#endif
+}
+
+/* These are x86-specific, used by some header files */
+#define atomic_clear_mask(mask, addr)
+#if 0
+__asm__ __volatile__(LOCK "andl %0,%1" \
+: : "r" (~(mask)),"m" (*addr) : "memory")
+#endif
+
+#define atomic_set_mask(mask, addr)
+#if 0
+__asm__ __volatile__(LOCK "orl %0,%1" \
+: : "r" (mask),"m" (*addr) : "memory")
+#endif
+
+/* Atomic operations are already serializing on x86 */
+#define smp_mb__before_atomic_dec()
+#define smp_mb__after_atomic_dec()
+#define smp_mb__before_atomic_inc()
+#define smp_mb__after_atomic_inc()
+
+
+
+#endif /* atomic */
+
+
+
+
+
+#if 1 /* list */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+#if 0
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+#endif
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+#if 0
+       __list_add(new, head, head->next);
+#endif
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+#if 0
+       __list_add(new, head->prev, head);
+#endif
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+#if 0
+       __list_del(entry->prev, entry->next);
+       entry->next = (void *) 0;
+       entry->prev = (void *) 0;
+#endif
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+#if 0
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry); 
+#endif
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+#if 0
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+#endif
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+                                 struct list_head *head)
+{
+#if 0
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+#endif
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+       return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+                                struct list_head *head)
+{
+#if 0
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+       struct list_head *at = head->next;
+
+       first->prev = head;
+       head->next = first;
+
+       last->next = at;
+       at->prev = last;
+#endif
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+#if 0
+       if (!list_empty(list))
+               __list_splice(list, head);
+#endif
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+                                   struct list_head *head)
+{
+#if 0
+       if (!list_empty(list)) {
+               __list_splice(list, head);
+               INIT_LIST_HEAD(list);
+       }
+#endif
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member)
+#if 0
+       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+#endif
+
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head)
+#if 0
+       for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+               pos = pos->next, prefetch(pos->next))
+#endif
+
+/**
+ * list_for_each_prev  -       iterate over a list backwards
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each_prev(pos, head)
+#if 0
+       for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+               pos = pos->prev, prefetch(pos->prev))
+#endif         
+
+/**
+ * list_for_each_safe  -       iterate over a list safe against removal of list entry
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head)
+#if 0
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+#endif
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)
+#if 0
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+                    prefetch(pos->member.next);                        \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member),  \
+                    prefetch(pos->member.next))
+#endif
+
+#endif /* list */
+
+
+
+
+
+#if 1 /* wait */
+
+#define WNOHANG                0x00000001
+#define WUNTRACED      0x00000002
+
+#define __WNOTHREAD    0x20000000      /* Don't wait on children of other threads in this group */
+#define __WALL         0x40000000      /* Wait on all children, regardless of type */
+#define __WCLONE       0x80000000      /* Wait only on non-SIGCHLD children */
+
+#if 0
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/stddef.h>
+#include <linux/spinlock.h>
+#include <linux/config.h>
+
+#include <asm/page.h>
+#include <asm/processor.h>
+#endif
+
+/*
+ * Debug control.  Slow but useful.
+ */
+#if defined(CONFIG_DEBUG_WAITQ)
+#define WAITQUEUE_DEBUG 1
+#else
+#define WAITQUEUE_DEBUG 0
+#endif
+
+struct __wait_queue {
+       unsigned int flags;
+#define WQ_FLAG_EXCLUSIVE      0x01
+       struct task_struct * task;
+       struct list_head task_list;
+#if WAITQUEUE_DEBUG
+       long __magic;
+       long __waker;
+#endif
+};
+typedef struct __wait_queue wait_queue_t;
+
+/*
+ * 'dual' spinlock architecture. Can be switched between spinlock_t and
+ * rwlock_t locks via changing this define. Since waitqueues are quite
+ * decoupled in the new architecture, lightweight 'simple' spinlocks give
+ * us slightly better latencies and smaller waitqueue structure size.
+ */
+#define USE_RW_WAIT_QUEUE_SPINLOCK 0
+
+#if USE_RW_WAIT_QUEUE_SPINLOCK
+# define wq_lock_t rwlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED RW_LOCK_UNLOCKED
+
+# define wq_read_lock read_lock
+# define wq_read_lock_irqsave read_lock_irqsave
+# define wq_read_unlock_irqrestore read_unlock_irqrestore
+# define wq_read_unlock read_unlock
+# define wq_write_lock_irq write_lock_irq
+# define wq_write_lock_irqsave write_lock_irqsave
+# define wq_write_unlock_irqrestore write_unlock_irqrestore
+# define wq_write_unlock write_unlock
+#else
+# define wq_lock_t spinlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
+
+# define wq_read_lock spin_lock
+# define wq_read_lock_irqsave spin_lock_irqsave
+# define wq_read_unlock spin_unlock
+# define wq_read_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_lock_irq spin_lock_irq
+# define wq_write_lock_irqsave spin_lock_irqsave
+# define wq_write_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_unlock spin_unlock
+#endif
+
+struct __wait_queue_head {
+       wq_lock_t lock;
+       struct list_head task_list;
+#if WAITQUEUE_DEBUG
+       long __magic;
+       long __creator;
+#endif
+};
+typedef struct __wait_queue_head wait_queue_head_t;
+
+
+/*
+ * Debugging macros.  We eschew `do { } while (0)' because gcc can generate
+ * spurious .aligns.
+ */
+#if WAITQUEUE_DEBUG
+#define WQ_BUG()       BUG()
+#define CHECK_MAGIC(x)
+#if 0
+       do {                                                                    \
+               if ((x) != (long)&(x)) {                                        \
+                       printk("bad magic %lx (should be %lx), ",               \
+                               (long)x, (long)&(x));                           \
+                       WQ_BUG();                                               \
+               }                                                               \
+       } while (0)
+#endif
+
+#define CHECK_MAGIC_WQHEAD(x)
+#if 0
+       do {                                                                    \
+               if ((x)->__magic != (long)&((x)->__magic)) {                    \
+                       printk("bad magic %lx (should be %lx, creator %lx), ",  \
+                       (x)->__magic, (long)&((x)->__magic), (x)->__creator);   \
+                       WQ_BUG();                                               \
+               }                                                               \
+       } while (0)
+#endif
+
+#define WQ_CHECK_LIST_HEAD(list)
+#if 0
+       do {                                                                    \
+               if (!(list)->next || !(list)->prev)                             \
+                       WQ_BUG();                                               \
+       } while(0)
+#endif
+
+#define WQ_NOTE_WAKER(tsk)
+#if 0
+       do {                                                                    \
+               (tsk)->__waker = (long)__builtin_return_address(0);             \
+       } while (0)
+#endif
+#else
+#define WQ_BUG()
+#define CHECK_MAGIC(x)
+#define CHECK_MAGIC_WQHEAD(x)
+#define WQ_CHECK_LIST_HEAD(list)
+#define WQ_NOTE_WAKER(tsk)
+#endif
+
+/*
+ * Macros for declaration and initialisaton of the datatypes
+ */
+
+#if WAITQUEUE_DEBUG
+# define __WAITQUEUE_DEBUG_INIT(name) //(long)&(name).__magic, 0
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name) //(long)&(name).__magic, (long)&(name).__magic
+#else
+# define __WAITQUEUE_DEBUG_INIT(name)
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name)
+#endif
+
+#define __WAITQUEUE_INITIALIZER(name, tsk)
+#if 0
+{
+       task:           tsk,                                            \
+       task_list:      { NULL, NULL },                                 \
+                        __WAITQUEUE_DEBUG_INIT(name)}
+#endif
+
+#define DECLARE_WAITQUEUE(name, tsk)
+#if 0
+       wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
+#endif
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name)
+#if 0
+{
+       lock:           WAITQUEUE_RW_LOCK_UNLOCKED,                     \
+       task_list:      { &(name).task_list, &(name).task_list },       \
+                       __WAITQUEUE_HEAD_DEBUG_INIT(name)}
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(name)
+#if 0
+       wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
+#endif
+
+static inline void init_waitqueue_head(wait_queue_head_t *q)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!q)
+               WQ_BUG();
+#endif
+       q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;
+       INIT_LIST_HEAD(&q->task_list);
+#if WAITQUEUE_DEBUG
+       q->__magic = (long)&q->__magic;
+       q->__creator = (long)current_text_addr();
+#endif
+#endif
+}
+
+static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!q || !p)
+               WQ_BUG();
+#endif
+       q->flags = 0;
+       q->task = p;
+#if WAITQUEUE_DEBUG
+       q->__magic = (long)&q->__magic;
+#endif
+#endif
+}
+
+static inline int waitqueue_active(wait_queue_head_t *q)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!q)
+               WQ_BUG();
+       CHECK_MAGIC_WQHEAD(q);
+#endif
+
+       return !list_empty(&q->task_list);
+#endif
+}
+
+static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!head || !new)
+               WQ_BUG();
+       CHECK_MAGIC_WQHEAD(head);
+       CHECK_MAGIC(new->__magic);
+       if (!head->task_list.next || !head->task_list.prev)
+               WQ_BUG();
+#endif
+       list_add(&new->task_list, &head->task_list);
+#endif
+}
+
+/*
+ * Used for wake-one threads:
+ */
+static inline void __add_wait_queue_tail(wait_queue_head_t *head,
+                                               wait_queue_t *new)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!head || !new)
+               WQ_BUG();
+       CHECK_MAGIC_WQHEAD(head);
+       CHECK_MAGIC(new->__magic);
+       if (!head->task_list.next || !head->task_list.prev)
+               WQ_BUG();
+#endif
+       list_add_tail(&new->task_list, &head->task_list);
+#endif
+}
+
+static inline void __remove_wait_queue(wait_queue_head_t *head,
+                                                       wait_queue_t *old)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+       if (!old)
+               WQ_BUG();
+       CHECK_MAGIC(old->__magic);
+#endif
+       list_del(&old->task_list);
+#endif
+}
+
+
+
+
+#endif /* wait */
+
+
+#endif
+
+
+
+
+#if 1 /* slab */
+
+typedef struct
+{
+ int x;
+} kmem_cache_s;
+
+typedef struct kmem_cache_s kmem_cache_t;
+
+#if 0
+#include       <linux/mm.h>
+#include       <linux/cache.h>
+#endif
+
+/* flags for kmem_cache_alloc() */
+#define        SLAB_NOFS               GFP_NOFS
+#define        SLAB_NOIO               GFP_NOIO
+#define SLAB_NOHIGHIO          GFP_NOHIGHIO
+#define        SLAB_ATOMIC             GFP_ATOMIC
+#define        SLAB_USER               GFP_USER
+#define        SLAB_KERNEL             GFP_KERNEL
+#define        SLAB_NFS                GFP_NFS
+#define        SLAB_DMA                GFP_DMA
+
+#define SLAB_LEVEL_MASK                (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_HIGHIO|__GFP_FS)
+#define        SLAB_NO_GROW            0x00001000UL    /* don't grow a cache */
+
+/* flags to pass to kmem_cache_create().
+ * The first 3 are only valid when the allocator as been build
+ * SLAB_DEBUG_SUPPORT.
+ */
+#define        SLAB_DEBUG_FREE         0x00000100UL    /* Peform (expensive) checks on free */
+#define        SLAB_DEBUG_INITIAL      0x00000200UL    /* Call constructor (as verifier) */
+#define        SLAB_RED_ZONE           0x00000400UL    /* Red zone objs in a cache */
+#define        SLAB_POISON             0x00000800UL    /* Poison objects */
+#define        SLAB_NO_REAP            0x00001000UL    /* never reap from the cache */
+#define        SLAB_HWCACHE_ALIGN      0x00002000UL    /* align objs on a h/w cache lines */
+#define SLAB_CACHE_DMA         0x00004000UL    /* use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN        0x00008000UL    /* force alignment */
+
+/* flags passed to a constructor func */
+#define        SLAB_CTOR_CONSTRUCTOR   0x001UL         /* if not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC       0x002UL         /* tell constructor it can't sleep */
+#define        SLAB_CTOR_VERIFY        0x004UL         /* tell constructor it's a verify call */
+
+/* prototypes */
+extern void kmem_cache_init(void);
+extern void kmem_cache_sizes_init(void);
+
+extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
+extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
+                                      void (*)(void *, kmem_cache_t *, unsigned long),
+                                      void (*)(void *, kmem_cache_t *, unsigned long));
+extern int kmem_cache_destroy(kmem_cache_t *);
+extern int kmem_cache_shrink(kmem_cache_t *);
+extern void *kmem_cache_alloc(kmem_cache_t *, int);
+extern void kmem_cache_free(kmem_cache_t *, void *);
+extern unsigned int kmem_cache_size(kmem_cache_t *);
+
+extern void *kmalloc(size_t, int);
+extern void kfree(const void *);
+
+//extern int FASTCALL(kmem_cache_reap(int));
+
+/* System wide caches */
+extern kmem_cache_t    *vm_area_cachep;
+extern kmem_cache_t    *mm_cachep;
+extern kmem_cache_t    *names_cachep;
+extern kmem_cache_t    *files_cachep;
+extern kmem_cache_t    *filp_cachep;
+extern kmem_cache_t    *dquot_cachep;
+extern kmem_cache_t    *bh_cachep;
+extern kmem_cache_t    *fs_cachep;
+extern kmem_cache_t    *sigact_cachep;
+
+#endif /* slab */
+
+
+
+/*
+ *     Berkeley style UIO structures   -       Alan Cox 1994.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+
+
+/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
+   library one from sys/uio.h if you have a very old library set */
+
+struct iovec
+{
+       void *iov_base;         /* BSD uses caddr_t (1003.1g requires void *) */
+       __kernel_size_t iov_len; /* Must be size_t (1003.1g) */
+};
+
+/*
+ *     UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
+ */
+#define UIO_FASTIOV    8
+#define UIO_MAXIOV     1024
+#if 0
+#define UIO_MAXIOV     16      /* Maximum iovec's in one operation 
+                                  16 matches BSD */
+                                /* Beg pardon: BSD has 1024 --ANK */
+#endif
+
+
+
+/*
+ * In Linux 2.4, static timers have been removed from the kernel.
+ * Timers may be dynamically created and destroyed, and should be initialized
+ * by a call to init_timer() upon creation.
+ *
+ * The "data" field enables use of a common timeout function for several
+ * timeouts. You can use this field to distinguish between the different
+ * invocations.
+ */
+struct timer_list {
+       struct list_head list;
+       unsigned long expires;
+       unsigned long data;
+       void (*function)(unsigned long);
+};
+
+
+
+struct timeval {
+  unsigned long tv_sec;
+  unsigned long tv_usec;
+//     time_t          tv_sec;         /* seconds */
+//     suseconds_t     tv_usec;        /* microseconds */
+};
+
+
+
+
+
+
+
+#if 1 /* poll */
+
+struct file;
+
+struct poll_table_page;
+
+typedef struct poll_table_struct {
+       int error;
+       struct poll_table_page * table;
+} poll_table;
+
+extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p);
+
+static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
+{
+       if (p && wait_address)
+               __pollwait(filp, wait_address, p);
+}
+
+static inline void poll_initwait(poll_table* pt)
+{
+       pt->error = 0;
+       pt->table = NULL;
+}
+extern void poll_freewait(poll_table* pt);
+
+
+/*
+ * Scaleable version of the fd_set.
+ */
+
+typedef struct {
+       unsigned long *in, *out, *ex;
+       unsigned long *res_in, *res_out, *res_ex;
+} fd_set_bits;
+
+/*
+ * How many longwords for "nr" bits?
+ */
+#define FDS_BITPERLONG (8*sizeof(long))
+#define FDS_LONGS(nr)  (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
+#define FDS_BYTES(nr)  (FDS_LONGS(nr)*sizeof(long))
+
+/*
+ * We do a VERIFY_WRITE here even though we are only reading this time:
+ * we'll write to it eventually..
+ *
+ * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
+ */
+static inline
+int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+#if 0
+       nr = FDS_BYTES(nr);
+       if (ufdset) {
+               int error;
+               error = verify_area(VERIFY_WRITE, ufdset, nr);
+               if (!error && __copy_from_user(fdset, ufdset, nr))
+                       error = -EFAULT;
+               return error;
+       }
+       memset(fdset, 0, nr);
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+static inline
+void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+#if 0
+       if (ufdset)
+               __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+#endif
+}
+
+static inline
+void zero_fd_set(unsigned long nr, unsigned long *fdset)
+{
+#if 0
+       memset(fdset, 0, FDS_BYTES(nr));
+#endif
+}
+
+extern int do_select(int n, fd_set_bits *fds, long *timeout);
+
+#endif /* poll */
+
+
+
+typedef struct
+{
+  int x;
+} read_descriptor_t;
+
+
+
+
+
+#if 1 /* poll */
+
+/* These are specified by iBCS2 */
+#define POLLIN         0x0001
+#define POLLPRI                0x0002
+#define POLLOUT                0x0004
+#define POLLERR                0x0008
+#define POLLHUP                0x0010
+#define POLLNVAL       0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM     0x0040
+#define POLLRDBAND     0x0080
+#define POLLWRNORM     0x0100
+#define POLLWRBAND     0x0200
+#define POLLMSG                0x0400
+
+struct pollfd {
+       int fd;
+       short events;
+       short revents;
+};
+
+#endif /* poll */
+
+#endif /* _LINUX_TYPES_H */
diff --git a/drivers/net/tcpip/include/tcpcore.h b/drivers/net/tcpip/include/tcpcore.h
new file mode 100755 (executable)
index 0000000..cda54ed
--- /dev/null
@@ -0,0 +1,3856 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        include/tcpcore.h
+ * PURPOSE:     Transmission Control Protocol definitions
+ * REVISIONS:
+ *   CSH 01/01-2003 Ported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Definitions for the TCP module.
+ *
+ * Version:    @(#)tcp.h       1.0.5   05/23/93
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+#ifndef __TCPCORE_H
+#define __TCPCORE_H
+
+#include "tcpdef.h"
+
+
+struct socket;
+
+
+
+#if 1 /* skbuff */
+
+#define HAVE_ALLOC_SKB         /* For the drivers to know */
+#define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */
+#define SLAB_SKB               /* Slabified skbuffs       */
+
+#define CHECKSUM_NONE 0
+#define CHECKSUM_HW 1
+#define CHECKSUM_UNNECESSARY 2
+
+#define SKB_DATA_ALIGN(X)      (((X) + (SMP_CACHE_BYTES-1)) & ~(SMP_CACHE_BYTES-1))
+#define SKB_MAX_ORDER(X,ORDER) (((PAGE_SIZE<<(ORDER)) - (X) - sizeof(struct skb_shared_info))&~(SMP_CACHE_BYTES-1))
+#define SKB_MAX_HEAD(X)                (SKB_MAX_ORDER((X),0))
+#define SKB_MAX_ALLOC          (SKB_MAX_ORDER(0,2))
+
+/* A. Checksumming of received packets by device.
+ *
+ *     NONE: device failed to checksum this packet.
+ *             skb->csum is undefined.
+ *
+ *     UNNECESSARY: device parsed packet and wouldbe verified checksum.
+ *             skb->csum is undefined.
+ *           It is bad option, but, unfortunately, many of vendors do this.
+ *           Apparently with secret goal to sell you new device, when you
+ *           will add new protocol to your host. F.e. IPv6. 8)
+ *
+ *     HW: the most generic way. Device supplied checksum of _all_
+ *         the packet as seen by netif_rx in skb->csum.
+ *         NOTE: Even if device supports only some protocols, but
+ *         is able to produce some skb->csum, it MUST use HW,
+ *         not UNNECESSARY.
+ *
+ * B. Checksumming on output.
+ *
+ *     NONE: skb is checksummed by protocol or csum is not required.
+ *
+ *     HW: device is required to csum packet as seen by hard_start_xmit
+ *     from skb->h.raw to the end and to record the checksum
+ *     at skb->h.raw+skb->csum.
+ *
+ *     Device must show its capabilities in dev->features, set
+ *     at device setup time.
+ *     NETIF_F_HW_CSUM - it is clever device, it is able to checksum
+ *                       everything.
+ *     NETIF_F_NO_CSUM - loopback or reliable single hop media.
+ *     NETIF_F_IP_CSUM - device is dumb. It is able to csum only
+ *                       TCP/UDP over IPv4. Sigh. Vendors like this
+ *                       way by an unknown reason. Though, see comment above
+ *                       about CHECKSUM_UNNECESSARY. 8)
+ *
+ *     Any questions? No questions, good.              --ANK
+ */
+
+#ifdef __i386__
+#define NET_CALLER(arg) (*(((void**)&arg)-1))
+#else
+#define NET_CALLER(arg) __builtin_return_address(0)
+#endif
+
+#ifdef CONFIG_NETFILTER
+struct nf_conntrack {
+       atomic_t use;
+       void (*destroy)(struct nf_conntrack *);
+};
+
+struct nf_ct_info {
+       struct nf_conntrack *master;
+};
+#endif
+
+struct sk_buff_head {
+       /* These two members must be first. */
+       struct sk_buff  * next;
+       struct sk_buff  * prev;
+
+       __u32           qlen;
+       spinlock_t      lock;
+};
+
+struct sk_buff;
+
+#define MAX_SKB_FRAGS 6
+
+typedef struct skb_frag_struct skb_frag_t;
+
+struct skb_frag_struct
+{
+       struct page *page;
+       __u16 page_offset;
+       __u16 size;
+};
+
+/* This data is invariant across clones and lives at
+ * the end of the header data, ie. at skb->end.
+ */
+struct skb_shared_info {
+       atomic_t        dataref;
+       unsigned int    nr_frags;
+       struct sk_buff  *frag_list;
+       skb_frag_t      frags[MAX_SKB_FRAGS];
+};
+
+struct sk_buff {
+       /* These two members must be first. */
+       struct sk_buff  * next;                 /* Next buffer in list                          */
+       struct sk_buff  * prev;                 /* Previous buffer in list                      */
+
+       struct sk_buff_head * list;             /* List we are on                               */
+       struct sock     *sk;                    /* Socket we are owned by                       */
+       struct timeval  stamp;                  /* Time we arrived                              */
+       struct net_device       *dev;           /* Device we arrived on/are leaving by          */
+
+       /* Transport layer header */
+       union
+       {
+               struct tcphdr   *th;
+               struct udphdr   *uh;
+               struct icmphdr  *icmph;
+               struct igmphdr  *igmph;
+               struct iphdr    *ipiph;
+               struct spxhdr   *spxh;
+               unsigned char   *raw;
+       } h;
+
+       /* Network layer header */
+       union
+       {
+               struct iphdr    *iph;
+               struct ipv6hdr  *ipv6h;
+               struct arphdr   *arph;
+               struct ipxhdr   *ipxh;
+               unsigned char   *raw;
+       } nh;
+  
+       /* Link layer header */
+       union 
+       {       
+               struct ethhdr   *ethernet;
+               unsigned char   *raw;
+       } mac;
+
+       struct  dst_entry *dst;
+
+       /* 
+        * This is the control buffer. It is free to use for every
+        * layer. Please put your private variables there. If you
+        * want to keep them across layers you have to do a skb_clone()
+        * first. This is owned by whoever has the skb queued ATM.
+        */ 
+       char            cb[48];  
+
+       unsigned int    len;                    /* Length of actual data                        */
+       unsigned int    data_len;
+       unsigned int    csum;                   /* Checksum                                     */
+       unsigned char   __unused,               /* Dead field, may be reused                    */
+                       cloned,                 /* head may be cloned (check refcnt to be sure). */
+                       pkt_type,               /* Packet class                                 */
+                       ip_summed;              /* Driver fed us an IP checksum                 */
+       __u32           priority;               /* Packet queueing priority                     */
+       atomic_t        users;                  /* User count - see datagram.c,tcp.c            */
+       unsigned short  protocol;               /* Packet protocol from driver.                 */
+       unsigned short  security;               /* Security level of packet                     */
+       unsigned int    truesize;               /* Buffer size                                  */
+
+       unsigned char   *head;                  /* Head of buffer                               */
+       unsigned char   *data;                  /* Data head pointer                            */
+       unsigned char   *tail;                  /* Tail pointer                                 */
+       unsigned char   *end;                   /* End pointer                                  */
+
+       void            (*destructor)(struct sk_buff *);        /* Destruct function            */
+#ifdef CONFIG_NETFILTER
+       /* Can be used for communication between hooks. */
+        unsigned long  nfmark;
+       /* Cache info */
+       __u32           nfcache;
+       /* Associated connection, if any */
+       struct nf_ct_info *nfct;
+#ifdef CONFIG_NETFILTER_DEBUG
+        unsigned int nf_debug;
+#endif
+#endif /*CONFIG_NETFILTER*/
+
+#if defined(CONFIG_HIPPI)
+       union{
+               __u32   ifield;
+       } private;
+#endif
+
+#ifdef CONFIG_NET_SCHED
+       __u32           tc_index;               /* traffic control index */
+#endif
+};
+
+#define SK_WMEM_MAX    65535
+#define SK_RMEM_MAX    65535
+
+#if 1
+//#ifdef __KERNEL__
+/*
+ *     Handling routines are only of interest to the kernel
+ */
+
+extern void                    __kfree_skb(struct sk_buff *skb);
+extern struct sk_buff *                alloc_skb(unsigned int size, int priority);
+extern void                    kfree_skbmem(struct sk_buff *skb);
+extern struct sk_buff *                skb_clone(struct sk_buff *skb, int priority);
+extern struct sk_buff *                skb_copy(const struct sk_buff *skb, int priority);
+extern struct sk_buff *                pskb_copy(struct sk_buff *skb, int gfp_mask);
+extern int                     pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask);
+extern struct sk_buff *                skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom);
+extern struct sk_buff *                skb_copy_expand(const struct sk_buff *skb, 
+                                               int newheadroom,
+                                               int newtailroom,
+                                               int priority);
+#define dev_kfree_skb(a)       kfree_skb(a)
+extern void    skb_over_panic(struct sk_buff *skb, int len, void *here);
+extern void    skb_under_panic(struct sk_buff *skb, int len, void *here);
+
+/* Internal */
+#define skb_shinfo(SKB)                ((struct skb_shared_info *)((SKB)->end))
+
+/**
+ *     skb_queue_empty - check if a queue is empty
+ *     @list: queue head
+ *
+ *     Returns true if the queue is empty, false otherwise.
+ */
+static inline int skb_queue_empty(struct sk_buff_head *list)
+{
+       return (list->next == (struct sk_buff *) list);
+}
+
+/**
+ *     skb_get - reference buffer
+ *     @skb: buffer to reference
+ *
+ *     Makes another reference to a socket buffer and returns a pointer
+ *     to the buffer.
+ */
+static inline struct sk_buff *skb_get(struct sk_buff *skb)
+{
+       atomic_inc(&skb->users);
+       return skb;
+}
+
+/*
+ * If users==1, we are the only owner and are can avoid redundant
+ * atomic change.
+ */
+/**
+ *     kfree_skb - free an sk_buff
+ *     @skb: buffer to free
+ *
+ *     Drop a reference to the buffer and free it if the usage count has
+ *     hit zero.
+ */
+static inline void kfree_skb(struct sk_buff *skb)
+{
+       if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users))
+               __kfree_skb(skb);
+}
+
+/* Use this if you didn't touch the skb state [for fast switching] */
+static inline void kfree_skb_fast(struct sk_buff *skb)
+{
+       if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users))
+               kfree_skbmem(skb);      
+}
+
+/**
+ *     skb_cloned - is the buffer a clone
+ *     @skb: buffer to check
+ *
+ *     Returns true if the buffer was generated with skb_clone() and is
+ *     one of multiple shared copies of the buffer. Cloned buffers are
+ *     shared data so must not be written to under normal circumstances.
+ */
+
+static inline int skb_cloned(struct sk_buff *skb)
+{
+       return skb->cloned && atomic_read(&skb_shinfo(skb)->dataref) != 1;
+}
+
+/**
+ *     skb_shared - is the buffer shared
+ *     @skb: buffer to check
+ *
+ *     Returns true if more than one person has a reference to this
+ *     buffer.
+ */
+static inline int skb_shared(struct sk_buff *skb)
+{
+       return (atomic_read(&skb->users) != 1);
+}
+
+/** 
+ *     skb_share_check - check if buffer is shared and if so clone it
+ *     @skb: buffer to check
+ *     @pri: priority for memory allocation
+ *     
+ *     If the buffer is shared the buffer is cloned and the old copy
+ *     drops a reference. A new clone with a single reference is returned.
+ *     If the buffer is not shared the original buffer is returned. When
+ *     being called from interrupt status or with spinlocks held pri must
+ *     be GFP_ATOMIC.
+ *
+ *     NULL is returned on a memory allocation failure.
+ */
+static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri)
+{
+       if (skb_shared(skb)) {
+               struct sk_buff *nskb;
+               nskb = skb_clone(skb, pri);
+               kfree_skb(skb);
+               return nskb;
+       }
+       return skb;
+}
+
+
+/*
+ *     Copy shared buffers into a new sk_buff. We effectively do COW on
+ *     packets to handle cases where we have a local reader and forward
+ *     and a couple of other messy ones. The normal one is tcpdumping
+ *     a packet thats being forwarded.
+ */
+/**
+ *     skb_unshare - make a copy of a shared buffer
+ *     @skb: buffer to check
+ *     @pri: priority for memory allocation
+ *
+ *     If the socket buffer is a clone then this function creates a new
+ *     copy of the data, drops a reference count on the old copy and returns
+ *     the new copy with the reference count at 1. If the buffer is not a clone
+ *     the original buffer is returned. When called with a spinlock held or
+ *     from interrupt state @pri must be %GFP_ATOMIC
+ *
+ *     %NULL is returned on a memory allocation failure.
+ */
+static inline struct sk_buff *skb_unshare(struct sk_buff *skb, int pri)
+{
+       struct sk_buff *nskb;
+       if(!skb_cloned(skb))
+               return skb;
+       nskb=skb_copy(skb, pri);
+       kfree_skb(skb);         /* Free our shared copy */
+       return nskb;
+}
+
+/**
+ *     skb_peek
+ *     @list_: list to peek at
+ *
+ *     Peek an &sk_buff. Unlike most other operations you _MUST_
+ *     be careful with this one. A peek leaves the buffer on the
+ *     list and someone else may run off with it. You must hold
+ *     the appropriate locks or have a private queue to do this.
+ *
+ *     Returns %NULL for an empty list or a pointer to the head element.
+ *     The reference count is not incremented and the reference is therefore
+ *     volatile. Use with caution.
+ */
+static inline struct sk_buff *skb_peek(struct sk_buff_head *list_)
+{
+       struct sk_buff *list = ((struct sk_buff *)list_)->next;
+       if (list == (struct sk_buff *)list_)
+               list = NULL;
+       return list;
+}
+
+/**
+ *     skb_peek_tail
+ *     @list_: list to peek at
+ *
+ *     Peek an &sk_buff. Unlike most other operations you _MUST_
+ *     be careful with this one. A peek leaves the buffer on the
+ *     list and someone else may run off with it. You must hold
+ *     the appropriate locks or have a private queue to do this.
+ *
+ *     Returns %NULL for an empty list or a pointer to the tail element.
+ *     The reference count is not incremented and the reference is therefore
+ *     volatile. Use with caution.
+ */
+
+static inline struct sk_buff *skb_peek_tail(struct sk_buff_head *list_)
+{
+       struct sk_buff *list = ((struct sk_buff *)list_)->prev;
+       if (list == (struct sk_buff *)list_)
+               list = NULL;
+       return list;
+}
+
+/**
+ *     skb_queue_len   - get queue length
+ *     @list_: list to measure
+ *
+ *     Return the length of an &sk_buff queue. 
+ */
+static inline __u32 skb_queue_len(struct sk_buff_head *list_)
+{
+       return(list_->qlen);
+}
+
+static inline void skb_queue_head_init(struct sk_buff_head *list)
+{
+       spin_lock_init(&list->lock);
+       list->prev = (struct sk_buff *)list;
+       list->next = (struct sk_buff *)list;
+       list->qlen = 0;
+}
+
+/*
+ *     Insert an sk_buff at the start of a list.
+ *
+ *     The "__skb_xxxx()" functions are the non-atomic ones that
+ *     can only be called with interrupts disabled.
+ */
+
+/**
+ *     __skb_queue_head - queue a buffer at the list head
+ *     @list: list to use
+ *     @newsk: buffer to queue
+ *
+ *     Queue a buffer at the start of a list. This function takes no locks
+ *     and you must therefore hold required locks before calling it.
+ *
+ *     A buffer cannot be placed on two lists at the same time.
+ */    
+static inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+       struct sk_buff *prev, *next;
+
+       newsk->list = list;
+       list->qlen++;
+       prev = (struct sk_buff *)list;
+       next = prev->next;
+       newsk->next = next;
+       newsk->prev = prev;
+       next->prev = newsk;
+       prev->next = newsk;
+}
+
+
+/**
+ *     skb_queue_head - queue a buffer at the list head
+ *     @list: list to use
+ *     @newsk: buffer to queue
+ *
+ *     Queue a buffer at the start of the list. This function takes the
+ *     list lock and can be used safely with other locking &sk_buff functions
+ *     safely.
+ *
+ *     A buffer cannot be placed on two lists at the same time.
+ */    
+
+static inline void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_queue_head(list, newsk);
+       spin_unlock_irqrestore(&list->lock, flags);
+}
+
+/**
+ *     __skb_queue_tail - queue a buffer at the list tail
+ *     @list: list to use
+ *     @newsk: buffer to queue
+ *
+ *     Queue a buffer at the end of a list. This function takes no locks
+ *     and you must therefore hold required locks before calling it.
+ *
+ *     A buffer cannot be placed on two lists at the same time.
+ */    
+
+static inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+       struct sk_buff *prev, *next;
+
+       newsk->list = list;
+       list->qlen++;
+       next = (struct sk_buff *)list;
+       prev = next->prev;
+       newsk->next = next;
+       newsk->prev = prev;
+       next->prev = newsk;
+       prev->next = newsk;
+}
+
+/**
+ *     skb_queue_tail - queue a buffer at the list tail
+ *     @list: list to use
+ *     @newsk: buffer to queue
+ *
+ *     Queue a buffer at the tail of the list. This function takes the
+ *     list lock and can be used safely with other locking &sk_buff functions
+ *     safely.
+ *
+ *     A buffer cannot be placed on two lists at the same time.
+ */    
+
+static inline void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&list->lock, flags);
+       __skb_queue_tail(list, newsk);
+       spin_unlock_irqrestore(&list->lock, flags);
+}
+
+/**
+ *     __skb_dequeue - remove from the head of the queue
+ *     @list: list to dequeue from
+ *
+ *     Remove the head of the list. This function does not take any locks
+ *     so must be used with appropriate locks held only. The head item is
+ *     returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+{
+       struct sk_buff *next, *prev, *result;
+
+       prev = (struct sk_buff *) list;
+       next = prev->next;
+       result = NULL;
+       if (next != prev) {
+               result = next;
+               next = next->next;
+               list->qlen--;
+               next->prev = prev;
+               prev->next = next;
+               result->next = NULL;
+               result->prev = NULL;
+               result->list = NULL;
+       }
+       return result;
+}
+
+/**
+ *     skb_dequeue - remove from the head of the queue
+ *     @list: list to dequeue from
+ *
+ *     Remove the head of the list. The list lock is taken so the function
+ *     may be used safely with other locking list functions. The head item is
+ *     returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
+{
+       unsigned long flags;
+       struct sk_buff *result;
+
+       spin_lock_irqsave(&list->lock, flags);
+       result = __skb_dequeue(list);
+       spin_unlock_irqrestore(&list->lock, flags);
+       return result;
+}
+
+/*
+ *     Insert a packet on a list.
+ */
+
+static inline void __skb_insert(struct sk_buff *newsk,
+       struct sk_buff * prev, struct sk_buff *next,
+       struct sk_buff_head * list)
+{
+       newsk->next = next;
+       newsk->prev = prev;
+       next->prev = newsk;
+       prev->next = newsk;
+       newsk->list = list;
+       list->qlen++;
+}
+
+/**
+ *     skb_insert      -       insert a buffer
+ *     @old: buffer to insert before
+ *     @newsk: buffer to insert
+ *
+ *     Place a packet before a given packet in a list. The list locks are taken
+ *     and this function is atomic with respect to other list locked calls
+ *     A buffer cannot be placed on two lists at the same time.
+ */
+
+static inline void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&old->list->lock, flags);
+       __skb_insert(newsk, old->prev, old, old->list);
+       spin_unlock_irqrestore(&old->list->lock, flags);
+}
+
+/*
+ *     Place a packet after a given packet in a list.
+ */
+
+static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+       __skb_insert(newsk, old, old->next, old->list);
+}
+
+/**
+ *     skb_append      -       append a buffer
+ *     @old: buffer to insert after
+ *     @newsk: buffer to insert
+ *
+ *     Place a packet after a given packet in a list. The list locks are taken
+ *     and this function is atomic with respect to other list locked calls.
+ *     A buffer cannot be placed on two lists at the same time.
+ */
+
+
+static inline void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&old->list->lock, flags);
+       __skb_append(old, newsk);
+       spin_unlock_irqrestore(&old->list->lock, flags);
+}
+
+/*
+ * remove sk_buff from list. _Must_ be called atomically, and with
+ * the list known..
+ */
+static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+{
+       struct sk_buff * next, * prev;
+
+       list->qlen--;
+       next = skb->next;
+       prev = skb->prev;
+       skb->next = NULL;
+       skb->prev = NULL;
+       skb->list = NULL;
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ *     skb_unlink      -       remove a buffer from a list
+ *     @skb: buffer to remove
+ *
+ *     Place a packet after a given packet in a list. The list locks are taken
+ *     and this function is atomic with respect to other list locked calls
+ *     
+ *     Works even without knowing the list it is sitting on, which can be 
+ *     handy at times. It also means that THE LIST MUST EXIST when you 
+ *     unlink. Thus a list must have its contents unlinked before it is
+ *     destroyed.
+ */
+
+static inline void skb_unlink(struct sk_buff *skb)
+{
+       struct sk_buff_head *list = skb->list;
+
+       if(list) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&list->lock, flags);
+               if(skb->list == list)
+                       __skb_unlink(skb, skb->list);
+               spin_unlock_irqrestore(&list->lock, flags);
+       }
+}
+
+/* XXX: more streamlined implementation */
+
+/**
+ *     __skb_dequeue_tail - remove from the tail of the queue
+ *     @list: list to dequeue from
+ *
+ *     Remove the tail of the list. This function does not take any locks
+ *     so must be used with appropriate locks held only. The tail item is
+ *     returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
+{
+       struct sk_buff *skb = skb_peek_tail(list); 
+       if (skb)
+               __skb_unlink(skb, list);
+       return skb;
+}
+
+/**
+ *     skb_dequeue - remove from the head of the queue
+ *     @list: list to dequeue from
+ *
+ *     Remove the head of the list. The list lock is taken so the function
+ *     may be used safely with other locking list functions. The tail item is
+ *     returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
+{
+       unsigned long flags;
+       struct sk_buff *result;
+
+       spin_lock_irqsave(&list->lock, flags);
+       result = __skb_dequeue_tail(list);
+       spin_unlock_irqrestore(&list->lock, flags);
+       return result;
+}
+
+static inline int skb_is_nonlinear(const struct sk_buff *skb)
+{
+       return skb->data_len;
+}
+
+static inline int skb_headlen(const struct sk_buff *skb)
+{
+       return skb->len - skb->data_len;
+}
+
+#define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) out_of_line_bug(); } while (0)
+#define SKB_FRAG_ASSERT(skb) do { if (skb_shinfo(skb)->frag_list) out_of_line_bug(); } while (0)
+#define SKB_LINEAR_ASSERT(skb) do { if (skb_is_nonlinear(skb)) out_of_line_bug(); } while (0)
+
+/*
+ *     Add data to an sk_buff
+ */
+static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+{
+       unsigned char *tmp=skb->tail;
+       SKB_LINEAR_ASSERT(skb);
+       skb->tail+=len;
+       skb->len+=len;
+       return tmp;
+}
+
+/**
+ *     skb_put - add data to a buffer
+ *     @skb: buffer to use 
+ *     @len: amount of data to add
+ *
+ *     This function extends the used data area of the buffer. If this would
+ *     exceed the total buffer size the kernel will panic. A pointer to the
+ *     first byte of the extra data is returned.
+ */
+static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+{
+#if 0
+       unsigned char *tmp=skb->tail;
+       SKB_LINEAR_ASSERT(skb);
+       skb->tail+=len;
+       skb->len+=len;
+       if(skb->tail>skb->end) {
+               skb_over_panic(skb, len, current_text_addr());
+       }
+       return tmp;
+#else
+return NULL;
+#endif
+}
+
+static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+{
+       skb->data-=len;
+       skb->len+=len;
+       return skb->data;
+}
+
+/**
+ *     skb_push - add data to the start of a buffer
+ *     @skb: buffer to use 
+ *     @len: amount of data to add
+ *
+ *     This function extends the used data area of the buffer at the buffer
+ *     start. If this would exceed the total buffer headroom the kernel will
+ *     panic. A pointer to the first byte of the extra data is returned.
+ */
+
+static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+{
+#if 0
+       skb->data-=len;
+       skb->len+=len;
+       if(skb->data<skb->head) {
+               skb_under_panic(skb, len, current_text_addr());
+       }
+       return skb->data;
+#else
+  return NULL;
+#endif
+}
+
+static inline char *__skb_pull(struct sk_buff *skb, unsigned int len)
+{
+       skb->len-=len;
+       if (skb->len < skb->data_len)
+               out_of_line_bug();
+       return  skb->data+=len;
+}
+
+/**
+ *     skb_pull - remove data from the start of a buffer
+ *     @skb: buffer to use 
+ *     @len: amount of data to remove
+ *
+ *     This function removes data from the start of a buffer, returning
+ *     the memory to the headroom. A pointer to the next data in the buffer
+ *     is returned. Once the data has been pulled future pushes will overwrite
+ *     the old data.
+ */
+
+static inline unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
+{      
+       if (len > skb->len)
+               return NULL;
+       return __skb_pull(skb,len);
+}
+
+extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta);
+
+static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len)
+{
+       if (len > skb_headlen(skb) &&
+           __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL)
+               return NULL;
+       skb->len -= len;
+       return  skb->data += len;
+}
+
+static inline unsigned char * pskb_pull(struct sk_buff *skb, unsigned int len)
+{      
+       if (len > skb->len)
+               return NULL;
+       return __pskb_pull(skb,len);
+}
+
+static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
+{
+       if (len <= skb_headlen(skb))
+               return 1;
+       if (len > skb->len)
+               return 0;
+       return (__pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL);
+}
+
+/**
+ *     skb_headroom - bytes at buffer head
+ *     @skb: buffer to check
+ *
+ *     Return the number of bytes of free space at the head of an &sk_buff.
+ */
+static inline int skb_headroom(const struct sk_buff *skb)
+{
+       return skb->data-skb->head;
+}
+
+/**
+ *     skb_tailroom - bytes at buffer end
+ *     @skb: buffer to check
+ *
+ *     Return the number of bytes of free space at the tail of an sk_buff
+ */
+
+static inline int skb_tailroom(const struct sk_buff *skb)
+{
+       return skb_is_nonlinear(skb) ? 0 : skb->end-skb->tail;
+}
+
+/**
+ *     skb_reserve - adjust headroom
+ *     @skb: buffer to alter
+ *     @len: bytes to move
+ *
+ *     Increase the headroom of an empty &sk_buff by reducing the tail
+ *     room. This is only allowed for an empty buffer.
+ */
+
+static inline void skb_reserve(struct sk_buff *skb, unsigned int len)
+{
+       skb->data+=len;
+       skb->tail+=len;
+}
+
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+
+static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
+{
+       if (!skb->data_len) {
+               skb->len = len;
+               skb->tail = skb->data+len;
+       } else {
+               ___pskb_trim(skb, len, 0);
+       }
+}
+
+/**
+ *     skb_trim - remove end from a buffer
+ *     @skb: buffer to alter
+ *     @len: new length
+ *
+ *     Cut the length of a buffer down by removing data from the tail. If
+ *     the buffer is already under the length specified it is not modified.
+ */
+
+static inline void skb_trim(struct sk_buff *skb, unsigned int len)
+{
+       if (skb->len > len) {
+               __skb_trim(skb, len);
+       }
+}
+
+
+static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
+{
+       if (!skb->data_len) {
+               skb->len = len;
+               skb->tail = skb->data+len;
+               return 0;
+       } else {
+               return ___pskb_trim(skb, len, 1);
+       }
+}
+
+static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
+{
+       if (len < skb->len)
+               return __pskb_trim(skb, len);
+       return 0;
+}
+
+/**
+ *     skb_orphan - orphan a buffer
+ *     @skb: buffer to orphan
+ *
+ *     If a buffer currently has an owner then we call the owner's
+ *     destructor function and make the @skb unowned. The buffer continues
+ *     to exist but is no longer charged to its former owner.
+ */
+
+
+static inline void skb_orphan(struct sk_buff *skb)
+{
+       if (skb->destructor)
+               skb->destructor(skb);
+       skb->destructor = NULL;
+       skb->sk = NULL;
+}
+
+/**
+ *     skb_purge - empty a list
+ *     @list: list to empty
+ *
+ *     Delete all buffers on an &sk_buff list. Each buffer is removed from
+ *     the list and one reference dropped. This function takes the list
+ *     lock and is atomic with respect to other list locking functions.
+ */
+
+
+static inline void skb_queue_purge(struct sk_buff_head *list)
+{
+       struct sk_buff *skb;
+       while ((skb=skb_dequeue(list))!=NULL)
+               kfree_skb(skb);
+}
+
+/**
+ *     __skb_purge - empty a list
+ *     @list: list to empty
+ *
+ *     Delete all buffers on an &sk_buff list. Each buffer is removed from
+ *     the list and one reference dropped. This function does not take the
+ *     list lock and the caller must hold the relevant locks to use it.
+ */
+
+
+static inline void __skb_queue_purge(struct sk_buff_head *list)
+{
+       struct sk_buff *skb;
+       while ((skb=__skb_dequeue(list))!=NULL)
+               kfree_skb(skb);
+}
+
+/**
+ *     __dev_alloc_skb - allocate an skbuff for sending
+ *     @length: length to allocate
+ *     @gfp_mask: get_free_pages mask, passed to alloc_skb
+ *
+ *     Allocate a new &sk_buff and assign it a usage count of one. The
+ *     buffer has unspecified headroom built in. Users should allocate
+ *     the headroom they think they need without accounting for the
+ *     built in space. The built in space is used for optimisations.
+ *
+ *     %NULL is returned in there is no free memory.
+ */
+static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+                                             int gfp_mask)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_skb(length+16, gfp_mask);
+       if (skb)
+               skb_reserve(skb,16);
+       return skb;
+}
+
+/**
+ *     dev_alloc_skb - allocate an skbuff for sending
+ *     @length: length to allocate
+ *
+ *     Allocate a new &sk_buff and assign it a usage count of one. The
+ *     buffer has unspecified headroom built in. Users should allocate
+ *     the headroom they think they need without accounting for the
+ *     built in space. The built in space is used for optimisations.
+ *
+ *     %NULL is returned in there is no free memory. Although this function
+ *     allocates memory it can be called from an interrupt.
+ */
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+#if 0
+       return __dev_alloc_skb(length, GFP_ATOMIC);
+#else
+  return NULL;
+#endif
+}
+
+/**
+ *     skb_cow - copy header of skb when it is required
+ *     @skb: buffer to cow
+ *     @headroom: needed headroom
+ *
+ *     If the skb passed lacks sufficient headroom or its data part
+ *     is shared, data is reallocated. If reallocation fails, an error
+ *     is returned and original skb is not changed.
+ *
+ *     The result is skb with writable area skb->head...skb->tail
+ *     and at least @headroom of space at head.
+ */
+
+static inline int
+skb_cow(struct sk_buff *skb, unsigned int headroom)
+{
+#if 0
+       int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb);
+
+       if (delta < 0)
+               delta = 0;
+
+       if (delta || skb_cloned(skb))
+               return pskb_expand_head(skb, (delta+15)&~15, 0, GFP_ATOMIC);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/**
+ *     skb_linearize - convert paged skb to linear one
+ *     @skb: buffer to linarize
+ *     @gfp: allocation mode
+ *
+ *     If there is no free memory -ENOMEM is returned, otherwise zero
+ *     is returned and the old skb data released.  */
+int skb_linearize(struct sk_buff *skb, int gfp);
+
+static inline void *kmap_skb_frag(const skb_frag_t *frag)
+{
+#if 0
+#ifdef CONFIG_HIGHMEM
+       if (in_irq())
+               out_of_line_bug();
+
+       local_bh_disable();
+#endif
+       return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ);
+#else
+  return NULL;
+#endif 
+}
+
+static inline void kunmap_skb_frag(void *vaddr)
+{
+#if 0
+       kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+#ifdef CONFIG_HIGHMEM
+       local_bh_enable();
+#endif
+#endif
+}
+
+#define skb_queue_walk(queue, skb) \
+               for (skb = (queue)->next;                       \
+                    (skb != (struct sk_buff *)(queue));        \
+                    skb=skb->next)
+
+
+extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
+extern unsigned int            datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait);
+extern int                     skb_copy_datagram(const struct sk_buff *from, int offset, char *to,int size);
+extern int                     skb_copy_datagram_iovec(const struct sk_buff *from, int offset, struct iovec *to,int size);
+extern int                     skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int *csump);
+extern int                     skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, int hlen, struct iovec *iov);
+extern void                    skb_free_datagram(struct sock * sk, struct sk_buff *skb);
+
+extern unsigned int            skb_checksum(const struct sk_buff *skb, int offset, int len, unsigned int csum);
+extern int                     skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
+extern unsigned int            skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int csum);
+extern void                    skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
+
+extern void skb_init(void);
+extern void skb_add_mtu(int mtu);
+
+#ifdef CONFIG_NETFILTER
+static inline void
+nf_conntrack_put(struct nf_ct_info *nfct)
+{
+       if (nfct && atomic_dec_and_test(&nfct->master->use))
+               nfct->master->destroy(nfct->master);
+}
+static inline void
+nf_conntrack_get(struct nf_ct_info *nfct)
+{
+       if (nfct)
+               atomic_inc(&nfct->master->use);
+}
+#endif
+
+
+#endif /* skbuff */
+
+
+
+
+
+struct sock;
+
+typedef struct sockaddr
+{
+  int x;
+} _sockaddr;
+
+
+struct msghdr {
+       void    *       msg_name;       /* Socket name                  */
+       int             msg_namelen;    /* Length of name               */
+       struct iovec *  msg_iov;        /* Data blocks                  */
+       __kernel_size_t msg_iovlen;     /* Number of blocks             */
+       void    *       msg_control;    /* Per protocol magic (eg BSD file descriptor passing) */
+       __kernel_size_t msg_controllen; /* Length of cmsg list */
+       unsigned        msg_flags;
+};
+
+
+/* IP protocol blocks we attach to sockets.
+ * socket layer -> transport layer interface
+ * transport -> network interface is defined by struct inet_proto
+ */
+struct proto {
+       void                    (*close)(struct sock *sk, 
+                                       long timeout);
+       int                     (*connect)(struct sock *sk,
+                                       struct sockaddr *uaddr, 
+                                       int addr_len);
+       int                     (*disconnect)(struct sock *sk, int flags);
+
+       struct sock *           (*accept) (struct sock *sk, int flags, int *err);
+
+       int                     (*ioctl)(struct sock *sk, int cmd,
+                                        unsigned long arg);
+       int                     (*init)(struct sock *sk);
+       int                     (*destroy)(struct sock *sk);
+       void                    (*shutdown)(struct sock *sk, int how);
+       int                     (*setsockopt)(struct sock *sk, int level, 
+                                       int optname, char *optval, int optlen);
+       int                     (*getsockopt)(struct sock *sk, int level, 
+                                       int optname, char *optval, 
+                                       int *option);    
+       int                     (*sendmsg)(struct sock *sk, struct msghdr *msg,
+                                          int len);
+       int                     (*recvmsg)(struct sock *sk, struct msghdr *msg,
+                                       int len, int noblock, int flags, 
+                                       int *addr_len);
+       int                     (*bind)(struct sock *sk, 
+                                       struct sockaddr *uaddr, int addr_len);
+
+       int                     (*backlog_rcv) (struct sock *sk, 
+                                               struct sk_buff *skb);
+
+       /* Keeping track of sk's, looking them up, and port selection methods. */
+       void                    (*hash)(struct sock *sk);
+       void                    (*unhash)(struct sock *sk);
+       int                     (*get_port)(struct sock *sk, unsigned short snum);
+
+       char                    name[32];
+
+       struct {
+               int inuse;
+  } stats[32];
+//             u8  __pad[SMP_CACHE_BYTES - sizeof(int)];
+//     } stats[NR_CPUS];
+};
+
+
+
+
+
+
+
+/* This defines a selective acknowledgement block. */
+struct tcp_sack_block {
+       __u32   start_seq;
+       __u32   end_seq;
+};
+
+
+struct tcp_opt {
+       int     tcp_header_len; /* Bytes of tcp header to send          */
+
+/*
+ *     Header prediction flags
+ *     0x5?10 << 16 + snd_wnd in net byte order
+ */
+       __u32   pred_flags;
+
+/*
+ *     RFC793 variables by their proper names. This means you can
+ *     read the code and the spec side by side (and laugh ...)
+ *     See RFC793 and RFC1122. The RFC writes these in capitals.
+ */
+       __u32   rcv_nxt;        /* What we want to receive next         */
+       __u32   snd_nxt;        /* Next sequence we send                */
+
+       __u32   snd_una;        /* First byte we want an ack for        */
+       __u32   snd_sml;        /* Last byte of the most recently transmitted small packet */
+       __u32   rcv_tstamp;     /* timestamp of last received ACK (for keepalives) */
+       __u32   lsndtime;       /* timestamp of last sent data packet (for restart window) */
+
+       /* Delayed ACK control data */
+       struct {
+               __u8    pending;        /* ACK is pending */
+               __u8    quick;          /* Scheduled number of quick acks       */
+               __u8    pingpong;       /* The session is interactive           */
+               __u8    blocked;        /* Delayed ACK was blocked by socket lock*/
+               __u32   ato;            /* Predicted tick of soft clock         */
+               unsigned long timeout;  /* Currently scheduled timeout          */
+               __u32   lrcvtime;       /* timestamp of last received data packet*/
+               __u16   last_seg_size;  /* Size of last incoming segment        */
+               __u16   rcv_mss;        /* MSS used for delayed ACK decisions   */ 
+       } ack;
+
+       /* Data for direct copy to user */
+       struct {
+               //struct sk_buff_head   prequeue;
+               struct task_struct      *task;
+               struct iovec            *iov;
+               int                     memory;
+               int                     len;
+       } ucopy;
+
+       __u32   snd_wl1;        /* Sequence for window update           */
+       __u32   snd_wnd;        /* The window we expect to receive      */
+       __u32   max_window;     /* Maximal window ever seen from peer   */
+       __u32   pmtu_cookie;    /* Last pmtu seen by socket             */
+       __u16   mss_cache;      /* Cached effective mss, not including SACKS */
+       __u16   mss_clamp;      /* Maximal mss, negotiated at connection setup */
+       __u16   ext_header_len; /* Network protocol overhead (IP/IPv6 options) */
+       __u8    ca_state;       /* State of fast-retransmit machine     */
+       __u8    retransmits;    /* Number of unrecovered RTO timeouts.  */
+
+       __u8    reordering;     /* Packet reordering metric.            */
+       __u8    queue_shrunk;   /* Write queue has been shrunk recently.*/
+       __u8    defer_accept;   /* User waits for some data after accept() */
+
+/* RTT measurement */
+       __u8    backoff;        /* backoff                              */
+       __u32   srtt;           /* smothed round trip time << 3         */
+       __u32   mdev;           /* medium deviation                     */
+       __u32   mdev_max;       /* maximal mdev for the last rtt period */
+       __u32   rttvar;         /* smoothed mdev_max                    */
+       __u32   rtt_seq;        /* sequence number to update rttvar     */
+       __u32   rto;            /* retransmit timeout                   */
+
+       __u32   packets_out;    /* Packets which are "in flight"        */
+       __u32   left_out;       /* Packets which leaved network         */
+       __u32   retrans_out;    /* Retransmitted packets out            */
+
+
+/*
+ *     Slow start and congestion control (see also Nagle, and Karn & Partridge)
+ */
+       __u32   snd_ssthresh;   /* Slow start size threshold            */
+       __u32   snd_cwnd;       /* Sending congestion window            */
+       __u16   snd_cwnd_cnt;   /* Linear increase counter              */
+       __u16   snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
+       __u32   snd_cwnd_used;
+       __u32   snd_cwnd_stamp;
+
+       /* Two commonly used timers in both sender and receiver paths. */
+       unsigned long           timeout;
+       struct timer_list       retransmit_timer;       /* Resend (no ack)      */
+       struct timer_list       delack_timer;           /* Ack delay            */
+
+       struct sk_buff_head     out_of_order_queue; /* Out of order segments go here */
+
+       struct tcp_func         *af_specific;   /* Operations which are AF_INET{4,6} specific   */
+       struct sk_buff          *send_head;     /* Front of stuff to transmit                   */
+       struct page             *sndmsg_page;   /* Cached page for sendmsg                      */
+       u32                     sndmsg_off;     /* Cached offset for sendmsg                    */
+
+       __u32   rcv_wnd;        /* Current receiver window              */
+       __u32   rcv_wup;        /* rcv_nxt on last window update sent   */
+       __u32   write_seq;      /* Tail(+1) of data held in tcp send buffer */
+       __u32   pushed_seq;     /* Last pushed seq, required to talk to windows */
+       __u32   copied_seq;     /* Head of yet unread data              */
+/*
+ *      Options received (usually on last packet, some only on SYN packets).
+ */
+       char    tstamp_ok,      /* TIMESTAMP seen on SYN packet         */
+               wscale_ok,      /* Wscale seen on SYN packet            */
+               sack_ok;        /* SACK seen on SYN packet              */
+       char    saw_tstamp;     /* Saw TIMESTAMP on last packet         */
+        __u8   snd_wscale;     /* Window scaling received from sender  */
+        __u8   rcv_wscale;     /* Window scaling to send to receiver   */
+       __u8    nonagle;        /* Disable Nagle algorithm?             */
+       __u8    keepalive_probes; /* num of allowed keep alive probes   */
+
+/*     PAWS/RTTM data  */
+        __u32  rcv_tsval;      /* Time stamp value                     */
+        __u32  rcv_tsecr;      /* Time stamp echo reply                */
+        __u32  ts_recent;      /* Time stamp to echo next              */
+        long   ts_recent_stamp;/* Time we stored ts_recent (for aging) */
+
+/*     SACKs data      */
+       __u16   user_mss;       /* mss requested by user in ioctl */
+       __u8    dsack;          /* D-SACK is scheduled                  */
+       __u8    eff_sacks;      /* Size of SACK array to send with next packet */
+       struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
+       struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
+
+       __u32   window_clamp;   /* Maximal window to advertise          */
+       __u32   rcv_ssthresh;   /* Current window clamp                 */
+       __u8    probes_out;     /* unanswered 0 window probes           */
+       __u8    num_sacks;      /* Number of SACK blocks                */
+       __u16   advmss;         /* Advertised MSS                       */
+
+       __u8    syn_retries;    /* num of allowed syn retries */
+       __u8    ecn_flags;      /* ECN status bits.                     */
+       __u16   prior_ssthresh; /* ssthresh saved at recovery start     */
+       __u32   lost_out;       /* Lost packets                         */
+       __u32   sacked_out;     /* SACK'd packets                       */
+       __u32   fackets_out;    /* FACK'd packets                       */
+       __u32   high_seq;       /* snd_nxt at onset of congestion       */
+
+       __u32   retrans_stamp;  /* Timestamp of the last retransmit,
+                                * also used in SYN-SENT to remember stamp of
+                                * the first SYN. */
+       __u32   undo_marker;    /* tracking retrans started here. */
+       int     undo_retrans;   /* number of undoable retransmissions. */
+       __u32   urg_seq;        /* Seq of received urgent pointer */
+       __u16   urg_data;       /* Saved octet of OOB data and control flags */
+       __u8    pending;        /* Scheduled timer event        */
+       __u8    urg_mode;       /* In urgent mode               */
+       __u32   snd_up;         /* Urgent pointer               */
+
+       /* The syn_wait_lock is necessary only to avoid tcp_get_info having
+        * to grab the main lock sock while browsing the listening hash
+        * (otherwise it's deadlock prone).
+        * This lock is acquired in read mode only from tcp_get_info() and
+        * it's acquired in write mode _only_ from code that is actively
+        * changing the syn_wait_queue. All readers that are holding
+        * the master sock lock don't need to grab this lock in read mode
+        * too as the syn_wait_queue writes are always protected from
+        * the main sock lock.
+        */
+       rwlock_t                syn_wait_lock;
+       struct tcp_listen_opt   *listen_opt;
+
+       /* FIFO of established children */
+       struct open_request     *accept_queue;
+       struct open_request     *accept_queue_tail;
+
+       int                     write_pending;  /* A write to socket waits to start. */
+
+       unsigned int            keepalive_time;   /* time before keep alive takes place */
+       unsigned int            keepalive_intvl;  /* time interval between keep alive probes */
+       int                     linger2;
+
+       unsigned long last_synq_overflow; 
+};
+
+
+
+
+/* This is the per-socket lock.  The spinlock provides a synchronization
+ * between user contexts and software interrupt processing, whereas the
+ * mini-semaphore synchronizes multiple users amongst themselves.
+ */
+typedef struct {
+       spinlock_t              slock;
+       unsigned int            users;
+       wait_queue_head_t       wq;
+} socket_lock_t;
+
+struct sock {
+       /* Socket demultiplex comparisons on incoming packets. */
+       __u32                   daddr;          /* Foreign IPv4 addr                    */
+       __u32                   rcv_saddr;      /* Bound local IPv4 addr                */
+       __u16                   dport;          /* Destination port                     */
+       unsigned short          num;            /* Local port                           */
+       int                     bound_dev_if;   /* Bound device index if != 0           */
+
+       /* Main hash linkage for various protocol lookup tables. */
+       struct sock             *next;
+       struct sock             **pprev;
+       struct sock             *bind_next;
+       struct sock             **bind_pprev;
+
+       volatile unsigned char  state,          /* Connection state                     */
+                               zapped;         /* In ax25 & ipx means not linked       */
+       __u16                   sport;          /* Source port                          */
+
+       unsigned short          family;         /* Address family                       */
+       unsigned char           reuse;          /* SO_REUSEADDR setting                 */
+       unsigned char           shutdown;
+       atomic_t                refcnt;         /* Reference count                      */
+
+       socket_lock_t           lock;           /* Synchronizer...                      */
+       int                     rcvbuf;         /* Size of receive buffer in bytes      */
+
+       wait_queue_head_t       *sleep;         /* Sock wait queue                      */
+       struct dst_entry        *dst_cache;     /* Destination cache                    */
+       rwlock_t                dst_lock;
+       atomic_t                rmem_alloc;     /* Receive queue bytes committed        */
+       struct sk_buff_head     receive_queue;  /* Incoming packets                     */
+       atomic_t                wmem_alloc;     /* Transmit queue bytes committed       */
+       struct sk_buff_head     write_queue;    /* Packet sending queue                 */
+       atomic_t                omem_alloc;     /* "o" is "option" or "other" */
+       int                     wmem_queued;    /* Persistent queue size */
+       int                     forward_alloc;  /* Space allocated forward. */
+       __u32                   saddr;          /* Sending source                       */
+       unsigned int            allocation;     /* Allocation mode                      */
+       int                     sndbuf;         /* Size of send buffer in bytes         */
+       struct sock             *prev;
+
+       /* Not all are volatile, but some are, so we might as well say they all are.
+        * XXX Make this a flag word -DaveM
+        */
+       volatile char           dead,
+                               done,
+                               urginline,
+                               keepopen,
+                               linger,
+                               destroy,
+                               no_check,
+                               broadcast,
+                               bsdism;
+       unsigned char           debug;
+       unsigned char           rcvtstamp;
+       unsigned char           use_write_queue;
+       unsigned char           userlocks;
+       /* Hole of 3 bytes. Try to pack. */
+       int                     route_caps;
+       int                     proc;
+       unsigned long           lingertime;
+
+       int                     hashent;
+       struct sock             *pair;
+
+       /* The backlog queue is special, it is always used with
+        * the per-socket spinlock held and requires low latency
+        * access.  Therefore we special case it's implementation.
+        */
+       struct {
+               struct sk_buff *head;
+               struct sk_buff *tail;
+       } backlog;
+
+       rwlock_t                callback_lock;
+
+       /* Error queue, rarely used. */
+       struct sk_buff_head     error_queue;
+
+       struct proto            *prot;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+       union {
+               struct ipv6_pinfo       af_inet6;
+       } net_pinfo;
+#endif
+
+       union {
+               struct tcp_opt          af_tcp;
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+               struct raw_opt          tp_raw4;
+#endif
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+               struct raw6_opt         tp_raw;
+#endif /* CONFIG_IPV6 */
+#if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
+               struct spx_opt          af_spx;
+#endif /* CONFIG_SPX */
+
+       } tp_pinfo;
+
+       int                     err, err_soft;  /* Soft holds errors that don't
+                                                  cause failure but are the cause
+                                                  of a persistent failure not just
+                                                  'timed out' */
+       unsigned short          ack_backlog;
+       unsigned short          max_ack_backlog;
+       __u32                   priority;
+       unsigned short          type;
+       unsigned char           localroute;     /* Route locally only */
+       unsigned char           protocol;
+//     struct ucred            peercred;
+       int                     rcvlowat;
+       long                    rcvtimeo;
+       long                    sndtimeo;
+
+#ifdef CONFIG_FILTER
+       /* Socket Filtering Instructions */
+       struct sk_filter        *filter;
+#endif /* CONFIG_FILTER */
+
+       /* This is where all the private (optional) areas that don't
+        * overlap will eventually live. 
+        */
+       union {
+               void *destruct_hook;
+//             struct unix_opt af_unix;
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+               struct inet_opt af_inet;
+#endif
+#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
+               struct atalk_sock       af_at;
+#endif
+#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
+               struct ipx_opt          af_ipx;
+#endif
+#if defined (CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
+               struct dn_scp           dn;
+#endif
+#if defined (CONFIG_PACKET) || defined(CONFIG_PACKET_MODULE)
+               struct packet_opt       *af_packet;
+#endif
+#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
+               x25_cb                  *x25;
+#endif
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+               ax25_cb                 *ax25;
+#endif
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+               nr_cb                   *nr;
+#endif
+#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
+               rose_cb                 *rose;
+#endif
+#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE)
+               struct pppox_opt        *pppox;
+#endif
+               struct netlink_opt      *af_netlink;
+#if defined(CONFIG_ECONET) || defined(CONFIG_ECONET_MODULE)
+               struct econet_opt       *af_econet;
+#endif
+#if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE)
+               struct atm_vcc          *af_atm;
+#endif
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+               struct irda_sock        *irda;
+#endif
+#if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE)
+               struct wanpipe_opt      *af_wanpipe;
+#endif
+       } protinfo;             
+
+
+       /* This part is used for the timeout functions. */
+       struct timer_list       timer;          /* This is the sock cleanup timer. */
+       struct timeval          stamp;
+
+       /* Identd and reporting IO signals */
+       struct socket           *socket;
+
+       /* RPC layer private data */
+       void                    *user_data;
+  
+       /* Callbacks */
+       void                    (*state_change)(struct sock *sk);
+       void                    (*data_ready)(struct sock *sk,int bytes);
+       void                    (*write_space)(struct sock *sk);
+       void                    (*error_report)(struct sock *sk);
+
+       int                     (*backlog_rcv) (struct sock *sk,
+                                               struct sk_buff *skb);  
+       void                    (*destruct)(struct sock *sk);
+};
+
+
+
+
+#if 1 /* dst (_NET_DST_H) */
+
+#if 0
+#include <linux/config.h>
+#include <net/neighbour.h>
+#endif
+
+/*
+ * 0 - no debugging messages
+ * 1 - rare events and bugs (default)
+ * 2 - trace mode.
+ */
+#define RT_CACHE_DEBUG         0
+
+#define DST_GC_MIN     (1*HZ)
+#define DST_GC_INC     (5*HZ)
+#define DST_GC_MAX     (120*HZ)
+
+struct sk_buff;
+
+struct dst_entry
+{
+       struct dst_entry        *next;
+       atomic_t                __refcnt;       /* client references    */
+       int                     __use;
+       struct net_device       *dev;
+       int                     obsolete;
+       int                     flags;
+#define DST_HOST               1
+       unsigned long           lastuse;
+       unsigned long           expires;
+
+       unsigned                mxlock;
+       unsigned                pmtu;
+       unsigned                window;
+       unsigned                rtt;
+       unsigned                rttvar;
+       unsigned                ssthresh;
+       unsigned                cwnd;
+       unsigned                advmss;
+       unsigned                reordering;
+
+       unsigned long           rate_last;      /* rate limiting for ICMP */
+       unsigned long           rate_tokens;
+
+       int                     error;
+
+       struct neighbour        *neighbour;
+       struct hh_cache         *hh;
+
+       int                     (*input)(struct sk_buff*);
+       int                     (*output)(struct sk_buff*);
+
+#ifdef CONFIG_NET_CLS_ROUTE
+       __u32                   tclassid;
+#endif
+
+       struct  dst_ops         *ops;
+               
+       char                    info[0];
+};
+
+
+struct dst_ops
+{
+       unsigned short          family;
+       unsigned short          protocol;
+       unsigned                gc_thresh;
+
+       int                     (*gc)(void);
+       struct dst_entry *      (*check)(struct dst_entry *, __u32 cookie);
+       struct dst_entry *      (*reroute)(struct dst_entry *,
+                                          struct sk_buff *);
+       void                    (*destroy)(struct dst_entry *);
+       struct dst_entry *      (*negative_advice)(struct dst_entry *);
+       void                    (*link_failure)(struct sk_buff *);
+       int                     entry_size;
+
+       atomic_t                entries;
+       kmem_cache_t            *kmem_cachep;
+};
+
+#ifdef __KERNEL__
+
+static inline void dst_hold(struct dst_entry * dst)
+{
+       atomic_inc(&dst->__refcnt);
+}
+
+static inline
+struct dst_entry * dst_clone(struct dst_entry * dst)
+{
+       if (dst)
+               atomic_inc(&dst->__refcnt);
+       return dst;
+}
+
+static inline
+void dst_release(struct dst_entry * dst)
+{
+       if (dst)
+               atomic_dec(&dst->__refcnt);
+}
+
+extern void * dst_alloc(struct dst_ops * ops);
+extern void __dst_free(struct dst_entry * dst);
+extern void dst_destroy(struct dst_entry * dst);
+
+static inline
+void dst_free(struct dst_entry * dst)
+{
+       if (dst->obsolete > 1)
+               return;
+       if (!atomic_read(&dst->__refcnt)) {
+               dst_destroy(dst);
+               return;
+       }
+       __dst_free(dst);
+}
+
+static inline void dst_confirm(struct dst_entry *dst)
+{
+       if (dst)
+               neigh_confirm(dst->neighbour);
+}
+
+static inline void dst_negative_advice(struct dst_entry **dst_p)
+{
+       struct dst_entry * dst = *dst_p;
+       if (dst && dst->ops->negative_advice)
+               *dst_p = dst->ops->negative_advice(dst);
+}
+
+static inline void dst_link_failure(struct sk_buff *skb)
+{
+       struct dst_entry * dst = skb->dst;
+       if (dst && dst->ops && dst->ops->link_failure)
+               dst->ops->link_failure(skb);
+}
+
+static inline void dst_set_expires(struct dst_entry *dst, int timeout)
+{
+       unsigned long expires = jiffies + timeout;
+
+       if (expires == 0)
+               expires = 1;
+
+       if (dst->expires == 0 || (long)(dst->expires - expires) > 0)
+               dst->expires = expires;
+}
+
+extern void            dst_init(void);
+
+#endif /* dst */
+
+
+
+#if 1
+/* dummy types */
+
+
+#endif
+
+#define TCP_DEBUG 1
+#define FASTRETRANS_DEBUG 1
+
+/* Cancel timers, when they are not required. */
+#undef TCP_CLEAR_TIMERS
+
+#if 0
+#include <linux/config.h>
+#include <linux/tcp.h>
+#include <linux/slab.h>
+#include <linux/cache.h>
+#include <net/checksum.h>
+#include <net/sock.h>
+#else
+#include "linux.h"
+#endif
+
+/* This is for all connections with a full identity, no wildcards.
+ * New scheme, half the table is for TIME_WAIT, the other half is
+ * for the rest.  I'll experiment with dynamic table growth later.
+ */
+struct tcp_ehash_bucket {
+       rwlock_t        lock;
+       struct sock     *chain;
+} __attribute__((__aligned__(8)));
+
+/* This is for listening sockets, thus all sockets which possess wildcards. */
+#define TCP_LHTABLE_SIZE       32      /* Yes, really, this is all you need. */
+
+/* There are a few simple rules, which allow for local port reuse by
+ * an application.  In essence:
+ *
+ *     1) Sockets bound to different interfaces may share a local port.
+ *        Failing that, goto test 2.
+ *     2) If all sockets have sk->reuse set, and none of them are in
+ *        TCP_LISTEN state, the port may be shared.
+ *        Failing that, goto test 3.
+ *     3) If all sockets are bound to a specific sk->rcv_saddr local
+ *        address, and none of them are the same, the port may be
+ *        shared.
+ *        Failing this, the port cannot be shared.
+ *
+ * The interesting point, is test #2.  This is what an FTP server does
+ * all day.  To optimize this case we use a specific flag bit defined
+ * below.  As we add sockets to a bind bucket list, we perform a
+ * check of: (newsk->reuse && (newsk->state != TCP_LISTEN))
+ * As long as all sockets added to a bind bucket pass this test,
+ * the flag bit will be set.
+ * The resulting situation is that tcp_v[46]_verify_bind() can just check
+ * for this flag bit, if it is set and the socket trying to bind has
+ * sk->reuse set, we don't even have to walk the owners list at all,
+ * we return that it is ok to bind this socket to the requested local port.
+ *
+ * Sounds like a lot of work, but it is worth it.  In a more naive
+ * implementation (ie. current FreeBSD etc.) the entire list of ports
+ * must be walked for each data port opened by an ftp server.  Needless
+ * to say, this does not scale at all.  With a couple thousand FTP
+ * users logged onto your box, isn't it nice to know that new data
+ * ports are created in O(1) time?  I thought so. ;-)  -DaveM
+ */
+struct tcp_bind_bucket {
+       unsigned short          port;
+       signed short            fastreuse;
+       struct tcp_bind_bucket  *next;
+       struct sock             *owners;
+       struct tcp_bind_bucket  **pprev;
+};
+
+struct tcp_bind_hashbucket {
+       spinlock_t              lock;
+       struct tcp_bind_bucket  *chain;
+};
+
+extern struct tcp_hashinfo {
+       /* This is for sockets with full identity only.  Sockets here will
+        * always be without wildcards and will have the following invariant:
+        *
+        *          TCP_ESTABLISHED <= sk->state < TCP_CLOSE
+        *
+        * First half of the table is for sockets not in TIME_WAIT, second half
+        * is for TIME_WAIT sockets only.
+        */
+       struct tcp_ehash_bucket *__tcp_ehash;
+
+       /* Ok, let's try this, I give up, we do need a local binding
+        * TCP hash as well as the others for fast bind/connect.
+        */
+       struct tcp_bind_hashbucket *__tcp_bhash;
+
+       int __tcp_bhash_size;
+       int __tcp_ehash_size;
+
+       /* All sockets in TCP_LISTEN state will be in here.  This is the only
+        * table where wildcard'd TCP sockets can exist.  Hash function here
+        * is just local port number.
+        */
+       struct sock *__tcp_listening_hash[TCP_LHTABLE_SIZE];
+
+       /* All the above members are written once at bootup and
+        * never written again _or_ are predominantly read-access.
+        *
+        * Now align to a new cache line as all the following members
+        * are often dirty.
+        */
+       rwlock_t __tcp_lhash_lock ____cacheline_aligned;
+       atomic_t __tcp_lhash_users;
+       wait_queue_head_t __tcp_lhash_wait;
+       spinlock_t __tcp_portalloc_lock;
+} tcp_hashinfo;
+
+#define tcp_ehash      (tcp_hashinfo.__tcp_ehash)
+#define tcp_bhash      (tcp_hashinfo.__tcp_bhash)
+#define tcp_ehash_size (tcp_hashinfo.__tcp_ehash_size)
+#define tcp_bhash_size (tcp_hashinfo.__tcp_bhash_size)
+#define tcp_listening_hash (tcp_hashinfo.__tcp_listening_hash)
+#define tcp_lhash_lock (tcp_hashinfo.__tcp_lhash_lock)
+#define tcp_lhash_users        (tcp_hashinfo.__tcp_lhash_users)
+#define tcp_lhash_wait (tcp_hashinfo.__tcp_lhash_wait)
+#define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock)
+
+extern kmem_cache_t *tcp_bucket_cachep;
+extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
+                                                unsigned short snum);
+extern void tcp_bucket_unlock(struct sock *sk);
+extern int tcp_port_rover;
+extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
+
+/* These are AF independent. */
+static __inline__ int tcp_bhashfn(__u16 lport)
+{
+       return (lport & (tcp_bhash_size - 1));
+}
+
+/* This is a TIME_WAIT bucket.  It works around the memory consumption
+ * problems of sockets in such a state on heavily loaded servers, but
+ * without violating the protocol specification.
+ */
+struct tcp_tw_bucket {
+       /* These _must_ match the beginning of struct sock precisely.
+        * XXX Yes I know this is gross, but I'd have to edit every single
+        * XXX networking file if I created a "struct sock_header". -DaveM
+        */
+       __u32                   daddr;
+       __u32                   rcv_saddr;
+       __u16                   dport;
+       unsigned short          num;
+       int                     bound_dev_if;
+       struct sock             *next;
+       struct sock             **pprev;
+       struct sock             *bind_next;
+       struct sock             **bind_pprev;
+       unsigned char           state,
+                               substate; /* "zapped" is replaced with "substate" */
+       __u16                   sport;
+       unsigned short          family;
+       unsigned char           reuse,
+                               rcv_wscale; /* It is also TW bucket specific */
+       atomic_t                refcnt;
+
+       /* And these are ours. */
+       int                     hashent;
+       int                     timeout;
+       __u32                   rcv_nxt;
+       __u32                   snd_nxt;
+       __u32                   rcv_wnd;
+        __u32                  ts_recent;
+        long                   ts_recent_stamp;
+       unsigned long           ttd;
+       struct tcp_bind_bucket  *tb;
+       struct tcp_tw_bucket    *next_death;
+       struct tcp_tw_bucket    **pprev_death;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct in6_addr         v6_daddr;
+       struct in6_addr         v6_rcv_saddr;
+#endif
+};
+
+extern kmem_cache_t *tcp_timewait_cachep;
+
+static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
+{
+       if (atomic_dec_and_test(&tw->refcnt)) {
+#ifdef INET_REFCNT_DEBUG
+               printk(KERN_DEBUG "tw_bucket %p released\n", tw);
+#endif
+               kmem_cache_free(tcp_timewait_cachep, tw);
+       }
+}
+
+extern atomic_t tcp_orphan_count;
+extern int tcp_tw_count;
+extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+extern void tcp_timewait_kill(struct tcp_tw_bucket *tw);
+extern void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo);
+extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
+
+
+/* Socket demux engine toys. */
+#ifdef __BIG_ENDIAN
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+       (((__u32)(__sport)<<16) | (__u32)(__dport))
+#else /* __LITTLE_ENDIAN */
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+       (((__u32)(__dport)<<16) | (__u32)(__sport))
+#endif
+
+#if (BITS_PER_LONG == 64)
+#ifdef __BIG_ENDIAN
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+       __u64 __name = (((__u64)(__saddr))<<32)|((__u64)(__daddr));
+#else /* __LITTLE_ENDIAN */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+       __u64 __name = (((__u64)(__daddr))<<32)|((__u64)(__saddr));
+#endif /* __BIG_ENDIAN */
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((*((__u64 *)&((__sk)->daddr)))== (__cookie))  &&              \
+        ((*((__u32 *)&((__sk)->dport)))== (__ports))   &&              \
+        (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#else /* 32-bit arch */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr)
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->daddr                 == (__saddr))   &&              \
+        ((__sk)->rcv_saddr             == (__daddr))   &&              \
+        ((*((__u32 *)&((__sk)->dport)))== (__ports))   &&              \
+        (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#endif /* 64-bit arch */
+
+#define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif)                    \
+       (((*((__u32 *)&((__sk)->dport)))== (__ports))                           && \
+        ((__sk)->family                == AF_INET6)                            && \
+        !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.daddr, (__saddr))           && \
+        !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.rcv_saddr, (__daddr))       && \
+        (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+
+/* These can have wildcards, don't try too hard. */
+static __inline__ int tcp_lhashfn(unsigned short num)
+{
+#if 0
+       return num & (TCP_LHTABLE_SIZE - 1);
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
+{
+#if 0
+       return tcp_lhashfn(sk->num);
+#else
+  return 0;
+#endif
+}
+
+#define MAX_TCP_HEADER (128 + MAX_HEADER)
+
+/* 
+ * Never offer a window over 32767 without using window scaling. Some
+ * poor stacks do signed 16bit maths! 
+ */
+#define MAX_TCP_WINDOW         32767U
+
+/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
+#define TCP_MIN_MSS            88U
+
+/* Minimal RCV_MSS. */
+#define TCP_MIN_RCVMSS         536U
+
+/* After receiving this amount of duplicate ACKs fast retransmit starts. */
+#define TCP_FASTRETRANS_THRESH 3
+
+/* Maximal reordering. */
+#define TCP_MAX_REORDERING     127
+
+/* Maximal number of ACKs sent quickly to accelerate slow-start. */
+#define TCP_MAX_QUICKACKS      16U
+
+/* urg_data states */
+#define TCP_URG_VALID  0x0100
+#define TCP_URG_NOTYET 0x0200
+#define TCP_URG_READ   0x0400
+
+#define TCP_RETR1      3       /*
+                                * This is how many retries it does before it
+                                * tries to figure out if the gateway is
+                                * down. Minimal RFC value is 3; it corresponds
+                                * to ~3sec-8min depending on RTO.
+                                */
+
+#define TCP_RETR2      15      /*
+                                * This should take at least
+                                * 90 minutes to time out.
+                                * RFC1122 says that the limit is 100 sec.
+                                * 15 is ~13-30min depending on RTO.
+                                */
+
+#define TCP_SYN_RETRIES         5      /* number of times to retry active opening a
+                                * connection: ~180sec is RFC minumum   */
+
+#define TCP_SYNACK_RETRIES 5   /* number of times to retry passive opening a
+                                * connection: ~180sec is RFC minumum   */
+
+
+#define TCP_ORPHAN_RETRIES 7   /* number of times to retry on an orphaned
+                                * socket. 7 is ~50sec-16min.
+                                */
+
+
+#define TCP_TIMEWAIT_LEN (60*1000)
+//#define TCP_TIMEWAIT_LEN (60*HZ)
+/* how long to wait to destroy TIME-WAIT
+                                 * state, about 60 seconds     */
+#define TCP_FIN_TIMEOUT        TCP_TIMEWAIT_LEN
+                                 /* BSD style FIN_WAIT2 deadlock breaker.
+                                 * It used to be 3min, new value is 60sec,
+                                 * to combine FIN-WAIT-2 timeout with
+                                 * TIME-WAIT timer.
+                                 */
+
+#define TCP_DELACK_MAX ((unsigned)(HZ/5))      /* maximal time to delay before sending an ACK */
+#if HZ >= 100
+#define TCP_DELACK_MIN ((unsigned)(HZ/25))     /* minimal time to delay before sending an ACK */
+#define TCP_ATO_MIN    ((unsigned)(HZ/25))
+#else
+#define TCP_DELACK_MIN 4U
+#define TCP_ATO_MIN    4U
+#endif
+#define TCP_RTO_MAX    ((unsigned)(120*HZ))
+#define TCP_RTO_MIN    ((unsigned)(HZ/5))
+#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ))    /* RFC 1122 initial RTO value   */
+
+#define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
+                                                        * for local resources.
+                                                        */
+
+#define TCP_KEEPALIVE_TIME     (120*60*HZ)     /* two hours */
+#define TCP_KEEPALIVE_PROBES   9               /* Max of 9 keepalive probes    */
+#define TCP_KEEPALIVE_INTVL    (75*HZ)
+
+#define MAX_TCP_KEEPIDLE       32767
+#define MAX_TCP_KEEPINTVL      32767
+#define MAX_TCP_KEEPCNT                127
+#define MAX_TCP_SYNCNT         127
+
+/* TIME_WAIT reaping mechanism. */
+#define TCP_TWKILL_SLOTS       8       /* Please keep this a power of 2. */
+#define TCP_TWKILL_PERIOD      (TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
+
+#define TCP_SYNQ_INTERVAL      (HZ/5)  /* Period of SYNACK timer */
+#define TCP_SYNQ_HSIZE         512     /* Size of SYNACK hash table */
+
+#define TCP_PAWS_24DAYS        (60 * 60 * 24 * 24)
+#define TCP_PAWS_MSL   60              /* Per-host timestamps are invalidated
+                                        * after this time. It should be equal
+                                        * (or greater than) TCP_TIMEWAIT_LEN
+                                        * to provide reliability equal to one
+                                        * provided by timewait state.
+                                        */
+#define TCP_PAWS_WINDOW        1               /* Replay window for per-host
+                                        * timestamps. It must be less than
+                                        * minimal timewait lifetime.
+                                        */
+
+#define TCP_TW_RECYCLE_SLOTS_LOG       5
+#define TCP_TW_RECYCLE_SLOTS           (1<<TCP_TW_RECYCLE_SLOTS_LOG)
+
+/* If time > 4sec, it is "slow" path, no recycling is required,
+   so that we select tick to get range about 4 seconds.
+ */
+
+#if 0
+#if HZ <= 16 || HZ > 4096
+# error Unsupported: HZ <= 16 or HZ > 4096
+#elif HZ <= 32
+# define TCP_TW_RECYCLE_TICK (5+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 64
+# define TCP_TW_RECYCLE_TICK (6+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 128
+# define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 256
+# define TCP_TW_RECYCLE_TICK (8+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 512
+# define TCP_TW_RECYCLE_TICK (9+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 1024
+# define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 2048
+# define TCP_TW_RECYCLE_TICK (11+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#else
+# define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#endif
+#else
+#define TCP_TW_RECYCLE_TICK (0)
+#endif
+
+/*
+ *     TCP option
+ */
+#define TCPOPT_NOP             1       /* Padding */
+#define TCPOPT_EOL             0       /* End of options */
+#define TCPOPT_MSS             2       /* Segment size negotiating */
+#define TCPOPT_WINDOW          3       /* Window scaling */
+#define TCPOPT_SACK_PERM        4       /* SACK Permitted */
+#define TCPOPT_SACK             5       /* SACK Block */
+#define TCPOPT_TIMESTAMP       8       /* Better RTT estimations/PAWS */
+
+/*
+ *     TCP option lengths
+ */
+
+#define TCPOLEN_MSS            4
+#define TCPOLEN_WINDOW         3
+#define TCPOLEN_SACK_PERM      2
+#define TCPOLEN_TIMESTAMP      10
+
+/* But this is what stacks really send out. */
+#define TCPOLEN_TSTAMP_ALIGNED         12
+#define TCPOLEN_WSCALE_ALIGNED         4
+#define TCPOLEN_SACKPERM_ALIGNED       4
+#define TCPOLEN_SACK_BASE              2
+#define TCPOLEN_SACK_BASE_ALIGNED      4
+#define TCPOLEN_SACK_PERBLOCK          8
+
+#define TCP_TIME_RETRANS       1       /* Retransmit timer */
+#define TCP_TIME_DACK          2       /* Delayed ack timer */
+#define TCP_TIME_PROBE0                3       /* Zero window probe timer */
+#define TCP_TIME_KEEPOPEN      4       /* Keepalive timer */
+
+#if 0
+/* sysctl variables for tcp */
+extern int sysctl_max_syn_backlog;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_fin_timeout;
+extern int sysctl_tcp_tw_recycle;
+extern int sysctl_tcp_keepalive_time;
+extern int sysctl_tcp_keepalive_probes;
+extern int sysctl_tcp_keepalive_intvl;
+extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_synack_retries;
+extern int sysctl_tcp_retries1;
+extern int sysctl_tcp_retries2;
+extern int sysctl_tcp_orphan_retries;
+extern int sysctl_tcp_syncookies;
+extern int sysctl_tcp_retrans_collapse;
+extern int sysctl_tcp_stdurg;
+extern int sysctl_tcp_rfc1337;
+extern int sysctl_tcp_abort_on_overflow;
+extern int sysctl_tcp_max_orphans;
+extern int sysctl_tcp_max_tw_buckets;
+extern int sysctl_tcp_fack;
+extern int sysctl_tcp_reordering;
+extern int sysctl_tcp_ecn;
+extern int sysctl_tcp_dsack;
+extern int sysctl_tcp_mem[3];
+extern int sysctl_tcp_wmem[3];
+extern int sysctl_tcp_rmem[3];
+extern int sysctl_tcp_app_win;
+extern int sysctl_tcp_adv_win_scale;
+extern int sysctl_tcp_tw_reuse;
+#endif
+
+extern atomic_t tcp_memory_allocated;
+extern atomic_t tcp_sockets_allocated;
+extern int tcp_memory_pressure;
+
+struct open_request;
+
+struct or_calltable {
+       int  family;
+       int  (*rtx_syn_ack)     (struct sock *sk, struct open_request *req, struct dst_entry*);
+       void (*send_ack)        (struct sk_buff *skb, struct open_request *req);
+       void (*destructor)      (struct open_request *req);
+       void (*send_reset)      (struct sk_buff *skb);
+};
+
+struct tcp_v4_open_req {
+       __u32                   loc_addr;
+       __u32                   rmt_addr;
+       struct ip_options       *opt;
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct tcp_v6_open_req {
+       struct in6_addr         loc_addr;
+       struct in6_addr         rmt_addr;
+       struct sk_buff          *pktopts;
+       int                     iif;
+};
+#endif
+
+/* this structure is too big */
+struct open_request {
+       struct open_request     *dl_next; /* Must be first member! */
+       __u32                   rcv_isn;
+       __u32                   snt_isn;
+       __u16                   rmt_port;
+       __u16                   mss;
+       __u8                    retrans;
+       __u8                    __pad;
+       __u16   snd_wscale : 4, 
+               rcv_wscale : 4, 
+               tstamp_ok : 1,
+               sack_ok : 1,
+               wscale_ok : 1,
+               ecn_ok : 1,
+               acked : 1;
+       /* The following two fields can be easily recomputed I think -AK */
+       __u32                   window_clamp;   /* window clamp at creation time */
+       __u32                   rcv_wnd;        /* rcv_wnd offered first time */
+       __u32                   ts_recent;
+       unsigned long           expires;
+       struct or_calltable     *class;
+       struct sock             *sk;
+       union {
+               struct tcp_v4_open_req v4_req;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+               struct tcp_v6_open_req v6_req;
+#endif
+       } af;
+};
+
+/* SLAB cache for open requests. */
+extern kmem_cache_t *tcp_openreq_cachep;
+
+#define tcp_openreq_alloc()            kmem_cache_alloc(tcp_openreq_cachep, SLAB_ATOMIC)
+#define tcp_openreq_fastfree(req)      kmem_cache_free(tcp_openreq_cachep, req)
+
+static inline void tcp_openreq_free(struct open_request *req)
+{
+       req->class->destructor(req);
+       tcp_openreq_fastfree(req);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#define TCP_INET_FAMILY(fam) ((fam) == AF_INET)
+#else
+#define TCP_INET_FAMILY(fam) 1
+#endif
+
+/*
+ *     Pointers to address related TCP functions
+ *     (i.e. things that depend on the address family)
+ *
+ *     BUGGG_FUTURE: all the idea behind this struct is wrong.
+ *     It mixes socket frontend with transport function.
+ *     With port sharing between IPv6/v4 it gives the only advantage,
+ *     only poor IPv6 needs to permanently recheck, that it
+ *     is still IPv6 8)8) It must be cleaned up as soon as possible.
+ *                                             --ANK (980802)
+ */
+
+struct tcp_func {
+       int                     (*queue_xmit)           (struct sk_buff *skb);
+
+       void                    (*send_check)           (struct sock *sk,
+                                                        struct tcphdr *th,
+                                                        int len,
+                                                        struct sk_buff *skb);
+
+       int                     (*rebuild_header)       (struct sock *sk);
+
+       int                     (*conn_request)         (struct sock *sk,
+                                                        struct sk_buff *skb);
+
+       struct sock *           (*syn_recv_sock)        (struct sock *sk,
+                                                        struct sk_buff *skb,
+                                                        struct open_request *req,
+                                                        struct dst_entry *dst);
+    
+       int                     (*remember_stamp)       (struct sock *sk);
+
+       __u16                   net_header_len;
+
+       int                     (*setsockopt)           (struct sock *sk, 
+                                                        int level, 
+                                                        int optname, 
+                                                        char *optval, 
+                                                        int optlen);
+
+       int                     (*getsockopt)           (struct sock *sk, 
+                                                        int level, 
+                                                        int optname, 
+                                                        char *optval, 
+                                                        int *optlen);
+
+
+       void                    (*addr2sockaddr)        (struct sock *sk,
+                                                        struct sockaddr *);
+
+       int sockaddr_len;
+};
+
+/*
+ * The next routines deal with comparing 32 bit unsigned ints
+ * and worry about wraparound (automatic with unsigned arithmetic).
+ */
+
+extern __inline int before(__u32 seq1, __u32 seq2)
+{
+        return (__s32)(seq1-seq2) < 0;
+}
+
+extern __inline int after(__u32 seq1, __u32 seq2)
+{
+       return (__s32)(seq2-seq1) < 0;
+}
+
+
+/* is s2<=s1<=s3 ? */
+extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
+{
+       return seq3 - seq2 >= seq1 - seq2;
+}
+
+
+extern struct proto tcp_prot;
+
+#ifdef ROS_STATISTICS
+extern struct tcp_mib tcp_statistics[NR_CPUS*2];
+
+#define TCP_INC_STATS(field)           SNMP_INC_STATS(tcp_statistics, field)
+#define TCP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(tcp_statistics, field)
+#define TCP_INC_STATS_USER(field)      SNMP_INC_STATS_USER(tcp_statistics, field)
+#endif
+
+extern void                    tcp_put_port(struct sock *sk);
+extern void                    __tcp_put_port(struct sock *sk);
+extern void                    tcp_inherit_port(struct sock *sk, struct sock *child);
+
+extern void                    tcp_v4_err(struct sk_buff *skb, u32);
+
+extern void                    tcp_shutdown (struct sock *sk, int how);
+
+extern int                     tcp_v4_rcv(struct sk_buff *skb);
+
+extern int                     tcp_v4_remember_stamp(struct sock *sk);
+
+extern int                     tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw);
+
+extern int                     tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size);
+extern ssize_t                 tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
+
+extern int                     tcp_ioctl(struct sock *sk, 
+                                         int cmd, 
+                                         unsigned long arg);
+
+extern int                     tcp_rcv_state_process(struct sock *sk, 
+                                                     struct sk_buff *skb,
+                                                     struct tcphdr *th,
+                                                     unsigned len);
+
+extern int                     tcp_rcv_established(struct sock *sk, 
+                                                   struct sk_buff *skb,
+                                                   struct tcphdr *th, 
+                                                   unsigned len);
+
+enum tcp_ack_state_t
+{
+       TCP_ACK_SCHED = 1,
+       TCP_ACK_TIMER = 2,
+       TCP_ACK_PUSHED= 4
+};
+
+static inline void tcp_schedule_ack(struct tcp_opt *tp)
+{
+       tp->ack.pending |= TCP_ACK_SCHED;
+}
+
+static inline int tcp_ack_scheduled(struct tcp_opt *tp)
+{
+       return tp->ack.pending&TCP_ACK_SCHED;
+}
+
+static __inline__ void tcp_dec_quickack_mode(struct tcp_opt *tp)
+{
+       if (tp->ack.quick && --tp->ack.quick == 0) {
+               /* Leaving quickack mode we deflate ATO. */
+               tp->ack.ato = TCP_ATO_MIN;
+       }
+}
+
+extern void tcp_enter_quickack_mode(struct tcp_opt *tp);
+
+static __inline__ void tcp_delack_init(struct tcp_opt *tp)
+{
+       memset(&tp->ack, 0, sizeof(tp->ack));
+}
+
+static inline void tcp_clear_options(struct tcp_opt *tp)
+{
+       tp->tstamp_ok = tp->sack_ok = tp->wscale_ok = tp->snd_wscale = 0;
+}
+
+enum tcp_tw_status
+{
+       TCP_TW_SUCCESS = 0,
+       TCP_TW_RST = 1,
+       TCP_TW_ACK = 2,
+       TCP_TW_SYN = 3
+};
+
+
+extern enum tcp_tw_status      tcp_timewait_state_process(struct tcp_tw_bucket *tw,
+                                                          struct sk_buff *skb,
+                                                          struct tcphdr *th,
+                                                          unsigned len);
+
+extern struct sock *           tcp_check_req(struct sock *sk,struct sk_buff *skb,
+                                             struct open_request *req,
+                                             struct open_request **prev);
+extern int                     tcp_child_process(struct sock *parent,
+                                                 struct sock *child,
+                                                 struct sk_buff *skb);
+extern void                    tcp_enter_loss(struct sock *sk, int how);
+extern void                    tcp_clear_retrans(struct tcp_opt *tp);
+extern void                    tcp_update_metrics(struct sock *sk);
+
+extern void                    tcp_close(struct sock *sk, 
+                                         long timeout);
+extern struct sock *           tcp_accept(struct sock *sk, int flags, int *err);
+extern unsigned int            tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
+extern void                    tcp_write_space(struct sock *sk); 
+
+extern int                     tcp_getsockopt(struct sock *sk, int level, 
+                                              int optname, char *optval, 
+                                              int *optlen);
+extern int                     tcp_setsockopt(struct sock *sk, int level, 
+                                              int optname, char *optval, 
+                                              int optlen);
+extern void                    tcp_set_keepalive(struct sock *sk, int val);
+extern int                     tcp_recvmsg(struct sock *sk, 
+                                           struct msghdr *msg,
+                                           int len, int nonblock, 
+                                           int flags, int *addr_len);
+
+extern int                     tcp_listen_start(struct sock *sk);
+
+extern void                    tcp_parse_options(struct sk_buff *skb,
+                                                 struct tcp_opt *tp,
+                                                 int estab);
+
+/*
+ *     TCP v4 functions exported for the inet6 API
+ */
+
+extern int                     tcp_v4_rebuild_header(struct sock *sk);
+
+extern int                     tcp_v4_build_header(struct sock *sk, 
+                                                   struct sk_buff *skb);
+
+extern void                    tcp_v4_send_check(struct sock *sk, 
+                                                 struct tcphdr *th, int len, 
+                                                 struct sk_buff *skb);
+
+extern int                     tcp_v4_conn_request(struct sock *sk,
+                                                   struct sk_buff *skb);
+
+extern struct sock *           tcp_create_openreq_child(struct sock *sk,
+                                                        struct open_request *req,
+                                                        struct sk_buff *skb);
+
+extern struct sock *           tcp_v4_syn_recv_sock(struct sock *sk,
+                                                    struct sk_buff *skb,
+                                                    struct open_request *req,
+                                                       struct dst_entry *dst);
+
+extern int                     tcp_v4_do_rcv(struct sock *sk,
+                                             struct sk_buff *skb);
+
+extern int                     tcp_v4_connect(struct sock *sk,
+                                              struct sockaddr *uaddr,
+                                              int addr_len);
+
+extern int                     tcp_connect(struct sock *sk);
+
+extern struct sk_buff *                tcp_make_synack(struct sock *sk,
+                                               struct dst_entry *dst,
+                                               struct open_request *req);
+
+extern int                     tcp_disconnect(struct sock *sk, int flags);
+
+extern void                    tcp_unhash(struct sock *sk);
+
+extern int                     tcp_v4_hash_connecting(struct sock *sk);
+
+
+/* From syncookies.c */
+extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 
+                                   struct ip_options *opt);
+extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
+                                    __u16 *mss);
+
+/* tcp_output.c */
+
+extern int tcp_write_xmit(struct sock *, int nonagle);
+extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_xmit_retransmit_queue(struct sock *);
+extern void tcp_simple_retransmit(struct sock *);
+
+extern void tcp_send_probe0(struct sock *);
+extern void tcp_send_partial(struct sock *);
+extern int  tcp_write_wakeup(struct sock *);
+extern void tcp_send_fin(struct sock *sk);
+extern void tcp_send_active_reset(struct sock *sk, int priority);
+extern int  tcp_send_synack(struct sock *);
+extern int  tcp_transmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_send_skb(struct sock *, struct sk_buff *, int force_queue, unsigned mss_now);
+extern void tcp_push_one(struct sock *, unsigned mss_now);
+extern void tcp_send_ack(struct sock *sk);
+extern void tcp_send_delayed_ack(struct sock *sk);
+
+/* tcp_timer.c */
+extern void tcp_init_xmit_timers(struct sock *);
+extern void tcp_clear_xmit_timers(struct sock *);
+
+extern void tcp_delete_keepalive_timer (struct sock *);
+extern void tcp_reset_keepalive_timer (struct sock *, unsigned long);
+extern int tcp_sync_mss(struct sock *sk, u32 pmtu);
+
+extern const char timer_bug_msg[];
+
+/* Read 'sendfile()'-style from a TCP socket */
+typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
+                               unsigned int, size_t);
+extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+                        sk_read_actor_t recv_actor);
+
+static inline void tcp_clear_xmit_timer(struct sock *sk, int what)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       
+       switch (what) {
+       case TCP_TIME_RETRANS:
+       case TCP_TIME_PROBE0:
+               tp->pending = 0;
+
+#ifdef TCP_CLEAR_TIMERS
+               if (timer_pending(&tp->retransmit_timer) &&
+                   del_timer(&tp->retransmit_timer))
+                       __sock_put(sk);
+#endif
+               break;
+       case TCP_TIME_DACK:
+               tp->ack.blocked = 0;
+               tp->ack.pending = 0;
+
+#ifdef TCP_CLEAR_TIMERS
+               if (timer_pending(&tp->delack_timer) &&
+                   del_timer(&tp->delack_timer))
+                       __sock_put(sk);
+#endif
+               break;
+       default:
+               printk(timer_bug_msg);
+               return;
+       };
+#endif
+}
+
+/*
+ *     Reset the retransmission timer
+ */
+static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       if (when > TCP_RTO_MAX) {
+#ifdef TCP_DEBUG
+               printk(KERN_DEBUG "reset_xmit_timer sk=%p %d when=0x%lx, caller=%p\n", sk, what, when, current_text_addr());
+#endif
+               when = TCP_RTO_MAX;
+       }
+
+       switch (what) {
+       case TCP_TIME_RETRANS:
+       case TCP_TIME_PROBE0:
+               tp->pending = what;
+               tp->timeout = jiffies+when;
+               if (!mod_timer(&tp->retransmit_timer, tp->timeout))
+                       sock_hold(sk);
+               break;
+
+       case TCP_TIME_DACK:
+               tp->ack.pending |= TCP_ACK_TIMER;
+               tp->ack.timeout = jiffies+when;
+               if (!mod_timer(&tp->delack_timer, tp->ack.timeout))
+                       sock_hold(sk);
+               break;
+
+       default:
+               printk(KERN_DEBUG "bug: unknown timer value\n");
+       };
+#endif
+}
+
+/* Compute the current effective MSS, taking SACKs and IP options,
+ * and even PMTU discovery events into account.
+ */
+
+static __inline__ unsigned int tcp_current_mss(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct dst_entry *dst = __sk_dst_get(sk);
+       int mss_now = tp->mss_cache; 
+
+       if (dst && dst->pmtu != tp->pmtu_cookie)
+               mss_now = tcp_sync_mss(sk, dst->pmtu);
+
+       if (tp->eff_sacks)
+               mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
+                           (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
+       return mss_now;
+#else
+  return 0;
+#endif
+}
+
+/* Initialize RCV_MSS value.
+ * RCV_MSS is an our guess about MSS used by the peer.
+ * We haven't any direct information about the MSS.
+ * It's better to underestimate the RCV_MSS rather than overestimate.
+ * Overestimations make us ACKing less frequently than needed.
+ * Underestimations are more easy to detect and fix by tcp_measure_rcv_mss().
+ */
+
+static inline void tcp_initialize_rcv_mss(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       unsigned int hint = min(tp->advmss, tp->mss_cache);
+
+       hint = min(hint, tp->rcv_wnd/2);
+       hint = min(hint, TCP_MIN_RCVMSS);
+       hint = max(hint, TCP_MIN_MSS);
+
+       tp->ack.rcv_mss = hint;
+#endif
+}
+
+static __inline__ void __tcp_fast_path_on(struct tcp_opt *tp, u32 snd_wnd)
+{
+#if 0
+       tp->pred_flags = htonl((tp->tcp_header_len << 26) |
+                              ntohl(TCP_FLAG_ACK) |
+                              snd_wnd);
+#endif
+}
+
+static __inline__ void tcp_fast_path_on(struct tcp_opt *tp)
+{
+#if 0
+       __tcp_fast_path_on(tp, tp->snd_wnd>>tp->snd_wscale);
+#endif
+}
+
+static inline void tcp_fast_path_check(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (skb_queue_len(&tp->out_of_order_queue) == 0 &&
+           tp->rcv_wnd &&
+           atomic_read(&sk->rmem_alloc) < sk->rcvbuf &&
+           !tp->urg_data)
+               tcp_fast_path_on(tp);
+#endif
+}
+
+/* Compute the actual receive window we are currently advertising.
+ * Rcv_nxt can be after the window if our peer push more data
+ * than the offered window.
+ */
+static __inline__ u32 tcp_receive_window(struct tcp_opt *tp)
+{
+#if 0
+       s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
+
+       if (win < 0)
+               win = 0;
+       return (u32) win;
+#else
+  return 0;
+#endif
+}
+
+/* Choose a new window, without checks for shrinking, and without
+ * scaling applied to the result.  The caller does these things
+ * if necessary.  This is a "raw" window selection.
+ */
+extern u32     __tcp_select_window(struct sock *sk);
+
+/* TCP timestamps are only 32-bits, this causes a slight
+ * complication on 64-bit systems since we store a snapshot
+ * of jiffies in the buffer control blocks below.  We decidely
+ * only use of the low 32-bits of jiffies and hide the ugly
+ * casts with the following macro.
+ */
+#define tcp_time_stamp         ((__u32)(jiffies))
+
+/* This is what the send packet queueing engine uses to pass
+ * TCP per-packet control information to the transmission
+ * code.  We also store the host-order sequence numbers in
+ * here too.  This is 36 bytes on 32-bit architectures,
+ * 40 bytes on 64-bit machines, if this grows please adjust
+ * skbuff.h:skbuff->cb[xxx] size appropriately.
+ */
+struct tcp_skb_cb {
+       union {
+#if 0
+               struct inet_skb_parm    h4;
+#endif
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+               struct inet6_skb_parm   h6;
+#endif
+       } header;       /* For incoming frames          */
+       __u32           seq;            /* Starting sequence number     */
+       __u32           end_seq;        /* SEQ + FIN + SYN + datalen    */
+       __u32           when;           /* used to compute rtt's        */
+       __u8            flags;          /* TCP header flags.            */
+
+       /* NOTE: These must match up to the flags byte in a
+        *       real TCP header.
+        */
+#define TCPCB_FLAG_FIN         0x01
+#define TCPCB_FLAG_SYN         0x02
+#define TCPCB_FLAG_RST         0x04
+#define TCPCB_FLAG_PSH         0x08
+#define TCPCB_FLAG_ACK         0x10
+#define TCPCB_FLAG_URG         0x20
+#define TCPCB_FLAG_ECE         0x40
+#define TCPCB_FLAG_CWR         0x80
+
+       __u8            sacked;         /* State flags for SACK/FACK.   */
+#define TCPCB_SACKED_ACKED     0x01    /* SKB ACK'd by a SACK block    */
+#define TCPCB_SACKED_RETRANS   0x02    /* SKB retransmitted            */
+#define TCPCB_LOST             0x04    /* SKB is lost                  */
+#define TCPCB_TAGBITS          0x07    /* All tag bits                 */
+
+#define TCPCB_EVER_RETRANS     0x80    /* Ever retransmitted frame     */
+#define TCPCB_RETRANS          (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
+
+#define TCPCB_URG              0x20    /* Urgent pointer advenced here */
+
+#define TCPCB_AT_TAIL          (TCPCB_URG)
+
+       __u16           urg_ptr;        /* Valid w/URG flags is set.    */
+       __u32           ack_seq;        /* Sequence number ACK'd        */
+};
+
+#define TCP_SKB_CB(__skb)      ((struct tcp_skb_cb *)&((__skb)->cb[0]))
+
+#define for_retrans_queue(skb, sk, tp) \
+               for (skb = (sk)->write_queue.next;                      \
+                    (skb != (tp)->send_head) &&                        \
+                    (skb != (struct sk_buff *)&(sk)->write_queue);     \
+                    skb=skb->next)
+
+
+//#include <net/tcp_ecn.h>
+
+
+/*
+ *     Compute minimal free write space needed to queue new packets. 
+ */
+static inline int tcp_min_write_space(struct sock *sk)
+{
+#if 0
+       return sk->wmem_queued/2;
+#else
+return 0;
+#endif
+}
+static inline int tcp_wspace(struct sock *sk)
+{
+#if 0
+       return sk->sndbuf - sk->wmem_queued;
+#else
+return 0;
+#endif
+}
+
+
+/* This determines how many packets are "in the network" to the best
+ * of our knowledge.  In many cases it is conservative, but where
+ * detailed information is available from the receiver (via SACK
+ * blocks etc.) we can make more aggressive calculations.
+ *
+ * Use this for decisions involving congestion control, use just
+ * tp->packets_out to determine if the send queue is empty or not.
+ *
+ * Read this equation as:
+ *
+ *     "Packets sent once on transmission queue" MINUS
+ *     "Packets left network, but not honestly ACKed yet" PLUS
+ *     "Packets fast retransmitted"
+ */
+static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
+{
+#if 0
+       return tp->packets_out - tp->left_out + tp->retrans_out;
+#else
+  return 0;
+#endif
+}
+
+/* Recalculate snd_ssthresh, we want to set it to:
+ *
+ *     one half the current congestion window, but no
+ *     less than two segments
+ */
+static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
+{
+#if 0
+       return max(tp->snd_cwnd >> 1U, 2U);
+#else
+  return 0;
+#endif
+}
+
+/* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
+ * The exception is rate halving phase, when cwnd is decreasing towards
+ * ssthresh.
+ */
+static inline __u32 tcp_current_ssthresh(struct tcp_opt *tp)
+{
+#if 0
+       if ((1<<tp->ca_state)&(TCPF_CA_CWR|TCPF_CA_Recovery))
+               return tp->snd_ssthresh;
+       else
+               return max(tp->snd_ssthresh,
+                          ((tp->snd_cwnd >> 1) +
+                           (tp->snd_cwnd >> 2)));
+#else
+  return 0;
+#endif
+}
+
+static inline void tcp_sync_left_out(struct tcp_opt *tp)
+{
+#if 0
+       if (tp->sack_ok && tp->sacked_out >= tp->packets_out - tp->lost_out)
+               tp->sacked_out = tp->packets_out - tp->lost_out;
+       tp->left_out = tp->sacked_out + tp->lost_out;
+#endif
+}
+
+extern void tcp_cwnd_application_limited(struct sock *sk);
+
+/* Congestion window validation. (RFC2861) */
+
+static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (tp->packets_out >= tp->snd_cwnd) {
+               /* Network is feed fully. */
+               tp->snd_cwnd_used = 0;
+               tp->snd_cwnd_stamp = tcp_time_stamp;
+       } else {
+               /* Network starves. */
+               if (tp->packets_out > tp->snd_cwnd_used)
+                       tp->snd_cwnd_used = tp->packets_out;
+
+               if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= tp->rto)
+                       tcp_cwnd_application_limited(sk);
+       }
+#endif
+}
+
+/* Set slow start threshould and cwnd not falling to slow start */
+static inline void __tcp_enter_cwr(struct tcp_opt *tp)
+{
+#if 0
+       tp->undo_marker = 0;
+       tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+       tp->snd_cwnd = min(tp->snd_cwnd,
+                          tcp_packets_in_flight(tp) + 1U);
+       tp->snd_cwnd_cnt = 0;
+       tp->high_seq = tp->snd_nxt;
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+       TCP_ECN_queue_cwr(tp);
+#endif
+}
+
+static inline void tcp_enter_cwr(struct tcp_opt *tp)
+{
+#if 0
+       tp->prior_ssthresh = 0;
+       if (tp->ca_state < TCP_CA_CWR) {
+               __tcp_enter_cwr(tp);
+               tp->ca_state = TCP_CA_CWR;
+       }
+#endif
+}
+
+extern __u32 tcp_init_cwnd(struct tcp_opt *tp);
+
+/* Slow start with delack produces 3 packets of burst, so that
+ * it is safe "de facto".
+ */
+static __inline__ __u32 tcp_max_burst(struct tcp_opt *tp)
+{
+       return 3;
+}
+
+static __inline__ int tcp_minshall_check(struct tcp_opt *tp)
+{
+#if 0
+       return after(tp->snd_sml,tp->snd_una) &&
+               !after(tp->snd_sml, tp->snd_nxt);
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void tcp_minshall_update(struct tcp_opt *tp, int mss, struct sk_buff *skb)
+{
+#if 0
+       if (skb->len < mss)
+               tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
+#endif
+}
+
+/* Return 0, if packet can be sent now without violation Nagle's rules:
+   1. It is full sized.
+   2. Or it contains FIN.
+   3. Or TCP_NODELAY was set.
+   4. Or TCP_CORK is not set, and all sent packets are ACKed.
+      With Minshall's modification: all sent small packets are ACKed.
+ */
+
+static __inline__ int
+tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int nonagle)
+{
+#if 0
+       return (skb->len < mss_now &&
+               !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+               (nonagle == 2 ||
+                (!nonagle &&
+                 tp->packets_out &&
+                 tcp_minshall_check(tp))));
+#else
+  return 0;
+#endif
+}
+
+/* This checks if the data bearing packet SKB (usually tp->send_head)
+ * should be put on the wire right now.
+ */
+static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
+                                  unsigned cur_mss, int nonagle)
+{
+#if 0
+       /*      RFC 1122 - section 4.2.3.4
+        *
+        *      We must queue if
+        *
+        *      a) The right edge of this frame exceeds the window
+        *      b) There are packets in flight and we have a small segment
+        *         [SWS avoidance and Nagle algorithm]
+        *         (part of SWS is done on packetization)
+        *         Minshall version sounds: there are no _small_
+        *         segments in flight. (tcp_nagle_check)
+        *      c) We have too many packets 'in flight'
+        *
+        *      Don't use the nagle rule for urgent data (or
+        *      for the final FIN -DaveM).
+        *
+        *      Also, Nagle rule does not apply to frames, which
+        *      sit in the middle of queue (they have no chances
+        *      to get new data) and if room at tail of skb is
+        *      not enough to save something seriously (<32 for now).
+        */
+
+       /* Don't be strict about the congestion window for the
+        * final FIN frame.  -DaveM
+        */
+       return ((nonagle==1 || tp->urg_mode
+                || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
+               ((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
+                (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
+               !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (!tp->packets_out && !tp->pending)
+               tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
+#endif
+}
+
+static __inline__ int tcp_skb_is_last(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       return (skb->next == (struct sk_buff*)&sk->write_queue);
+#else
+  return 0;
+#endif
+}
+
+/* Push out any pending frames which were held back due to
+ * TCP_CORK or attempt at coalescing tiny packets.
+ * The socket must be locked by the caller.
+ */
+static __inline__ void __tcp_push_pending_frames(struct sock *sk,
+                                                struct tcp_opt *tp,
+                                                unsigned cur_mss,
+                                                int nonagle)
+{
+#if 0
+       struct sk_buff *skb = tp->send_head;
+
+       if (skb) {
+               if (!tcp_skb_is_last(sk, skb))
+                       nonagle = 1;
+               if (!tcp_snd_test(tp, skb, cur_mss, nonagle) ||
+                   tcp_write_xmit(sk, nonagle))
+                       tcp_check_probe_timer(sk, tp);
+       }
+       tcp_cwnd_validate(sk, tp);
+#endif
+}
+
+static __inline__ void tcp_push_pending_frames(struct sock *sk,
+                                              struct tcp_opt *tp)
+{
+#if 0
+       __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk), tp->nonagle);
+#endif
+}
+
+static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       struct sk_buff *skb = tp->send_head;
+
+       return (skb &&
+               tcp_snd_test(tp, skb, tcp_current_mss(sk),
+                            tcp_skb_is_last(sk, skb) ? 1 : tp->nonagle));
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void tcp_init_wl(struct tcp_opt *tp, u32 ack, u32 seq)
+{
+#if 0
+       tp->snd_wl1 = seq;
+#endif
+}
+
+static __inline__ void tcp_update_wl(struct tcp_opt *tp, u32 ack, u32 seq)
+{
+#if 0
+       tp->snd_wl1 = seq;
+#endif
+}
+
+extern void                    tcp_destroy_sock(struct sock *sk);
+
+
+/*
+ * Calculate(/check) TCP checksum
+ */
+static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
+                                  unsigned long saddr, unsigned long daddr, 
+                                  unsigned long base)
+{
+#if 0
+       return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int __tcp_checksum_complete(struct sk_buff *skb)
+{
+#if 0
+       return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int tcp_checksum_complete(struct sk_buff *skb)
+{
+#if 0
+       return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+               __tcp_checksum_complete(skb);
+#else
+  return 0;
+#endif
+}
+
+/* Prequeue for VJ style copy to user, combined with checksumming. */
+
+static __inline__ void tcp_prequeue_init(struct tcp_opt *tp)
+{
+#if 0
+       tp->ucopy.task = NULL;
+       tp->ucopy.len = 0;
+       tp->ucopy.memory = 0;
+       skb_queue_head_init(&tp->ucopy.prequeue);
+#endif
+}
+
+/* Packet is added to VJ-style prequeue for processing in process
+ * context, if a reader task is waiting. Apparently, this exciting
+ * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
+ * failed somewhere. Latency? Burstiness? Well, at least now we will
+ * see, why it failed. 8)8)                              --ANK
+ *
+ * NOTE: is this not too big to inline?
+ */
+static __inline__ int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       if (tp->ucopy.task) {
+               __skb_queue_tail(&tp->ucopy.prequeue, skb);
+               tp->ucopy.memory += skb->truesize;
+               if (tp->ucopy.memory > sk->rcvbuf) {
+                       struct sk_buff *skb1;
+
+                       if (sk->lock.users)
+                               out_of_line_bug();
+
+                       while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
+                               sk->backlog_rcv(sk, skb1);
+                               NET_INC_STATS_BH(TCPPrequeueDropped);
+                       }
+
+                       tp->ucopy.memory = 0;
+               } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
+                       wake_up_interruptible(sk->sleep);
+                       if (!tcp_ack_scheduled(tp))
+                               tcp_reset_xmit_timer(sk, TCP_TIME_DACK, (3*TCP_RTO_MIN)/4);
+               }
+               return 1;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+
+#undef STATE_TRACE
+
+#ifdef STATE_TRACE
+static char *statename[]={
+       "Unused","Established","Syn Sent","Syn Recv",
+       "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
+       "Close Wait","Last ACK","Listen","Closing"
+};
+#endif
+
+static __inline__ void tcp_set_state(struct sock *sk, int state)
+{
+#if 0
+       int oldstate = sk->state;
+
+       switch (state) {
+       case TCP_ESTABLISHED:
+               if (oldstate != TCP_ESTABLISHED)
+                       TCP_INC_STATS(TcpCurrEstab);
+               break;
+
+       case TCP_CLOSE:
+               sk->prot->unhash(sk);
+               if (sk->prev && !(sk->userlocks&SOCK_BINDPORT_LOCK))
+                       tcp_put_port(sk);
+               /* fall through */
+       default:
+               if (oldstate==TCP_ESTABLISHED)
+                       tcp_statistics[smp_processor_id()*2+!in_softirq()].TcpCurrEstab--;
+       }
+
+       /* Change state AFTER socket is unhashed to avoid closed
+        * socket sitting in hash tables.
+        */
+       sk->state = state;
+
+#ifdef STATE_TRACE
+       SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]);
+#endif 
+#endif
+}
+
+static __inline__ void tcp_done(struct sock *sk)
+{
+#if 0
+       tcp_set_state(sk, TCP_CLOSE);
+       tcp_clear_xmit_timers(sk);
+
+       sk->shutdown = SHUTDOWN_MASK;
+
+       if (!sk->dead)
+               sk->state_change(sk);
+       else
+               tcp_destroy_sock(sk);
+#endif
+}
+
+static __inline__ void tcp_sack_reset(struct tcp_opt *tp)
+{
+#if 0
+       tp->dsack = 0;
+       tp->eff_sacks = 0;
+       tp->num_sacks = 0;
+#endif
+}
+
+static __inline__ void tcp_build_and_update_options(__u32 *ptr, struct tcp_opt *tp, __u32 tstamp)
+{
+#if 0
+       if (tp->tstamp_ok) {
+               *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+                                         (TCPOPT_NOP << 16) |
+                                         (TCPOPT_TIMESTAMP << 8) |
+                                         TCPOLEN_TIMESTAMP);
+               *ptr++ = htonl(tstamp);
+               *ptr++ = htonl(tp->ts_recent);
+       }
+       if (tp->eff_sacks) {
+               struct tcp_sack_block *sp = tp->dsack ? tp->duplicate_sack : tp->selective_acks;
+               int this_sack;
+
+               *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+                                         (TCPOPT_NOP << 16) |
+                                         (TCPOPT_SACK << 8) |
+                                         (TCPOLEN_SACK_BASE +
+                                          (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK)));
+               for(this_sack = 0; this_sack < tp->eff_sacks; this_sack++) {
+                       *ptr++ = htonl(sp[this_sack].start_seq);
+                       *ptr++ = htonl(sp[this_sack].end_seq);
+               }
+               if (tp->dsack) {
+                       tp->dsack = 0;
+                       tp->eff_sacks--;
+               }
+       }
+#endif
+}
+
+/* Construct a tcp options header for a SYN or SYN_ACK packet.
+ * If this is every changed make sure to change the definition of
+ * MAX_SYN_SIZE to match the new maximum number of options that you
+ * can generate.
+ */
+static inline void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+                                            int offer_wscale, int wscale, __u32 tstamp, __u32 ts_recent)
+{
+#if 0
+       /* We always get an MSS option.
+        * The option bytes which will be seen in normal data
+        * packets should timestamps be used, must be in the MSS
+        * advertised.  But we subtract them from tp->mss_cache so
+        * that calculations in tcp_sendmsg are simpler etc.
+        * So account for this fact here if necessary.  If we
+        * don't do this correctly, as a receiver we won't
+        * recognize data packets as being full sized when we
+        * should, and thus we won't abide by the delayed ACK
+        * rules correctly.
+        * SACKs don't matter, we never delay an ACK when we
+        * have any of those going out.
+        */
+       *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
+       if (ts) {
+               if(sack)
+                       *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
+                                                 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+               else
+                       *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+                                                 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+               *ptr++ = htonl(tstamp);         /* TSVAL */
+               *ptr++ = htonl(ts_recent);      /* TSECR */
+       } else if(sack)
+               *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+                                         (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+       if (offer_wscale)
+               *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+#endif
+}
+
+/* Determine a window scaling and initial window to offer.
+ * Based on the assumption that the given amount of space
+ * will be offered. Store the results in the tp structure.
+ * NOTE: for smooth operation initial space offering should
+ * be a multiple of mss if possible. We assume here that mss >= 1.
+ * This MUST be enforced by all callers.
+ */
+static inline void tcp_select_initial_window(int __space, __u32 mss,
+       __u32 *rcv_wnd,
+       __u32 *window_clamp,
+       int wscale_ok,
+       __u8 *rcv_wscale)
+{
+#if 0
+       unsigned int space = (__space < 0 ? 0 : __space);
+
+       /* If no clamp set the clamp to the max possible scaled window */
+       if (*window_clamp == 0)
+               (*window_clamp) = (65535 << 14);
+       space = min(*window_clamp, space);
+
+       /* Quantize space offering to a multiple of mss if possible. */
+       if (space > mss)
+               space = (space / mss) * mss;
+
+       /* NOTE: offering an initial window larger than 32767
+        * will break some buggy TCP stacks. We try to be nice.
+        * If we are not window scaling, then this truncates
+        * our initial window offering to 32k. There should also
+        * be a sysctl option to stop being nice.
+        */
+       (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
+       (*rcv_wscale) = 0;
+       if (wscale_ok) {
+               /* See RFC1323 for an explanation of the limit to 14 */
+               while (space > 65535 && (*rcv_wscale) < 14) {
+                       space >>= 1;
+                       (*rcv_wscale)++;
+               }
+               if (*rcv_wscale && sysctl_tcp_app_win && space>=mss &&
+                   space - max((space>>sysctl_tcp_app_win), mss>>*rcv_wscale) < 65536/2)
+                       (*rcv_wscale)--;
+       }
+
+       /* Set initial window to value enough for senders,
+        * following RFC1414. Senders, not following this RFC,
+        * will be satisfied with 2.
+        */
+       if (mss > (1<<*rcv_wscale)) {
+               int init_cwnd = 4;
+               if (mss > 1460*3)
+                       init_cwnd = 2;
+               else if (mss > 1460)
+                       init_cwnd = 3;
+               if (*rcv_wnd > init_cwnd*mss)
+                       *rcv_wnd = init_cwnd*mss;
+       }
+       /* Set the clamp no higher than max representable value */
+       (*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
+#endif
+}
+
+static inline int tcp_win_from_space(int space)
+{
+#if 0
+       return sysctl_tcp_adv_win_scale<=0 ?
+               (space>>(-sysctl_tcp_adv_win_scale)) :
+               space - (space>>sysctl_tcp_adv_win_scale);
+#else
+  return 0;
+#endif
+}
+
+/* Note: caller must be prepared to deal with negative returns */ 
+static inline int tcp_space(struct sock *sk)
+{
+#if 0
+       return tcp_win_from_space(sk->rcvbuf - atomic_read(&sk->rmem_alloc));
+#else
+  return 0;
+#endif
+} 
+
+static inline int tcp_full_space( struct sock *sk)
+{
+#if 0
+       return tcp_win_from_space(sk->rcvbuf); 
+#else
+  return 0;
+#endif
+}
+
+static inline void tcp_acceptq_removed(struct sock *sk)
+{
+#if 0
+       sk->ack_backlog--;
+#endif
+}
+
+static inline void tcp_acceptq_added(struct sock *sk)
+{
+#if 0
+       sk->ack_backlog++;
+#endif
+}
+
+static inline int tcp_acceptq_is_full(struct sock *sk)
+{
+#if 0
+       return sk->ack_backlog > sk->max_ack_backlog;
+#else
+  return 0;
+#endif
+}
+
+static inline void tcp_acceptq_queue(struct sock *sk, struct open_request *req,
+                                        struct sock *child)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       req->sk = child;
+       tcp_acceptq_added(sk);
+
+       if (!tp->accept_queue_tail) {
+               tp->accept_queue = req;
+       } else {
+               tp->accept_queue_tail->dl_next = req;
+       }
+       tp->accept_queue_tail = req;
+       req->dl_next = NULL;
+#endif
+}
+
+struct tcp_listen_opt
+{
+       u8                      max_qlen_log;   /* log_2 of maximal queued SYNs */
+       int                     qlen;
+       int                     qlen_young;
+       int                     clock_hand;
+       struct open_request     *syn_table[TCP_SYNQ_HSIZE];
+};
+
+static inline void
+tcp_synq_removed(struct sock *sk, struct open_request *req)
+{
+#if 0
+       struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt;
+
+       if (--lopt->qlen == 0)
+               tcp_delete_keepalive_timer(sk);
+       if (req->retrans == 0)
+               lopt->qlen_young--;
+#endif
+}
+
+static inline void tcp_synq_added(struct sock *sk)
+{
+#if 0
+       struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt;
+
+       if (lopt->qlen++ == 0)
+               tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT);
+       lopt->qlen_young++;
+#endif
+}
+
+static inline int tcp_synq_len(struct sock *sk)
+{
+#if 0
+       return sk->tp_pinfo.af_tcp.listen_opt->qlen;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_synq_young(struct sock *sk)
+{
+#if 0
+       return sk->tp_pinfo.af_tcp.listen_opt->qlen_young;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_synq_is_full(struct sock *sk)
+{
+#if 0
+       return tcp_synq_len(sk)>>sk->tp_pinfo.af_tcp.listen_opt->max_qlen_log;
+#else
+  return 0;
+#endif
+}
+
+static inline void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req,
+                                      struct open_request **prev)
+{
+#if 0
+       write_lock(&tp->syn_wait_lock);
+       *prev = req->dl_next;
+       write_unlock(&tp->syn_wait_lock);
+#endif
+}
+
+static inline void tcp_synq_drop(struct sock *sk, struct open_request *req,
+                                    struct open_request **prev)
+{
+#if 0
+       tcp_synq_unlink(&sk->tp_pinfo.af_tcp, req, prev);
+       tcp_synq_removed(sk, req);
+       tcp_openreq_free(req);
+#endif
+}
+
+static __inline__ void tcp_openreq_init(struct open_request *req,
+                                       struct tcp_opt *tp,
+                                       struct sk_buff *skb)
+{
+#if 0
+       req->rcv_wnd = 0;               /* So that tcp_send_synack() knows! */
+       req->rcv_isn = TCP_SKB_CB(skb)->seq;
+       req->mss = tp->mss_clamp;
+       req->ts_recent = tp->saw_tstamp ? tp->rcv_tsval : 0;
+       req->tstamp_ok = tp->tstamp_ok;
+       req->sack_ok = tp->sack_ok;
+       req->snd_wscale = tp->snd_wscale;
+       req->wscale_ok = tp->wscale_ok;
+       req->acked = 0;
+       req->ecn_ok = 0;
+       req->rmt_port = skb->h.th->source;
+#endif
+}
+
+#define TCP_MEM_QUANTUM        ((int)PAGE_SIZE)
+
+static inline void tcp_free_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       sk->tp_pinfo.af_tcp.queue_shrunk = 1;
+       sk->wmem_queued -= skb->truesize;
+       sk->forward_alloc += skb->truesize;
+       __kfree_skb(skb);
+#endif
+}
+
+static inline void tcp_charge_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       sk->wmem_queued += skb->truesize;
+       sk->forward_alloc -= skb->truesize;
+#endif
+}
+
+extern void __tcp_mem_reclaim(struct sock *sk);
+extern int tcp_mem_schedule(struct sock *sk, int size, int kind);
+
+static inline void tcp_mem_reclaim(struct sock *sk)
+{
+#if 0
+       if (sk->forward_alloc >= TCP_MEM_QUANTUM)
+               __tcp_mem_reclaim(sk);
+#endif
+}
+
+static inline void tcp_enter_memory_pressure(void)
+{
+#if 0
+       if (!tcp_memory_pressure) {
+               NET_INC_STATS(TCPMemoryPressures);
+               tcp_memory_pressure = 1;
+       }
+#endif
+}
+
+static inline void tcp_moderate_sndbuf(struct sock *sk)
+{
+#if 0
+       if (!(sk->userlocks&SOCK_SNDBUF_LOCK)) {
+               sk->sndbuf = min(sk->sndbuf, sk->wmem_queued/2);
+               sk->sndbuf = max(sk->sndbuf, SOCK_MIN_SNDBUF);
+       }
+#endif
+}
+
+static inline struct sk_buff *tcp_alloc_pskb(struct sock *sk, int size, int mem, int gfp)
+{
+#if 0
+       struct sk_buff *skb = alloc_skb(size+MAX_TCP_HEADER, gfp);
+
+       if (skb) {
+               skb->truesize += mem;
+               if (sk->forward_alloc >= (int)skb->truesize ||
+                   tcp_mem_schedule(sk, skb->truesize, 0)) {
+                       skb_reserve(skb, MAX_TCP_HEADER);
+                       return skb;
+               }
+               __kfree_skb(skb);
+       } else {
+               tcp_enter_memory_pressure();
+               tcp_moderate_sndbuf(sk);
+       }
+       return NULL;
+#else
+  return NULL;
+#endif
+}
+
+static inline struct sk_buff *tcp_alloc_skb(struct sock *sk, int size, int gfp)
+{
+#if 0
+       return tcp_alloc_pskb(sk, size, 0, gfp);
+#else
+  return NULL;
+#endif
+}
+
+static inline struct page * tcp_alloc_page(struct sock *sk)
+{
+#if 0
+       if (sk->forward_alloc >= (int)PAGE_SIZE ||
+           tcp_mem_schedule(sk, PAGE_SIZE, 0)) {
+               struct page *page = alloc_pages(sk->allocation, 0);
+               if (page)
+                       return page;
+       }
+       tcp_enter_memory_pressure();
+       tcp_moderate_sndbuf(sk);
+       return NULL;
+#else
+  return NULL;
+#endif
+}
+
+static inline void tcp_writequeue_purge(struct sock *sk)
+{
+#if 0
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(&sk->write_queue)) != NULL)
+               tcp_free_skb(sk, skb);
+       tcp_mem_reclaim(sk);
+#endif
+}
+
+extern void tcp_rfree(struct sk_buff *skb);
+
+static inline void tcp_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+#if 0
+       skb->sk = sk;
+       skb->destructor = tcp_rfree;
+       atomic_add(skb->truesize, &sk->rmem_alloc);
+       sk->forward_alloc -= skb->truesize;
+#endif
+}
+
+extern void tcp_listen_wlock(void);
+
+/* - We may sleep inside this lock.
+ * - If sleeping is not required (or called from BH),
+ *   use plain read_(un)lock(&tcp_lhash_lock).
+ */
+
+static inline void tcp_listen_lock(void)
+{
+#if 0
+       /* read_lock synchronizes to candidates to writers */
+       read_lock(&tcp_lhash_lock);
+       atomic_inc(&tcp_lhash_users);
+       read_unlock(&tcp_lhash_lock);
+#endif
+}
+
+static inline void tcp_listen_unlock(void)
+{
+#if 0
+       if (atomic_dec_and_test(&tcp_lhash_users))
+               wake_up(&tcp_lhash_wait);
+#endif
+}
+
+static inline int keepalive_intvl_when(struct tcp_opt *tp)
+{
+#if 0
+       return tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl;
+#else
+  return 0;
+#endif
+}
+
+static inline int keepalive_time_when(struct tcp_opt *tp)
+{
+#if 0
+       return tp->keepalive_time ? : sysctl_tcp_keepalive_time;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_fin_time(struct tcp_opt *tp)
+{
+#if 0
+       int fin_timeout = tp->linger2 ? : sysctl_tcp_fin_timeout;
+
+       if (fin_timeout < (tp->rto<<2) - (tp->rto>>1))
+               fin_timeout = (tp->rto<<2) - (tp->rto>>1);
+
+       return fin_timeout;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_paws_check(struct tcp_opt *tp, int rst)
+{
+#if 0
+       if ((s32)(tp->rcv_tsval - tp->ts_recent) >= 0)
+               return 0;
+       if (xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_24DAYS)
+               return 0;
+
+       /* RST segments are not recommended to carry timestamp,
+          and, if they do, it is recommended to ignore PAWS because
+          "their cleanup function should take precedence over timestamps."
+          Certainly, it is mistake. It is necessary to understand the reasons
+          of this constraint to relax it: if peer reboots, clock may go
+          out-of-sync and half-open connections will not be reset.
+          Actually, the problem would be not existing if all
+          the implementations followed draft about maintaining clock
+          via reboots. Linux-2.2 DOES NOT!
+
+          However, we can relax time bounds for RST segments to MSL.
+        */
+       if (rst && xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_MSL)
+               return 0;
+       return 1;
+#else
+  return 0;
+#endif
+}
+
+#define TCP_CHECK_TIMER(sk) do { } while (0)
+
+#endif /* __TCPCORE_H */
+
+
+//
+#endif
+#endif
diff --git a/drivers/net/tcpip/include/tcpdef.h b/drivers/net/tcpip/include/tcpdef.h
new file mode 100755 (executable)
index 0000000..8005de2
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Definitions for the TCP protocol.
+ *
+ * Version:    @(#)tcp.h       1.0.2   04/28/93
+ *
+ * Author:     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_TCP_H
+#define _LINUX_TCP_H
+
+#include "linux.h"
+
+struct tcphdr {
+       __u16   source;
+       __u16   dest;
+       __u32   seq;
+       __u32   ack_seq;
+//#if defined(__LITTLE_ENDIAN_BITFIELD)
+       __u16   res1:4,
+               doff:4,
+               fin:1,
+               syn:1,
+               rst:1,
+               psh:1,
+               ack:1,
+               urg:1,
+               ece:1,
+               cwr:1;
+/*#elif defined(__BIG_ENDIAN_BITFIELD)
+       __u16   doff:4,
+               res1:4,
+               cwr:1,
+               ece:1,
+               urg:1,
+               ack:1,
+               psh:1,
+               rst:1,
+               syn:1,
+               fin:1;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif */
+       __u16   window;
+       __u16   check;
+       __u16   urg_ptr;
+};
+
+
+enum {
+  TCP_ESTABLISHED = 1,
+  TCP_SYN_SENT,
+  TCP_SYN_RECV,
+  TCP_FIN_WAIT1,
+  TCP_FIN_WAIT2,
+  TCP_TIME_WAIT,
+  TCP_CLOSE,
+  TCP_CLOSE_WAIT,
+  TCP_LAST_ACK,
+  TCP_LISTEN,
+  TCP_CLOSING,  /* now a valid state */
+
+  TCP_MAX_STATES /* Leave at the end! */
+};
+
+#define TCP_STATE_MASK 0xF
+#define TCP_ACTION_FIN (1 << 7)
+
+enum {
+  TCPF_ESTABLISHED = (1 << 1),
+  TCPF_SYN_SENT  = (1 << 2),
+  TCPF_SYN_RECV  = (1 << 3),
+  TCPF_FIN_WAIT1 = (1 << 4),
+  TCPF_FIN_WAIT2 = (1 << 5),
+  TCPF_TIME_WAIT = (1 << 6),
+  TCPF_CLOSE     = (1 << 7),
+  TCPF_CLOSE_WAIT = (1 << 8),
+  TCPF_LAST_ACK  = (1 << 9),
+  TCPF_LISTEN    = (1 << 10),
+  TCPF_CLOSING   = (1 << 11) 
+};
+
+/*
+ *     The union cast uses a gcc extension to avoid aliasing problems
+ *  (union is compatible to any of its members)
+ *  This means this part of the code is -fstrict-aliasing safe now.
+ */
+union tcp_word_hdr { 
+       struct tcphdr hdr;
+       __u32             words[5];
+}; 
+
+#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
+
+enum { 
+       TCP_FLAG_CWR = 0x00800000, // __constant_htonl(0x00800000), 
+       TCP_FLAG_ECE = 0x00400000, //__constant_htonl(0x00400000), 
+       TCP_FLAG_URG = 0x00200000, //__constant_htonl(0x00200000), 
+       TCP_FLAG_ACK = 0x00100000, //__constant_htonl(0x00100000), 
+       TCP_FLAG_PSH = 0x00080000, //__constant_htonl(0x00080000), 
+       TCP_FLAG_RST = 0x00040000, //__constant_htonl(0x00040000), 
+       TCP_FLAG_SYN = 0x00020000, //__constant_htonl(0x00020000), 
+       TCP_FLAG_FIN = 0x00010000, //__constant_htonl(0x00010000),
+       TCP_RESERVED_BITS = 0x0F000000, //__constant_htonl(0x0F000000),
+       TCP_DATA_OFFSET = 0xF0000000, //__constant_htonl(0xF0000000)
+}; 
+
+/* TCP socket options */
+#define TCP_NODELAY            1       /* Turn off Nagle's algorithm. */
+#define TCP_MAXSEG             2       /* Limit MSS */
+#define TCP_CORK               3       /* Never send partially complete segments */
+#define TCP_KEEPIDLE           4       /* Start keeplives after this period */
+#define TCP_KEEPINTVL          5       /* Interval between keepalives */
+#define TCP_KEEPCNT            6       /* Number of keepalives before death */
+#define TCP_SYNCNT             7       /* Number of SYN retransmits */
+#define TCP_LINGER2            8       /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT       9       /* Wake up listener only when data arrive */
+#define TCP_WINDOW_CLAMP       10      /* Bound advertised window */
+#define TCP_INFO               11      /* Information about this connection. */
+#define TCP_QUICKACK           12      /* Block/reenable quick acks */
+
+#define TCPI_OPT_TIMESTAMPS    1
+#define TCPI_OPT_SACK          2
+#define TCPI_OPT_WSCALE                4
+#define TCPI_OPT_ECN           8
+
+enum tcp_ca_state
+{
+       TCP_CA_Open = 0,
+#define TCPF_CA_Open   (1<<TCP_CA_Open)
+       TCP_CA_Disorder = 1,
+#define TCPF_CA_Disorder (1<<TCP_CA_Disorder)
+       TCP_CA_CWR = 2,
+#define TCPF_CA_CWR    (1<<TCP_CA_CWR)
+       TCP_CA_Recovery = 3,
+#define TCPF_CA_Recovery (1<<TCP_CA_Recovery)
+       TCP_CA_Loss = 4
+#define TCPF_CA_Loss   (1<<TCP_CA_Loss)
+};
+
+struct tcp_info
+{
+       __u8    tcpi_state;
+       __u8    tcpi_ca_state;
+       __u8    tcpi_retransmits;
+       __u8    tcpi_probes;
+       __u8    tcpi_backoff;
+       __u8    tcpi_options;
+       __u8    tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+
+       __u32   tcpi_rto;
+       __u32   tcpi_ato;
+       __u32   tcpi_snd_mss;
+       __u32   tcpi_rcv_mss;
+
+       __u32   tcpi_unacked;
+       __u32   tcpi_sacked;
+       __u32   tcpi_lost;
+       __u32   tcpi_retrans;
+       __u32   tcpi_fackets;
+
+       /* Times. */
+       __u32   tcpi_last_data_sent;
+       __u32   tcpi_last_ack_sent;     /* Not remembered, sorry. */
+       __u32   tcpi_last_data_recv;
+       __u32   tcpi_last_ack_recv;
+
+       /* Metrics. */
+       __u32   tcpi_pmtu;
+       __u32   tcpi_rcv_ssthresh;
+       __u32   tcpi_rtt;
+       __u32   tcpi_rttvar;
+       __u32   tcpi_snd_ssthresh;
+       __u32   tcpi_snd_cwnd;
+       __u32   tcpi_advmss;
+       __u32   tcpi_reordering;
+};
+
+#endif /* _LINUX_TCP_H */
diff --git a/drivers/net/tcpip/network/.cvsignore b/drivers/net/tcpip/network/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/tcpip/.cvsignore b/drivers/net/tcpip/tcpip/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/transport/datagram/.cvsignore b/drivers/net/tcpip/transport/datagram/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/transport/rawip/.cvsignore b/drivers/net/tcpip/transport/rawip/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/transport/tcp/.cvsignore b/drivers/net/tcpip/transport/tcp/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tcpip/transport/tcp/tcp_input.c b/drivers/net/tcpip/transport/tcp/tcp_input.c
new file mode 100755 (executable)
index 0000000..484d558
--- /dev/null
@@ -0,0 +1,4184 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        transport/tcp/tcp_input.c
+ * PURPOSE:     Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version:    $Id$
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *             Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *             Florian La Roche, <flla@stud.uni-sb.de>
+ *             Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ *             Linus Torvalds, <torvalds@cs.helsinki.fi>
+ *             Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *             Matthew Dillon, <dillon@apollo.west.oic.com>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes:
+ *             Pedro Roque     :       Fast Retransmit/Recovery.
+ *                                     Two receive queues.
+ *                                     Retransmit queue handled by TCP.
+ *                                     Better retransmit timer handling.
+ *                                     New congestion avoidance.
+ *                                     Header prediction.
+ *                                     Variable renaming.
+ *
+ *             Eric            :       Fast Retransmit.
+ *             Randy Scott     :       MSS option defines.
+ *             Eric Schenk     :       Fixes to slow start algorithm.
+ *             Eric Schenk     :       Yet another double ACK bug.
+ *             Eric Schenk     :       Delayed ACK bug fixes.
+ *             Eric Schenk     :       Floyd style fast retrans war avoidance.
+ *             David S. Miller :       Don't allow zero congestion window.
+ *             Eric Schenk     :       Fix retransmitter so that it sends
+ *                                     next packet on ack of previous packet.
+ *             Andi Kleen      :       Moved open_request checking here
+ *                                     and process RSTs for open_requests.
+ *             Andi Kleen      :       Better prune_queue, and other fixes.
+ *             Andrey Savochkin:       Fix RTT measurements in the presnce of
+ *                                     timestamps.
+ *             Andrey Savochkin:       Check sequence numbers correctly when
+ *                                     removing SACKs due to in sequence incoming
+ *                                     data segments.
+ *             Andi Kleen:             Make sure we never ack data there is not
+ *                                     enough room for. Also make this condition
+ *                                     a fatal error if it might still happen.
+ *             Andi Kleen:             Add tcp_measure_rcv_mss to make 
+ *                                     connections with MSS<min(MTU,ann. MSS)
+ *                                     work without delayed acks. 
+ *             Andi Kleen:             Process packets with PSH set in the
+ *                                     fast path.
+ *             J Hadi Salim:           ECN support
+ *             Andrei Gurtov,
+ *             Pasi Sarolahti,
+ *             Panu Kuhlberg:          Experimental audit of TCP (re)transmission
+ *                                     engine. Lots of bugs are found.
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <net/tcp.h>
+#include <net/inet_common.h>
+#include <linux/ipsec.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_timestamps = 1;
+int sysctl_tcp_window_scaling = 1;
+int sysctl_tcp_sack = 1;
+int sysctl_tcp_fack = 1;
+int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
+#ifdef CONFIG_INET_ECN
+int sysctl_tcp_ecn = 1;
+#else
+int sysctl_tcp_ecn = 0;
+#endif
+int sysctl_tcp_dsack = 1;
+int sysctl_tcp_app_win = 31;
+int sysctl_tcp_adv_win_scale = 2;
+
+int sysctl_tcp_stdurg = 0;
+int sysctl_tcp_rfc1337 = 0;
+//int sysctl_tcp_max_orphans = NR_FILE;
+
+#define FLAG_DATA              0x01 /* Incoming frame contained data.          */
+#define FLAG_WIN_UPDATE                0x02 /* Incoming ACK was a window update.       */
+#define FLAG_DATA_ACKED                0x04 /* This ACK acknowledged new data.         */
+#define FLAG_RETRANS_DATA_ACKED        0x08 /* "" "" some of which was retransmitted.  */
+#define FLAG_SYN_ACKED         0x10 /* This ACK acknowledged SYN.              */
+#define FLAG_DATA_SACKED       0x20 /* New SACK.                               */
+#define FLAG_ECE               0x40 /* ECE in this ACK                         */
+#define FLAG_DATA_LOST         0x80 /* SACK detected data lossage.             */
+#define FLAG_SLOWPATH          0x100 /* Do not skip RFC checks for window update.*/
+
+#define FLAG_ACKED             (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
+#define FLAG_NOT_DUP           (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
+#define FLAG_CA_ALERT          (FLAG_DATA_SACKED|FLAG_ECE)
+#define FLAG_FORWARD_PROGRESS  (FLAG_ACKED|FLAG_DATA_SACKED)
+
+#define IsReno(tp) ((tp)->sack_ok == 0)
+#define IsFack(tp) ((tp)->sack_ok & 2)
+#define IsDSack(tp) ((tp)->sack_ok & 4)
+
+#define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH)
+
+/* Adapt the MSS value used to make delayed ack decision to the 
+ * real world.
+ */ 
+static __inline__ void tcp_measure_rcv_mss(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       unsigned int len, lss;
+
+       lss = tp->ack.last_seg_size; 
+       tp->ack.last_seg_size = 0; 
+
+       /* skb->len may jitter because of SACKs, even if peer
+        * sends good full-sized frames.
+        */
+       len = skb->len;
+       if (len >= tp->ack.rcv_mss) {
+               tp->ack.rcv_mss = len;
+       } else {
+               /* Otherwise, we make more careful check taking into account,
+                * that SACKs block is variable.
+                *
+                * "len" is invariant segment length, including TCP header.
+                */
+               len += skb->data - skb->h.raw;
+               if (len >= TCP_MIN_RCVMSS + sizeof(struct tcphdr) ||
+                   /* If PSH is not set, packet should be
+                    * full sized, provided peer TCP is not badly broken.
+                    * This observation (if it is correct 8)) allows
+                    * to handle super-low mtu links fairly.
+                    */
+                   (len >= TCP_MIN_MSS + sizeof(struct tcphdr) &&
+                    !(tcp_flag_word(skb->h.th)&TCP_REMNANT))) {
+                       /* Subtract also invariant (if peer is RFC compliant),
+                        * tcp header plus fixed timestamp option length.
+                        * Resulting "len" is MSS free of SACK jitter.
+                        */
+                       len -= tp->tcp_header_len;
+                       tp->ack.last_seg_size = len;
+                       if (len == lss) {
+                               tp->ack.rcv_mss = len;
+                               return;
+                       }
+               }
+               tp->ack.pending |= TCP_ACK_PUSHED;
+       }
+#endif
+}
+
+static void tcp_incr_quickack(struct tcp_opt *tp)
+{
+#if 0
+       unsigned quickacks = tp->rcv_wnd/(2*tp->ack.rcv_mss);
+
+       if (quickacks==0)
+               quickacks=2;
+       if (quickacks > tp->ack.quick)
+               tp->ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
+#endif
+}
+
+void tcp_enter_quickack_mode(struct tcp_opt *tp)
+{
+#if 0
+       tcp_incr_quickack(tp);
+       tp->ack.pingpong = 0;
+       tp->ack.ato = TCP_ATO_MIN;
+#endif
+}
+
+/* Send ACKs quickly, if "quick" count is not exhausted
+ * and the session is not interactive.
+ */
+
+static __inline__ int tcp_in_quickack_mode(struct tcp_opt *tp)
+{
+#if 0
+       return (tp->ack.quick && !tp->ack.pingpong);
+#else
+  return 0;
+#endif
+}
+
+/* Buffer size and advertised window tuning.
+ *
+ * 1. Tuning sk->sndbuf, when connection enters established state.
+ */
+
+static void tcp_fixup_sndbuf(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int sndmem = tp->mss_clamp+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+
+       if (sk->sndbuf < 3*sndmem)
+               sk->sndbuf = min(3*sndmem, sysctl_tcp_wmem[2]);
+#endif
+}
+
+/* 2. Tuning advertised window (window_clamp, rcv_ssthresh)
+ *
+ * All tcp_full_space() is split to two parts: "network" buffer, allocated
+ * forward and advertised in receiver window (tp->rcv_wnd) and
+ * "application buffer", required to isolate scheduling/application
+ * latencies from network.
+ * window_clamp is maximal advertised window. It can be less than
+ * tcp_full_space(), in this case tcp_full_space() - window_clamp
+ * is reserved for "application" buffer. The less window_clamp is
+ * the smoother our behaviour from viewpoint of network, but the lower
+ * throughput and the higher sensitivity of the connection to losses. 8)
+ *
+ * rcv_ssthresh is more strict window_clamp used at "slow start"
+ * phase to predict further behaviour of this connection.
+ * It is used for two goals:
+ * - to enforce header prediction at sender, even when application
+ *   requires some significant "application buffer". It is check #1.
+ * - to prevent pruning of receive queue because of misprediction
+ *   of receiver window. Check #2.
+ *
+ * The scheme does not work when sender sends good segments opening
+ * window and then starts to feed us spagetti. But it should work
+ * in common situations. Otherwise, we have to rely on queue collapsing.
+ */
+
+/* Slow part of check#2. */
+static int
+__tcp_grow_window(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       /* Optimize this! */
+       int truesize = tcp_win_from_space(skb->truesize)/2;
+       int window = tcp_full_space(sk)/2;
+
+       while (tp->rcv_ssthresh <= window) {
+               if (truesize <= skb->len)
+                       return 2*tp->ack.rcv_mss;
+
+               truesize >>= 1;
+               window >>= 1;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void
+tcp_grow_window(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       /* Check #1 */
+       if (tp->rcv_ssthresh < tp->window_clamp &&
+           (int)tp->rcv_ssthresh < tcp_space(sk) &&
+           !tcp_memory_pressure) {
+               int incr;
+
+               /* Check #2. Increase window, if skb with such overhead
+                * will fit to rcvbuf in future.
+                */
+               if (tcp_win_from_space(skb->truesize) <= skb->len)
+                       incr = 2*tp->advmss;
+               else
+                       incr = __tcp_grow_window(sk, tp, skb);
+
+               if (incr) {
+                       tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr, tp->window_clamp);
+                       tp->ack.quick |= 1;
+               }
+       }
+#endif
+}
+
+/* 3. Tuning rcvbuf, when connection enters established state. */
+
+static void tcp_fixup_rcvbuf(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int rcvmem = tp->advmss+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+
+       /* Try to select rcvbuf so that 4 mss-sized segments
+        * will fit to window and correspoding skbs will fit to our rcvbuf.
+        * (was 3; 4 is minimum to allow fast retransmit to work.)
+        */
+       while (tcp_win_from_space(rcvmem) < tp->advmss)
+               rcvmem += 128;
+       if (sk->rcvbuf < 4*rcvmem)
+               sk->rcvbuf = min(4*rcvmem, sysctl_tcp_rmem[2]);
+#endif
+}
+
+/* 4. Try to fixup all. It is made iimediately after connection enters
+ *    established state.
+ */
+static void tcp_init_buffer_space(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int maxwin;
+
+       if (!(sk->userlocks&SOCK_RCVBUF_LOCK))
+               tcp_fixup_rcvbuf(sk);
+       if (!(sk->userlocks&SOCK_SNDBUF_LOCK))
+               tcp_fixup_sndbuf(sk);
+
+       maxwin = tcp_full_space(sk);
+
+       if (tp->window_clamp >= maxwin) {
+               tp->window_clamp = maxwin;
+
+               if (sysctl_tcp_app_win && maxwin>4*tp->advmss)
+                       tp->window_clamp = max(maxwin-(maxwin>>sysctl_tcp_app_win), 4*tp->advmss);
+       }
+
+       /* Force reservation of one segment. */
+       if (sysctl_tcp_app_win &&
+           tp->window_clamp > 2*tp->advmss &&
+           tp->window_clamp + tp->advmss > maxwin)
+               tp->window_clamp = max(2*tp->advmss, maxwin-tp->advmss);
+
+       tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* 5. Recalculate window clamp after socket hit its memory bounds. */
+static void tcp_clamp_window(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       struct sk_buff *skb;
+       unsigned int app_win = tp->rcv_nxt - tp->copied_seq;
+       int ofo_win = 0;
+
+       tp->ack.quick = 0;
+
+       skb_queue_walk(&tp->out_of_order_queue, skb) {
+               ofo_win += skb->len;
+       }
+
+       /* If overcommit is due to out of order segments,
+        * do not clamp window. Try to expand rcvbuf instead.
+        */
+       if (ofo_win) {
+               if (sk->rcvbuf < sysctl_tcp_rmem[2] &&
+                   !(sk->userlocks&SOCK_RCVBUF_LOCK) &&
+                   !tcp_memory_pressure &&
+                   atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
+                       sk->rcvbuf = min(atomic_read(&sk->rmem_alloc), sysctl_tcp_rmem[2]);
+       }
+       if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) {
+               app_win += ofo_win;
+               if (atomic_read(&sk->rmem_alloc) >= 2*sk->rcvbuf)
+                       app_win >>= 1;
+               if (app_win > tp->ack.rcv_mss)
+                       app_win -= tp->ack.rcv_mss;
+               app_win = max(app_win, 2U*tp->advmss);
+
+               if (!ofo_win)
+                       tp->window_clamp = min(tp->window_clamp, app_win);
+               tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
+       }
+#endif
+}
+
+/* There is something which you must keep in mind when you analyze the
+ * behavior of the tp->ato delayed ack timeout interval.  When a
+ * connection starts up, we want to ack as quickly as possible.  The
+ * problem is that "good" TCP's do slow start at the beginning of data
+ * transmission.  The means that until we send the first few ACK's the
+ * sender will sit on his end and only queue most of his data, because
+ * he can only send snd_cwnd unacked packets at any given time.  For
+ * each ACK we send, he increments snd_cwnd and transmits more of his
+ * queue.  -DaveM
+ */
+static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       u32 now;
+
+       tcp_schedule_ack(tp);
+
+       tcp_measure_rcv_mss(tp, skb);
+
+       now = tcp_time_stamp;
+
+       if (!tp->ack.ato) {
+               /* The _first_ data packet received, initialize
+                * delayed ACK engine.
+                */
+               tcp_incr_quickack(tp);
+               tp->ack.ato = TCP_ATO_MIN;
+       } else {
+               int m = now - tp->ack.lrcvtime;
+
+               if (m <= TCP_ATO_MIN/2) {
+                       /* The fastest case is the first. */
+                       tp->ack.ato = (tp->ack.ato>>1) + TCP_ATO_MIN/2;
+               } else if (m < tp->ack.ato) {
+                       tp->ack.ato = (tp->ack.ato>>1) + m;
+                       if (tp->ack.ato > tp->rto)
+                               tp->ack.ato = tp->rto;
+               } else if (m > tp->rto) {
+                       /* Too long gap. Apparently sender falled to
+                        * restart window, so that we send ACKs quickly.
+                        */
+                       tcp_incr_quickack(tp);
+                       tcp_mem_reclaim(sk);
+               }
+       }
+       tp->ack.lrcvtime = now;
+
+       TCP_ECN_check_ce(tp, skb);
+
+       if (skb->len >= 128)
+               tcp_grow_window(sk, tp, skb);
+#endif
+}
+
+/* Called to compute a smoothed rtt estimate. The data fed to this
+ * routine either comes from timestamps, or from segments that were
+ * known _not_ to have been retransmitted [see Karn/Partridge
+ * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
+ * piece by Van Jacobson.
+ * NOTE: the next three routines used to be one big routine.
+ * To save cycles in the RFC 1323 implementation it was better to break
+ * it up into three procedures. -- erics
+ */
+static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
+{
+#if 0
+       long m = mrtt; /* RTT */
+
+       /*      The following amusing code comes from Jacobson's
+        *      article in SIGCOMM '88.  Note that rtt and mdev
+        *      are scaled versions of rtt and mean deviation.
+        *      This is designed to be as fast as possible 
+        *      m stands for "measurement".
+        *
+        *      On a 1990 paper the rto value is changed to:
+        *      RTO = rtt + 4 * mdev
+        *
+        * Funny. This algorithm seems to be very broken.
+        * These formulae increase RTO, when it should be decreased, increase
+        * too slowly, when it should be incresed fastly, decrease too fastly
+        * etc. I guess in BSD RTO takes ONE value, so that it is absolutely
+        * does not matter how to _calculate_ it. Seems, it was trap
+        * that VJ failed to avoid. 8)
+        */
+       if(m == 0)
+               m = 1;
+       if (tp->srtt != 0) {
+               m -= (tp->srtt >> 3);   /* m is now error in rtt est */
+               tp->srtt += m;          /* rtt = 7/8 rtt + 1/8 new */
+               if (m < 0) {
+                       m = -m;         /* m is now abs(error) */
+                       m -= (tp->mdev >> 2);   /* similar update on mdev */
+                       /* This is similar to one of Eifel findings.
+                        * Eifel blocks mdev updates when rtt decreases.
+                        * This solution is a bit different: we use finer gain
+                        * for mdev in this case (alpha*beta).
+                        * Like Eifel it also prevents growth of rto,
+                        * but also it limits too fast rto decreases,
+                        * happening in pure Eifel.
+                        */
+                       if (m > 0)
+                               m >>= 3;
+               } else {
+                       m -= (tp->mdev >> 2);   /* similar update on mdev */
+               }
+               tp->mdev += m;          /* mdev = 3/4 mdev + 1/4 new */
+               if (tp->mdev > tp->mdev_max) {
+                       tp->mdev_max = tp->mdev;
+                       if (tp->mdev_max > tp->rttvar)
+                               tp->rttvar = tp->mdev_max;
+               }
+               if (after(tp->snd_una, tp->rtt_seq)) {
+                       if (tp->mdev_max < tp->rttvar)
+                               tp->rttvar -= (tp->rttvar-tp->mdev_max)>>2;
+                       tp->rtt_seq = tp->snd_nxt;
+                       tp->mdev_max = TCP_RTO_MIN;
+               }
+       } else {
+               /* no previous measure. */
+               tp->srtt = m<<3;        /* take the measured time to be rtt */
+               tp->mdev = m<<1;        /* make sure rto = 3*rtt */
+               tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
+               tp->rtt_seq = tp->snd_nxt;
+       }
+#endif
+}
+
+/* Calculate rto without backoff.  This is the second half of Van Jacobson's
+ * routine referred to above.
+ */
+static __inline__ void tcp_set_rto(struct tcp_opt *tp)
+{
+#if 0
+       /* Old crap is replaced with new one. 8)
+        *
+        * More seriously:
+        * 1. If rtt variance happened to be less 50msec, it is hallucination.
+        *    It cannot be less due to utterly erratic ACK generation made
+        *    at least by solaris and freebsd. "Erratic ACKs" has _nothing_
+        *    to do with delayed acks, because at cwnd>2 true delack timeout
+        *    is invisible. Actually, Linux-2.4 also generates erratic
+        *    ACKs in some curcumstances.
+        */
+       tp->rto = (tp->srtt >> 3) + tp->rttvar;
+
+       /* 2. Fixups made earlier cannot be right.
+        *    If we do not estimate RTO correctly without them,
+        *    all the algo is pure shit and should be replaced
+        *    with correct one. It is exaclty, which we pretend to do.
+        */
+#endif
+}
+
+/* NOTE: clamping at TCP_RTO_MIN is not required, current algo
+ * guarantees that rto is higher.
+ */
+static __inline__ void tcp_bound_rto(struct tcp_opt *tp)
+{
+#if 0
+       if (tp->rto > TCP_RTO_MAX)
+               tp->rto = TCP_RTO_MAX;
+#endif
+}
+
+/* Save metrics learned by this TCP session.
+   This function is called only, when TCP finishes successfully
+   i.e. when it enters TIME-WAIT or goes from LAST-ACK to CLOSE.
+ */
+void tcp_update_metrics(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct dst_entry *dst = __sk_dst_get(sk);
+
+       dst_confirm(dst);
+
+       if (dst && (dst->flags&DST_HOST)) {
+               int m;
+
+               if (tp->backoff || !tp->srtt) {
+                       /* This session failed to estimate rtt. Why?
+                        * Probably, no packets returned in time.
+                        * Reset our results.
+                        */
+                       if (!(dst->mxlock&(1<<RTAX_RTT)))
+                               dst->rtt = 0;
+                       return;
+               }
+
+               m = dst->rtt - tp->srtt;
+
+               /* If newly calculated rtt larger than stored one,
+                * store new one. Otherwise, use EWMA. Remember,
+                * rtt overestimation is always better than underestimation.
+                */
+               if (!(dst->mxlock&(1<<RTAX_RTT))) {
+                       if (m <= 0)
+                               dst->rtt = tp->srtt;
+                       else
+                               dst->rtt -= (m>>3);
+               }
+
+               if (!(dst->mxlock&(1<<RTAX_RTTVAR))) {
+                       if (m < 0)
+                               m = -m;
+
+                       /* Scale deviation to rttvar fixed point */
+                       m >>= 1;
+                       if (m < tp->mdev)
+                               m = tp->mdev;
+
+                       if (m >= dst->rttvar)
+                               dst->rttvar = m;
+                       else
+                               dst->rttvar -= (dst->rttvar - m)>>2;
+               }
+
+               if (tp->snd_ssthresh >= 0xFFFF) {
+                       /* Slow start still did not finish. */
+                       if (dst->ssthresh &&
+                           !(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
+                           (tp->snd_cwnd>>1) > dst->ssthresh)
+                               dst->ssthresh = (tp->snd_cwnd>>1);
+                       if (!(dst->mxlock&(1<<RTAX_CWND)) &&
+                           tp->snd_cwnd > dst->cwnd)
+                               dst->cwnd = tp->snd_cwnd;
+               } else if (tp->snd_cwnd > tp->snd_ssthresh &&
+                          tp->ca_state == TCP_CA_Open) {
+                       /* Cong. avoidance phase, cwnd is reliable. */
+                       if (!(dst->mxlock&(1<<RTAX_SSTHRESH)))
+                               dst->ssthresh = max(tp->snd_cwnd>>1, tp->snd_ssthresh);
+                       if (!(dst->mxlock&(1<<RTAX_CWND)))
+                               dst->cwnd = (dst->cwnd + tp->snd_cwnd)>>1;
+               } else {
+                       /* Else slow start did not finish, cwnd is non-sense,
+                          ssthresh may be also invalid.
+                        */
+                       if (!(dst->mxlock&(1<<RTAX_CWND)))
+                               dst->cwnd = (dst->cwnd + tp->snd_ssthresh)>>1;
+                       if (dst->ssthresh &&
+                           !(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
+                           tp->snd_ssthresh > dst->ssthresh)
+                               dst->ssthresh = tp->snd_ssthresh;
+               }
+
+               if (!(dst->mxlock&(1<<RTAX_REORDERING))) {
+                       if (dst->reordering < tp->reordering &&
+                           tp->reordering != sysctl_tcp_reordering)
+                               dst->reordering = tp->reordering;
+               }
+       }
+#endif
+}
+
+/* Increase initial CWND conservatively: if estimated
+ * RTT is low enough (<20msec) or if we have some preset ssthresh.
+ *
+ * Numbers are taken from RFC2414.
+ */
+__u32 tcp_init_cwnd(struct tcp_opt *tp)
+{
+#if 0
+       __u32 cwnd;
+
+       if (tp->mss_cache > 1460)
+               return 2;
+
+       cwnd = (tp->mss_cache > 1095) ? 3 : 4;
+
+       if (!tp->srtt || (tp->snd_ssthresh >= 0xFFFF && tp->srtt > ((HZ/50)<<3)))
+               cwnd = 2;
+       else if (cwnd > tp->snd_ssthresh)
+               cwnd = tp->snd_ssthresh;
+
+       return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
+#else
+  return 0;
+#endif
+}
+
+/* Initialize metrics on socket. */
+
+static void tcp_init_metrics(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct dst_entry *dst = __sk_dst_get(sk);
+
+       if (dst == NULL)
+               goto reset;
+
+       dst_confirm(dst);
+
+       if (dst->mxlock&(1<<RTAX_CWND))
+               tp->snd_cwnd_clamp = dst->cwnd;
+       if (dst->ssthresh) {
+               tp->snd_ssthresh = dst->ssthresh;
+               if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
+                       tp->snd_ssthresh = tp->snd_cwnd_clamp;
+       }
+       if (dst->reordering && tp->reordering != dst->reordering) {
+               tp->sack_ok &= ~2;
+               tp->reordering = dst->reordering;
+       }
+
+       if (dst->rtt == 0)
+               goto reset;
+
+       if (!tp->srtt && dst->rtt < (TCP_TIMEOUT_INIT<<3))
+               goto reset;
+
+       /* Initial rtt is determined from SYN,SYN-ACK.
+        * The segment is small and rtt may appear much
+        * less than real one. Use per-dst memory
+        * to make it more realistic.
+        *
+        * A bit of theory. RTT is time passed after "normal" sized packet
+        * is sent until it is ACKed. In normal curcumstances sending small
+        * packets force peer to delay ACKs and calculation is correct too.
+        * The algorithm is adaptive and, provided we follow specs, it
+        * NEVER underestimate RTT. BUT! If peer tries to make some clever
+        * tricks sort of "quick acks" for time long enough to decrease RTT
+        * to low value, and then abruptly stops to do it and starts to delay
+        * ACKs, wait for troubles.
+        */
+       if (dst->rtt > tp->srtt)
+               tp->srtt = dst->rtt;
+       if (dst->rttvar > tp->mdev) {
+               tp->mdev = dst->rttvar;
+               tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
+       }
+       tcp_set_rto(tp);
+       tcp_bound_rto(tp);
+       if (tp->rto < TCP_TIMEOUT_INIT && !tp->saw_tstamp)
+               goto reset;
+       tp->snd_cwnd = tcp_init_cwnd(tp);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+       return;
+
+reset:
+       /* Play conservative. If timestamps are not
+        * supported, TCP will fail to recalculate correct
+        * rtt, if initial rto is too small. FORGET ALL AND RESET!
+        */
+       if (!tp->saw_tstamp && tp->srtt) {
+               tp->srtt = 0;
+               tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
+               tp->rto = TCP_TIMEOUT_INIT;
+       }
+#endif
+}
+
+static void tcp_update_reordering(struct tcp_opt *tp, int metric, int ts)
+{
+#if 0
+       if (metric > tp->reordering) {
+               tp->reordering = min(TCP_MAX_REORDERING, metric);
+
+               /* This exciting event is worth to be remembered. 8) */
+               if (ts)
+                       NET_INC_STATS_BH(TCPTSReorder);
+               else if (IsReno(tp))
+                       NET_INC_STATS_BH(TCPRenoReorder);
+               else if (IsFack(tp))
+                       NET_INC_STATS_BH(TCPFACKReorder);
+               else
+                       NET_INC_STATS_BH(TCPSACKReorder);
+#if FASTRETRANS_DEBUG > 1
+               printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n",
+                      tp->sack_ok, tp->ca_state,
+                      tp->reordering, tp->fackets_out, tp->sacked_out,
+                      tp->undo_marker ? tp->undo_retrans : 0);
+#endif
+               /* Disable FACK yet. */
+               tp->sack_ok &= ~2;
+       }
+#endif
+}
+
+/* This procedure tags the retransmission queue when SACKs arrive.
+ *
+ * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L).
+ * Packets in queue with these bits set are counted in variables
+ * sacked_out, retrans_out and lost_out, correspondingly.
+ *
+ * Valid combinations are:
+ * Tag  InFlight       Description
+ * 0   1               - orig segment is in flight.
+ * S   0               - nothing flies, orig reached receiver.
+ * L   0               - nothing flies, orig lost by net.
+ * R   2               - both orig and retransmit are in flight.
+ * L|R 1               - orig is lost, retransmit is in flight.
+ * S|R  1              - orig reached receiver, retrans is still in flight.
+ * (L|S|R is logically valid, it could occur when L|R is sacked,
+ *  but it is equivalent to plain S and code short-curcuits it to S.
+ *  L|S is logically invalid, it would mean -1 packet in flight 8))
+ *
+ * These 6 states form finite state machine, controlled by the following events:
+ * 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())
+ * 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())
+ * 3. Loss detection event of one of three flavors:
+ *     A. Scoreboard estimator decided the packet is lost.
+ *        A'. Reno "three dupacks" marks head of queue lost.
+ *        A''. Its FACK modfication, head until snd.fack is lost.
+ *     B. SACK arrives sacking data transmitted after never retransmitted
+ *        hole was sent out.
+ *     C. SACK arrives sacking SND.NXT at the moment, when the
+ *        segment was retransmitted.
+ * 4. D-SACK added new rule: D-SACK changes any tag to S.
+ *
+ * It is pleasant to note, that state diagram turns out to be commutative,
+ * so that we are allowed not to be bothered by order of our actions,
+ * when multiple events arrive simultaneously. (see the function below).
+ *
+ * Reordering detection.
+ * --------------------
+ * Reordering metric is maximal distance, which a packet can be displaced
+ * in packet stream. With SACKs we can estimate it:
+ *
+ * 1. SACK fills old hole and the corresponding segment was not
+ *    ever retransmitted -> reordering. Alas, we cannot use it
+ *    when segment was retransmitted.
+ * 2. The last flaw is solved with D-SACK. D-SACK arrives
+ *    for retransmitted and already SACKed segment -> reordering..
+ * Both of these heuristics are not used in Loss state, when we cannot
+ * account for retransmits accurately.
+ */
+static int
+tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
+       struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
+       int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
+       int reord = tp->packets_out;
+       int prior_fackets;
+       u32 lost_retrans = 0;
+       int flag = 0;
+       int i;
+
+       if (!tp->sacked_out)
+               tp->fackets_out = 0;
+       prior_fackets = tp->fackets_out;
+
+       for (i=0; i<num_sacks; i++, sp++) {
+               struct sk_buff *skb;
+               __u32 start_seq = ntohl(sp->start_seq);
+               __u32 end_seq = ntohl(sp->end_seq);
+               int fack_count = 0;
+               int dup_sack = 0;
+
+               /* Check for D-SACK. */
+               if (i == 0) {
+                       u32 ack = TCP_SKB_CB(ack_skb)->ack_seq;
+
+                       if (before(start_seq, ack)) {
+                               dup_sack = 1;
+                               tp->sack_ok |= 4;
+                               NET_INC_STATS_BH(TCPDSACKRecv);
+                       } else if (num_sacks > 1 &&
+                                  !after(end_seq, ntohl(sp[1].end_seq)) &&
+                                  !before(start_seq, ntohl(sp[1].start_seq))) {
+                               dup_sack = 1;
+                               tp->sack_ok |= 4;
+                               NET_INC_STATS_BH(TCPDSACKOfoRecv);
+                       }
+
+                       /* D-SACK for already forgotten data...
+                        * Do dumb counting. */
+                       if (dup_sack &&
+                           !after(end_seq, prior_snd_una) &&
+                           after(end_seq, tp->undo_marker))
+                               tp->undo_retrans--;
+
+                       /* Eliminate too old ACKs, but take into
+                        * account more or less fresh ones, they can
+                        * contain valid SACK info.
+                        */
+                       if (before(ack, prior_snd_una-tp->max_window))
+                               return 0;
+               }
+
+               /* Event "B" in the comment above. */
+               if (after(end_seq, tp->high_seq))
+                       flag |= FLAG_DATA_LOST;
+
+               for_retrans_queue(skb, sk, tp) {
+                       u8 sacked = TCP_SKB_CB(skb)->sacked;
+                       int in_sack;
+
+                       /* The retransmission queue is always in order, so
+                        * we can short-circuit the walk early.
+                        */
+                       if(!before(TCP_SKB_CB(skb)->seq, end_seq))
+                               break;
+
+                       fack_count++;
+
+                       in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
+                               !before(end_seq, TCP_SKB_CB(skb)->end_seq);
+
+                       /* Account D-SACK for retransmitted packet. */
+                       if ((dup_sack && in_sack) &&
+                           (sacked & TCPCB_RETRANS) &&
+                           after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
+                               tp->undo_retrans--;
+
+                       /* The frame is ACKed. */
+                       if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) {
+                               if (sacked&TCPCB_RETRANS) {
+                                       if ((dup_sack && in_sack) &&
+                                           (sacked&TCPCB_SACKED_ACKED))
+                                               reord = min(fack_count, reord);
+                               } else {
+                                       /* If it was in a hole, we detected reordering. */
+                                       if (fack_count < prior_fackets &&
+                                           !(sacked&TCPCB_SACKED_ACKED))
+                                               reord = min(fack_count, reord);
+                               }
+
+                               /* Nothing to do; acked frame is about to be dropped. */
+                               continue;
+                       }
+
+                       if ((sacked&TCPCB_SACKED_RETRANS) &&
+                           after(end_seq, TCP_SKB_CB(skb)->ack_seq) &&
+                           (!lost_retrans || after(end_seq, lost_retrans)))
+                               lost_retrans = end_seq;
+
+                       if (!in_sack)
+                               continue;
+
+                       if (!(sacked&TCPCB_SACKED_ACKED)) {
+                               if (sacked & TCPCB_SACKED_RETRANS) {
+                                       /* If the segment is not tagged as lost,
+                                        * we do not clear RETRANS, believing
+                                        * that retransmission is still in flight.
+                                        */
+                                       if (sacked & TCPCB_LOST) {
+                                               TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
+                                               tp->lost_out--;
+                                               tp->retrans_out--;
+                                       }
+                               } else {
+                                       /* New sack for not retransmitted frame,
+                                        * which was in hole. It is reordering.
+                                        */
+                                       if (!(sacked & TCPCB_RETRANS) &&
+                                           fack_count < prior_fackets)
+                                               reord = min(fack_count, reord);
+
+                                       if (sacked & TCPCB_LOST) {
+                                               TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
+                                               tp->lost_out--;
+                                       }
+                               }
+
+                               TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
+                               flag |= FLAG_DATA_SACKED;
+                               tp->sacked_out++;
+
+                               if (fack_count > tp->fackets_out)
+                                       tp->fackets_out = fack_count;
+                       } else {
+                               if (dup_sack && (sacked&TCPCB_RETRANS))
+                                       reord = min(fack_count, reord);
+                       }
+
+                       /* D-SACK. We can detect redundant retransmission
+                        * in S|R and plain R frames and clear it.
+                        * undo_retrans is decreased above, L|R frames
+                        * are accounted above as well.
+                        */
+                       if (dup_sack &&
+                           (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) {
+                               TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+                               tp->retrans_out--;
+                       }
+               }
+       }
+
+       /* Check for lost retransmit. This superb idea is
+        * borrowed from "ratehalving". Event "C".
+        * Later note: FACK people cheated me again 8),
+        * we have to account for reordering! Ugly,
+        * but should help.
+        */
+       if (lost_retrans && tp->ca_state == TCP_CA_Recovery) {
+               struct sk_buff *skb;
+
+               for_retrans_queue(skb, sk, tp) {
+                       if (after(TCP_SKB_CB(skb)->seq, lost_retrans))
+                               break;
+                       if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
+                               continue;
+                       if ((TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) &&
+                           after(lost_retrans, TCP_SKB_CB(skb)->ack_seq) &&
+                           (IsFack(tp) ||
+                            !before(lost_retrans, TCP_SKB_CB(skb)->ack_seq+tp->reordering*tp->mss_cache))) {
+                               TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+                               tp->retrans_out--;
+
+                               if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) {
+                                       tp->lost_out++;
+                                       TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+                                       flag |= FLAG_DATA_SACKED;
+                                       NET_INC_STATS_BH(TCPLostRetransmit);
+                               }
+                       }
+               }
+       }
+
+       tp->left_out = tp->sacked_out + tp->lost_out;
+
+       if (reord < tp->fackets_out && tp->ca_state != TCP_CA_Loss)
+               tcp_update_reordering(tp, (tp->fackets_out+1)-reord, 0);
+
+#if FASTRETRANS_DEBUG > 0
+       BUG_TRAP((int)tp->sacked_out >= 0);
+       BUG_TRAP((int)tp->lost_out >= 0);
+       BUG_TRAP((int)tp->retrans_out >= 0);
+       BUG_TRAP((int)tcp_packets_in_flight(tp) >= 0);
+#endif
+       return flag;
+#else
+  return 0;
+#endif
+}
+
+void tcp_clear_retrans(struct tcp_opt *tp)
+{
+#if 0
+       tp->left_out = 0;
+       tp->retrans_out = 0;
+
+       tp->fackets_out = 0;
+       tp->sacked_out = 0;
+       tp->lost_out = 0;
+
+       tp->undo_marker = 0;
+       tp->undo_retrans = 0;
+#endif
+}
+
+/* Enter Loss state. If "how" is not zero, forget all SACK information
+ * and reset tags completely, otherwise preserve SACKs. If receiver
+ * dropped its ofo queue, we will know this due to reneging detection.
+ */
+void tcp_enter_loss(struct sock *sk, int how)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct sk_buff *skb;
+       int cnt = 0;
+
+       /* Reduce ssthresh if it has not yet been made inside this window. */
+       if (tp->ca_state <= TCP_CA_Disorder ||
+           tp->snd_una == tp->high_seq ||
+           (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
+               tp->prior_ssthresh = tcp_current_ssthresh(tp);
+               tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+       }
+       tp->snd_cwnd = 1;
+       tp->snd_cwnd_cnt = 0;
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+
+       tcp_clear_retrans(tp);
+
+       /* Push undo marker, if it was plain RTO and nothing
+        * was retransmitted. */
+       if (!how)
+               tp->undo_marker = tp->snd_una;
+
+       for_retrans_queue(skb, sk, tp) {
+               cnt++;
+               if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
+                       tp->undo_marker = 0;
+               TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
+               if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
+                       TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
+                       TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+                       tp->lost_out++;
+               } else {
+                       tp->sacked_out++;
+                       tp->fackets_out = cnt;
+               }
+       }
+       tcp_sync_left_out(tp);
+
+       tp->reordering = min_t(unsigned int, tp->reordering, sysctl_tcp_reordering);
+       tp->ca_state = TCP_CA_Loss;
+       tp->high_seq = tp->snd_nxt;
+       TCP_ECN_queue_cwr(tp);
+#endif
+}
+
+static int tcp_check_sack_reneging(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       struct sk_buff *skb;
+
+       /* If ACK arrived pointing to a remembered SACK,
+        * it means that our remembered SACKs do not reflect
+        * real state of receiver i.e.
+        * receiver _host_ is heavily congested (or buggy).
+        * Do processing similar to RTO timeout.
+        */
+       if ((skb = skb_peek(&sk->write_queue)) != NULL &&
+           (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
+               NET_INC_STATS_BH(TCPSACKReneging);
+
+               tcp_enter_loss(sk, 1);
+               tp->retransmits++;
+               tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+               return 1;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_fackets_out(struct tcp_opt *tp)
+{
+#if 0
+       return IsReno(tp) ? tp->sacked_out+1 : tp->fackets_out;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_skb_timedout(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       return (tcp_time_stamp - TCP_SKB_CB(skb)->when > tp->rto);
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_head_timedout(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       return tp->packets_out && tcp_skb_timedout(tp, skb_peek(&sk->write_queue));
+#else
+  return 0;
+#endif
+}
+
+/* Linux NewReno/SACK/FACK/ECN state machine.
+ * --------------------------------------
+ *
+ * "Open"      Normal state, no dubious events, fast path.
+ * "Disorder"   In all the respects it is "Open",
+ *             but requires a bit more attention. It is entered when
+ *             we see some SACKs or dupacks. It is split of "Open"
+ *             mainly to move some processing from fast path to slow one.
+ * "CWR"       CWND was reduced due to some Congestion Notification event.
+ *             It can be ECN, ICMP source quench, local device congestion.
+ * "Recovery"  CWND was reduced, we are fast-retransmitting.
+ * "Loss"      CWND was reduced due to RTO timeout or SACK reneging.
+ *
+ * tcp_fastretrans_alert() is entered:
+ * - each incoming ACK, if state is not "Open"
+ * - when arrived ACK is unusual, namely:
+ *     * SACK
+ *     * Duplicate ACK.
+ *     * ECN ECE.
+ *
+ * Counting packets in flight is pretty simple.
+ *
+ *     in_flight = packets_out - left_out + retrans_out
+ *
+ *     packets_out is SND.NXT-SND.UNA counted in packets.
+ *
+ *     retrans_out is number of retransmitted segments.
+ *
+ *     left_out is number of segments left network, but not ACKed yet.
+ *
+ *             left_out = sacked_out + lost_out
+ *
+ *     sacked_out: Packets, which arrived to receiver out of order
+ *                and hence not ACKed. With SACKs this number is simply
+ *                amount of SACKed data. Even without SACKs
+ *                it is easy to give pretty reliable estimate of this number,
+ *                counting duplicate ACKs.
+ *
+ *       lost_out: Packets lost by network. TCP has no explicit
+ *                "loss notification" feedback from network (for now).
+ *                It means that this number can be only _guessed_.
+ *                Actually, it is the heuristics to predict lossage that
+ *                distinguishes different algorithms.
+ *
+ *     F.e. after RTO, when all the queue is considered as lost,
+ *     lost_out = packets_out and in_flight = retrans_out.
+ *
+ *             Essentially, we have now two algorithms counting
+ *             lost packets.
+ *
+ *             FACK: It is the simplest heuristics. As soon as we decided
+ *             that something is lost, we decide that _all_ not SACKed
+ *             packets until the most forward SACK are lost. I.e.
+ *             lost_out = fackets_out - sacked_out and left_out = fackets_out.
+ *             It is absolutely correct estimate, if network does not reorder
+ *             packets. And it loses any connection to reality when reordering
+ *             takes place. We use FACK by default until reordering
+ *             is suspected on the path to this destination.
+ *
+ *             NewReno: when Recovery is entered, we assume that one segment
+ *             is lost (classic Reno). While we are in Recovery and
+ *             a partial ACK arrives, we assume that one more packet
+ *             is lost (NewReno). This heuristics are the same in NewReno
+ *             and SACK.
+ *
+ *  Imagine, that's all! Forget about all this shamanism about CWND inflation
+ *  deflation etc. CWND is real congestion window, never inflated, changes
+ *  only according to classic VJ rules.
+ *
+ * Really tricky (and requiring careful tuning) part of algorithm
+ * is hidden in functions tcp_time_to_recover() and tcp_xmit_retransmit_queue().
+ * The first determines the moment _when_ we should reduce CWND and,
+ * hence, slow down forward transmission. In fact, it determines the moment
+ * when we decide that hole is caused by loss, rather than by a reorder.
+ *
+ * tcp_xmit_retransmit_queue() decides, _what_ we should retransmit to fill
+ * holes, caused by lost packets.
+ *
+ * And the most logically complicated part of algorithm is undo
+ * heuristics. We detect false retransmits due to both too early
+ * fast retransmit (reordering) and underestimated RTO, analyzing
+ * timestamps and D-SACKs. When we detect that some segments were
+ * retransmitted by mistake and CWND reduction was wrong, we undo
+ * window reduction and abort recovery phase. This logic is hidden
+ * inside several functions named tcp_try_undo_<something>.
+ */
+
+/* This function decides, when we should leave Disordered state
+ * and enter Recovery phase, reducing congestion window.
+ *
+ * Main question: may we further continue forward transmission
+ * with the same cwnd?
+ */
+static int
+tcp_time_to_recover(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       /* Trick#1: The loss is proven. */
+       if (tp->lost_out)
+               return 1;
+
+       /* Not-A-Trick#2 : Classic rule... */
+       if (tcp_fackets_out(tp) > tp->reordering)
+               return 1;
+
+       /* Trick#3 : when we use RFC2988 timer restart, fast
+        * retransmit can be triggered by timeout of queue head.
+        */
+       if (tcp_head_timedout(sk, tp))
+               return 1;
+
+       /* Trick#4: It is still not OK... But will it be useful to delay
+        * recovery more?
+        */
+       if (tp->packets_out <= tp->reordering &&
+           tp->sacked_out >= max_t(__u32, tp->packets_out/2, sysctl_tcp_reordering) &&
+           !tcp_may_send_now(sk, tp)) {
+               /* We have nothing to send. This connection is limited
+                * either by receiver window or by application.
+                */
+               return 1;
+       }
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* If we receive more dupacks than we expected counting segments
+ * in assumption of absent reordering, interpret this as reordering.
+ * The only another reason could be bug in receiver TCP.
+ */
+static void tcp_check_reno_reordering(struct tcp_opt *tp, int addend)
+{
+#if 0
+       u32 holes;
+
+       holes = max(tp->lost_out, 1U);
+       holes = min(holes, tp->packets_out);
+
+       if (tp->sacked_out + holes > tp->packets_out) {
+               tp->sacked_out = tp->packets_out - holes;
+               tcp_update_reordering(tp, tp->packets_out+addend, 0);
+       }
+#endif
+}
+
+/* Emulate SACKs for SACKless connection: account for a new dupack. */
+
+static void tcp_add_reno_sack(struct tcp_opt *tp)
+{
+#if 0
+       ++tp->sacked_out;
+       tcp_check_reno_reordering(tp, 0);
+       tcp_sync_left_out(tp);
+#endif
+}
+
+/* Account for ACK, ACKing some data in Reno Recovery phase. */
+
+static void tcp_remove_reno_sacks(struct sock *sk, struct tcp_opt *tp, int acked)
+{
+#if 0
+       if (acked > 0) {
+               /* One ACK acked hole. The rest eat duplicate ACKs. */
+               if (acked-1 >= tp->sacked_out)
+                       tp->sacked_out = 0;
+               else
+                       tp->sacked_out -= acked-1;
+       }
+       tcp_check_reno_reordering(tp, acked);
+       tcp_sync_left_out(tp);
+#endif
+}
+
+static inline void tcp_reset_reno_sack(struct tcp_opt *tp)
+{
+#if 0
+       tp->sacked_out = 0;
+       tp->left_out = tp->lost_out;
+#endif
+}
+
+/* Mark head of queue up as lost. */
+static void
+tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_seq)
+{
+#if 0
+       struct sk_buff *skb;
+       int cnt = packets;
+
+       BUG_TRAP(cnt <= tp->packets_out);
+
+       for_retrans_queue(skb, sk, tp) {
+               if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
+                       break;
+               if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
+                       TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+                       tp->lost_out++;
+               }
+       }
+       tcp_sync_left_out(tp);
+#endif
+}
+
+/* Account newly detected lost packet(s) */
+
+static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (IsFack(tp)) {
+               int lost = tp->fackets_out - tp->reordering;
+               if (lost <= 0)
+                       lost = 1;
+               tcp_mark_head_lost(sk, tp, lost, tp->high_seq);
+       } else {
+               tcp_mark_head_lost(sk, tp, 1, tp->high_seq);
+       }
+
+       /* New heuristics: it is possible only after we switched
+        * to restart timer each time when something is ACKed.
+        * Hence, we can detect timed out packets during fast
+        * retransmit without falling to slow start.
+        */
+       if (tcp_head_timedout(sk, tp)) {
+               struct sk_buff *skb;
+
+               for_retrans_queue(skb, sk, tp) {
+                       if (tcp_skb_timedout(tp, skb) &&
+                           !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
+                               TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+                               tp->lost_out++;
+                       }
+               }
+               tcp_sync_left_out(tp);
+       }
+#endif
+}
+
+/* CWND moderation, preventing bursts due to too big ACKs
+ * in dubious situations.
+ */
+static __inline__ void tcp_moderate_cwnd(struct tcp_opt *tp)
+{
+#if 0
+       tp->snd_cwnd = min(tp->snd_cwnd,
+                          tcp_packets_in_flight(tp)+tcp_max_burst(tp));
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Decrease cwnd each second ack. */
+
+static void tcp_cwnd_down(struct tcp_opt *tp)
+{
+#if 0
+       int decr = tp->snd_cwnd_cnt + 1;
+
+       tp->snd_cwnd_cnt = decr&1;
+       decr >>= 1;
+
+       if (decr && tp->snd_cwnd > tp->snd_ssthresh/2)
+               tp->snd_cwnd -= decr;
+
+       tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Nothing was retransmitted or returned timestamp is less
+ * than timestamp of the first retransmission.
+ */
+static __inline__ int tcp_packet_delayed(struct tcp_opt *tp)
+{
+#if 0
+       return !tp->retrans_stamp ||
+               (tp->saw_tstamp && tp->rcv_tsecr &&
+                (__s32)(tp->rcv_tsecr - tp->retrans_stamp) < 0);
+#else
+  return 0;
+#endif
+}
+
+/* Undo procedures. */
+
+#if FASTRETRANS_DEBUG > 1
+static void DBGUNDO(struct sock *sk, struct tcp_opt *tp, const char *msg)
+{
+#if 0
+       printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
+              msg,
+              NIPQUAD(sk->daddr), ntohs(sk->dport),
+              tp->snd_cwnd, tp->left_out,
+              tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out);
+#endif
+}
+#else
+#define DBGUNDO(x...) do { } while (0)
+#endif
+
+static void tcp_undo_cwr(struct tcp_opt *tp, int undo)
+{
+#if 0
+       if (tp->prior_ssthresh) {
+               tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
+
+               if (undo && tp->prior_ssthresh > tp->snd_ssthresh) {
+                       tp->snd_ssthresh = tp->prior_ssthresh;
+                       TCP_ECN_withdraw_cwr(tp);
+               }
+       } else {
+               tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh);
+       }
+       tcp_moderate_cwnd(tp);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+static inline int tcp_may_undo(struct tcp_opt *tp)
+{
+#if 0
+       return tp->undo_marker &&
+               (!tp->undo_retrans || tcp_packet_delayed(tp));
+#else
+  return 0;
+#endif
+}
+
+/* People celebrate: "We love our President!" */
+static int tcp_try_undo_recovery(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (tcp_may_undo(tp)) {
+               /* Happy end! We did not retransmit anything
+                * or our original transmission succeeded.
+                */
+               DBGUNDO(sk, tp, tp->ca_state == TCP_CA_Loss ? "loss" : "retrans");
+               tcp_undo_cwr(tp, 1);
+               if (tp->ca_state == TCP_CA_Loss)
+                       NET_INC_STATS_BH(TCPLossUndo);
+               else
+                       NET_INC_STATS_BH(TCPFullUndo);
+               tp->undo_marker = 0;
+       }
+       if (tp->snd_una == tp->high_seq && IsReno(tp)) {
+               /* Hold old state until something *above* high_seq
+                * is ACKed. For Reno it is MUST to prevent false
+                * fast retransmits (RFC2582). SACK TCP is safe. */
+               tcp_moderate_cwnd(tp);
+               return 1;
+       }
+       tp->ca_state = TCP_CA_Open;
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* Try to undo cwnd reduction, because D-SACKs acked all retransmitted data */
+static void tcp_try_undo_dsack(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (tp->undo_marker && !tp->undo_retrans) {
+               DBGUNDO(sk, tp, "D-SACK");
+               tcp_undo_cwr(tp, 1);
+               tp->undo_marker = 0;
+               NET_INC_STATS_BH(TCPDSACKUndo);
+       }
+#endif
+}
+
+/* Undo during fast recovery after partial ACK. */
+
+static int tcp_try_undo_partial(struct sock *sk, struct tcp_opt *tp, int acked)
+{
+#if 0
+       /* Partial ACK arrived. Force Hoe's retransmit. */
+       int failed = IsReno(tp) || tp->fackets_out>tp->reordering;
+
+       if (tcp_may_undo(tp)) {
+               /* Plain luck! Hole if filled with delayed
+                * packet, rather than with a retransmit.
+                */
+               if (tp->retrans_out == 0)
+                       tp->retrans_stamp = 0;
+
+               tcp_update_reordering(tp, tcp_fackets_out(tp)+acked, 1);
+
+               DBGUNDO(sk, tp, "Hoe");
+               tcp_undo_cwr(tp, 0);
+               NET_INC_STATS_BH(TCPPartialUndo);
+
+               /* So... Do not make Hoe's retransmit yet.
+                * If the first packet was delayed, the rest
+                * ones are most probably delayed as well.
+                */
+               failed = 0;
+       }
+       return failed;
+#else
+  return 0;
+#endif
+}
+
+/* Undo during loss recovery after partial ACK. */
+static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (tcp_may_undo(tp)) {
+               struct sk_buff *skb;
+               for_retrans_queue(skb, sk, tp) {
+                       TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
+               }
+               DBGUNDO(sk, tp, "partial loss");
+               tp->lost_out = 0;
+               tp->left_out = tp->sacked_out;
+               tcp_undo_cwr(tp, 1);
+               NET_INC_STATS_BH(TCPLossUndo);
+               tp->retransmits = 0;
+               tp->undo_marker = 0;
+               if (!IsReno(tp))
+                       tp->ca_state = TCP_CA_Open;
+               return 1;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void tcp_complete_cwr(struct tcp_opt *tp)
+{
+#if 0
+       tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
+{
+#if 0
+       tp->left_out = tp->sacked_out;
+
+       if (tp->retrans_out == 0)
+               tp->retrans_stamp = 0;
+
+       if (flag&FLAG_ECE)
+               tcp_enter_cwr(tp);
+
+       if (tp->ca_state != TCP_CA_CWR) {
+               int state = TCP_CA_Open;
+
+               if (tp->left_out ||
+                   tp->retrans_out ||
+                   tp->undo_marker)
+                       state = TCP_CA_Disorder;
+
+               if (tp->ca_state != state) {
+                       tp->ca_state = state;
+                       tp->high_seq = tp->snd_nxt;
+               }
+               tcp_moderate_cwnd(tp);
+       } else {
+               tcp_cwnd_down(tp);
+       }
+#endif
+}
+
+/* Process an event, which can update packets-in-flight not trivially.
+ * Main goal of this function is to calculate new estimate for left_out,
+ * taking into account both packets sitting in receiver's buffer and
+ * packets lost by network.
+ *
+ * Besides that it does CWND reduction, when packet loss is detected
+ * and changes state of machine.
+ *
+ * It does _not_ decide what to send, it is made in function
+ * tcp_xmit_retransmit_queue().
+ */
+static void
+tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
+                     int prior_packets, int flag)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP));
+
+       /* Some technical things:
+        * 1. Reno does not count dupacks (sacked_out) automatically. */
+       if (!tp->packets_out)
+               tp->sacked_out = 0;
+        /* 2. SACK counts snd_fack in packets inaccurately. */
+       if (tp->sacked_out == 0)
+               tp->fackets_out = 0;
+
+        /* Now state machine starts.
+        * A. ECE, hence prohibit cwnd undoing, the reduction is required. */
+       if (flag&FLAG_ECE)
+               tp->prior_ssthresh = 0;
+
+       /* B. In all the states check for reneging SACKs. */
+       if (tp->sacked_out && tcp_check_sack_reneging(sk, tp))
+               return;
+
+       /* C. Process data loss notification, provided it is valid. */
+       if ((flag&FLAG_DATA_LOST) &&
+           before(tp->snd_una, tp->high_seq) &&
+           tp->ca_state != TCP_CA_Open &&
+           tp->fackets_out > tp->reordering) {
+               tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq);
+               NET_INC_STATS_BH(TCPLoss);
+       }
+
+       /* D. Synchronize left_out to current state. */
+       tcp_sync_left_out(tp);
+
+       /* E. Check state exit conditions. State can be terminated
+        *    when high_seq is ACKed. */
+       if (tp->ca_state == TCP_CA_Open) {
+               BUG_TRAP(tp->retrans_out == 0);
+               tp->retrans_stamp = 0;
+       } else if (!before(tp->snd_una, tp->high_seq)) {
+               switch (tp->ca_state) {
+               case TCP_CA_Loss:
+                       tp->retransmits = 0;
+                       if (tcp_try_undo_recovery(sk, tp))
+                               return;
+                       break;
+
+               case TCP_CA_CWR:
+                       /* CWR is to be held something *above* high_seq
+                        * is ACKed for CWR bit to reach receiver. */
+                       if (tp->snd_una != tp->high_seq) {
+                               tcp_complete_cwr(tp);
+                               tp->ca_state = TCP_CA_Open;
+                       }
+                       break;
+
+               case TCP_CA_Disorder:
+                       tcp_try_undo_dsack(sk, tp);
+                       if (!tp->undo_marker ||
+                           /* For SACK case do not Open to allow to undo
+                            * catching for all duplicate ACKs. */
+                           IsReno(tp) || tp->snd_una != tp->high_seq) {
+                               tp->undo_marker = 0;
+                               tp->ca_state = TCP_CA_Open;
+                       }
+                       break;
+
+               case TCP_CA_Recovery:
+                       if (IsReno(tp))
+                               tcp_reset_reno_sack(tp);
+                       if (tcp_try_undo_recovery(sk, tp))
+                               return;
+                       tcp_complete_cwr(tp);
+                       break;
+               }
+       }
+
+       /* F. Process state. */
+       switch (tp->ca_state) {
+       case TCP_CA_Recovery:
+               if (prior_snd_una == tp->snd_una) {
+                       if (IsReno(tp) && is_dupack)
+                               tcp_add_reno_sack(tp);
+               } else {
+                       int acked = prior_packets - tp->packets_out;
+                       if (IsReno(tp))
+                               tcp_remove_reno_sacks(sk, tp, acked);
+                       is_dupack = tcp_try_undo_partial(sk, tp, acked);
+               }
+               break;
+       case TCP_CA_Loss:
+               if (flag&FLAG_DATA_ACKED)
+                       tp->retransmits = 0;
+               if (!tcp_try_undo_loss(sk, tp)) {
+                       tcp_moderate_cwnd(tp);
+                       tcp_xmit_retransmit_queue(sk);
+                       return;
+               }
+               if (tp->ca_state != TCP_CA_Open)
+                       return;
+               /* Loss is undone; fall through to processing in Open state. */
+       default:
+               if (IsReno(tp)) {
+                       if (tp->snd_una != prior_snd_una)
+                               tcp_reset_reno_sack(tp);
+                       if (is_dupack)
+                               tcp_add_reno_sack(tp);
+               }
+
+               if (tp->ca_state == TCP_CA_Disorder)
+                       tcp_try_undo_dsack(sk, tp);
+
+               if (!tcp_time_to_recover(sk, tp)) {
+                       tcp_try_to_open(sk, tp, flag);
+                       return;
+               }
+
+               /* Otherwise enter Recovery state */
+
+               if (IsReno(tp))
+                       NET_INC_STATS_BH(TCPRenoRecovery);
+               else
+                       NET_INC_STATS_BH(TCPSackRecovery);
+
+               tp->high_seq = tp->snd_nxt;
+               tp->prior_ssthresh = 0;
+               tp->undo_marker = tp->snd_una;
+               tp->undo_retrans = tp->retrans_out;
+
+               if (tp->ca_state < TCP_CA_CWR) {
+                       if (!(flag&FLAG_ECE))
+                               tp->prior_ssthresh = tcp_current_ssthresh(tp);
+                       tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+                       TCP_ECN_queue_cwr(tp);
+               }
+
+               tp->snd_cwnd_cnt = 0;
+               tp->ca_state = TCP_CA_Recovery;
+       }
+
+       if (is_dupack || tcp_head_timedout(sk, tp))
+               tcp_update_scoreboard(sk, tp);
+       tcp_cwnd_down(tp);
+       tcp_xmit_retransmit_queue(sk);
+#endif
+}
+
+/* Read draft-ietf-tcplw-high-performance before mucking
+ * with this code. (Superceeds RFC1323)
+ */
+static void tcp_ack_saw_tstamp(struct tcp_opt *tp, int flag)
+{
+#if 0
+       __u32 seq_rtt;
+
+       /* RTTM Rule: A TSecr value received in a segment is used to
+        * update the averaged RTT measurement only if the segment
+        * acknowledges some new data, i.e., only if it advances the
+        * left edge of the send window.
+        *
+        * See draft-ietf-tcplw-high-performance-00, section 3.3.
+        * 1998/04/10 Andrey V. Savochkin <saw@msu.ru>
+        *
+        * Changed: reset backoff as soon as we see the first valid sample.
+        * If we do not, we get strongly overstimated rto. With timestamps
+        * samples are accepted even from very old segments: f.e., when rtt=1
+        * increases to 8, we retransmit 5 times and after 8 seconds delayed
+        * answer arrives rto becomes 120 seconds! If at least one of segments
+        * in window is lost... Voila.                          --ANK (010210)
+        */
+       seq_rtt = tcp_time_stamp - tp->rcv_tsecr;
+       tcp_rtt_estimator(tp, seq_rtt);
+       tcp_set_rto(tp);
+       tp->backoff = 0;
+       tcp_bound_rto(tp);
+#endif
+}
+
+static void tcp_ack_no_tstamp(struct tcp_opt *tp, u32 seq_rtt, int flag)
+{
+#if 0
+       /* We don't have a timestamp. Can only use
+        * packets that are not retransmitted to determine
+        * rtt estimates. Also, we must not reset the
+        * backoff for rto until we get a non-retransmitted
+        * packet. This allows us to deal with a situation
+        * where the network delay has increased suddenly.
+        * I.e. Karn's algorithm. (SIGCOMM '87, p5.)
+        */
+
+       if (flag & FLAG_RETRANS_DATA_ACKED)
+               return;
+
+       tcp_rtt_estimator(tp, seq_rtt);
+       tcp_set_rto(tp);
+       tp->backoff = 0;
+       tcp_bound_rto(tp);
+#endif
+}
+
+static __inline__ void
+tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
+{
+#if 0
+       /* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
+       if (tp->saw_tstamp && tp->rcv_tsecr)
+               tcp_ack_saw_tstamp(tp, flag);
+       else if (seq_rtt >= 0)
+               tcp_ack_no_tstamp(tp, seq_rtt, flag);
+#endif
+}
+
+/* This is Jacobson's slow start and congestion avoidance. 
+ * SIGCOMM '88, p. 328.
+ */
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
+{
+#if 0
+        if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                /* In "safe" area, increase. */
+               if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                       tp->snd_cwnd++;
+       } else {
+                /* In dangerous area, increase slowly.
+                * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+                */
+               if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+                       if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                               tp->snd_cwnd++;
+                       tp->snd_cwnd_cnt=0;
+               } else
+                       tp->snd_cwnd_cnt++;
+        }
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Restart timer after forward progress on connection.
+ * RFC2988 recommends to restart timer to now+rto.
+ */
+
+static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       if (tp->packets_out==0) {
+               tcp_clear_xmit_timer(sk, TCP_TIME_RETRANS);
+       } else {
+               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+       }
+#endif
+}
+
+/* Remove acknowledged frames from the retransmission queue. */
+static int tcp_clean_rtx_queue(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb;
+       __u32 now = tcp_time_stamp;
+       int acked = 0;
+       __s32 seq_rtt = -1;
+
+       while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
+               struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+               __u8 sacked = scb->sacked;
+
+               /* If our packet is before the ack sequence we can
+                * discard it as it's confirmed to have arrived at
+                * the other end.
+                */
+               if (after(scb->end_seq, tp->snd_una))
+                       break;
+
+               /* Initial outgoing SYN's get put onto the write_queue
+                * just like anything else we transmit.  It is not
+                * true data, and if we misinform our callers that
+                * this ACK acks real data, we will erroneously exit
+                * connection startup slow start one packet too
+                * quickly.  This is severely frowned upon behavior.
+                */
+               if(!(scb->flags & TCPCB_FLAG_SYN)) {
+                       acked |= FLAG_DATA_ACKED;
+               } else {
+                       acked |= FLAG_SYN_ACKED;
+                       tp->retrans_stamp = 0;
+               }
+
+               if (sacked) {
+                       if(sacked & TCPCB_RETRANS) {
+                               if(sacked & TCPCB_SACKED_RETRANS)
+                                       tp->retrans_out--;
+                               acked |= FLAG_RETRANS_DATA_ACKED;
+                               seq_rtt = -1;
+                       } else if (seq_rtt < 0)
+                               seq_rtt = now - scb->when;
+                       if(sacked & TCPCB_SACKED_ACKED)
+                               tp->sacked_out--;
+                       if(sacked & TCPCB_LOST)
+                               tp->lost_out--;
+                       if(sacked & TCPCB_URG) {
+                               if (tp->urg_mode &&
+                                   !before(scb->end_seq, tp->snd_up))
+                                       tp->urg_mode = 0;
+                       }
+               } else if (seq_rtt < 0)
+                       seq_rtt = now - scb->when;
+               if(tp->fackets_out)
+                       tp->fackets_out--;
+               tp->packets_out--;
+               __skb_unlink(skb, skb->list);
+               tcp_free_skb(sk, skb);
+       }
+
+       if (acked&FLAG_ACKED) {
+               tcp_ack_update_rtt(tp, acked, seq_rtt);
+               tcp_ack_packets_out(sk, tp);
+       }
+
+#if FASTRETRANS_DEBUG > 0
+       BUG_TRAP((int)tp->sacked_out >= 0);
+       BUG_TRAP((int)tp->lost_out >= 0);
+       BUG_TRAP((int)tp->retrans_out >= 0);
+       if (tp->packets_out==0 && tp->sack_ok) {
+               if (tp->lost_out) {
+                       printk(KERN_DEBUG "Leak l=%u %d\n", tp->lost_out, tp->ca_state);
+                       tp->lost_out = 0;
+               }
+               if (tp->sacked_out) {
+                       printk(KERN_DEBUG "Leak s=%u %d\n", tp->sacked_out, tp->ca_state);
+                       tp->sacked_out = 0;
+               }
+               if (tp->retrans_out) {
+                       printk(KERN_DEBUG "Leak r=%u %d\n", tp->retrans_out, tp->ca_state);
+                       tp->retrans_out = 0;
+               }
+       }
+#endif
+       return acked;
+#else
+  return 0;
+#endif
+}
+
+static void tcp_ack_probe(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /* Was it a usable window open? */
+
+       if (!after(TCP_SKB_CB(tp->send_head)->end_seq, tp->snd_una + tp->snd_wnd)) {
+               tp->backoff = 0;
+               tcp_clear_xmit_timer(sk, TCP_TIME_PROBE0);
+               /* Socket must be waked up by subsequent tcp_data_snd_check().
+                * This function is not for random using!
+                */
+       } else {
+               tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0,
+                                    min(tp->rto << tp->backoff, TCP_RTO_MAX));
+       }
+#endif
+}
+
+static __inline__ int tcp_ack_is_dubious(struct tcp_opt *tp, int flag)
+{
+#if 0
+       return (!(flag & FLAG_NOT_DUP) || (flag & FLAG_CA_ALERT) ||
+               tp->ca_state != TCP_CA_Open);
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int tcp_may_raise_cwnd(struct tcp_opt *tp, int flag)
+{
+#if 0
+       return (!(flag & FLAG_ECE) || tp->snd_cwnd < tp->snd_ssthresh) &&
+               !((1<<tp->ca_state)&(TCPF_CA_Recovery|TCPF_CA_CWR));
+#else
+  return 0;
+#endif
+}
+
+/* Check that window update is acceptable.
+ * The function assumes that snd_una<=ack<=snd_next.
+ */
+static __inline__ int
+tcp_may_update_window(struct tcp_opt *tp, u32 ack, u32 ack_seq, u32 nwin)
+{
+#if 0
+       return (after(ack, tp->snd_una) ||
+               after(ack_seq, tp->snd_wl1) ||
+               (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd));
+#else
+  return 0;
+#endif
+}
+
+/* Update our send window.
+ *
+ * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
+ * and in FreeBSD. NetBSD's one is even worse.) is wrong.
+ */
+static int tcp_ack_update_window(struct sock *sk, struct tcp_opt *tp,
+                                struct sk_buff *skb, u32 ack, u32 ack_seq)
+{
+#if 0
+       int flag = 0;
+       u32 nwin = ntohs(skb->h.th->window) << tp->snd_wscale;
+
+       if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
+               flag |= FLAG_WIN_UPDATE;
+               tcp_update_wl(tp, ack, ack_seq);
+
+               if (tp->snd_wnd != nwin) {
+                       tp->snd_wnd = nwin;
+
+                       /* Note, it is the only place, where
+                        * fast path is recovered for sending TCP.
+                        */
+                       tcp_fast_path_check(sk, tp);
+
+                       if (nwin > tp->max_window) {
+                               tp->max_window = nwin;
+                               tcp_sync_mss(sk, tp->pmtu_cookie);
+                       }
+               }
+       }
+
+       tp->snd_una = ack;
+
+       return flag;
+#else
+  return 0;
+#endif
+}
+
+/* This routine deals with incoming acks, but not outgoing ones. */
+static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       u32 prior_snd_una = tp->snd_una;
+       u32 ack_seq = TCP_SKB_CB(skb)->seq;
+       u32 ack = TCP_SKB_CB(skb)->ack_seq;
+       u32 prior_in_flight;
+       int prior_packets;
+
+       /* If the ack is newer than sent or older than previous acks
+        * then we can probably ignore it.
+        */
+       if (after(ack, tp->snd_nxt))
+               goto uninteresting_ack;
+
+       if (before(ack, prior_snd_una))
+               goto old_ack;
+
+       if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
+               /* Window is constant, pure forward advance.
+                * No more checks are required.
+                * Note, we use the fact that SND.UNA>=SND.WL2.
+                */
+               tcp_update_wl(tp, ack, ack_seq);
+               tp->snd_una = ack;
+               flag |= FLAG_WIN_UPDATE;
+
+               NET_INC_STATS_BH(TCPHPAcks);
+       } else {
+               if (ack_seq != TCP_SKB_CB(skb)->end_seq)
+                       flag |= FLAG_DATA;
+               else
+                       NET_INC_STATS_BH(TCPPureAcks);
+
+               flag |= tcp_ack_update_window(sk, tp, skb, ack, ack_seq);
+
+               if (TCP_SKB_CB(skb)->sacked)
+                       flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+
+               if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
+                       flag |= FLAG_ECE;
+       }
+
+       /* We passed data and got it acked, remove any soft error
+        * log. Something worked...
+        */
+       sk->err_soft = 0;
+       tp->rcv_tstamp = tcp_time_stamp;
+       if ((prior_packets = tp->packets_out) == 0)
+               goto no_queue;
+
+       prior_in_flight = tcp_packets_in_flight(tp);
+
+       /* See if we can take anything off of the retransmit queue. */
+       flag |= tcp_clean_rtx_queue(sk);
+
+       if (tcp_ack_is_dubious(tp, flag)) {
+               /* Advanve CWND, if state allows this. */
+               if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd &&
+                   tcp_may_raise_cwnd(tp, flag))
+                       tcp_cong_avoid(tp);
+               tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
+       } else {
+               if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd)
+                       tcp_cong_avoid(tp);
+       }
+
+       if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
+               dst_confirm(sk->dst_cache);
+
+       return 1;
+
+no_queue:
+       tp->probes_out = 0;
+
+       /* If this ack opens up a zero window, clear backoff.  It was
+        * being used to time the probes, and is probably far higher than
+        * it needs to be for normal retransmission.
+        */
+       if (tp->send_head)
+               tcp_ack_probe(sk);
+       return 1;
+
+old_ack:
+       if (TCP_SKB_CB(skb)->sacked)
+               tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+
+uninteresting_ack:
+       SOCK_DEBUG(sk, "Ack %u out of %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+
+/* Look for tcp options. Normally only called on SYN and SYNACK packets.
+ * But, this can also be called on packets in the established flow when
+ * the fast version below fails.
+ */
+void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp, int estab)
+{
+#if 0
+       unsigned char *ptr;
+       struct tcphdr *th = skb->h.th;
+       int length=(th->doff*4)-sizeof(struct tcphdr);
+
+       ptr = (unsigned char *)(th + 1);
+       tp->saw_tstamp = 0;
+
+       while(length>0) {
+               int opcode=*ptr++;
+               int opsize;
+
+               switch (opcode) {
+                       case TCPOPT_EOL:
+                               return;
+                       case TCPOPT_NOP:        /* Ref: RFC 793 section 3.1 */
+                               length--;
+                               continue;
+                       default:
+                               opsize=*ptr++;
+                               if (opsize < 2) /* "silly options" */
+                                       return;
+                               if (opsize > length)
+                                       return; /* don't parse partial options */
+                               switch(opcode) {
+                               case TCPOPT_MSS:
+                                       if(opsize==TCPOLEN_MSS && th->syn && !estab) {
+                                               u16 in_mss = ntohs(*(__u16 *)ptr);
+                                               if (in_mss) {
+                                                       if (tp->user_mss && tp->user_mss < in_mss)
+                                                               in_mss = tp->user_mss;
+                                                       tp->mss_clamp = in_mss;
+                                               }
+                                       }
+                                       break;
+                               case TCPOPT_WINDOW:
+                                       if(opsize==TCPOLEN_WINDOW && th->syn && !estab)
+                                               if (sysctl_tcp_window_scaling) {
+                                                       tp->wscale_ok = 1;
+                                                       tp->snd_wscale = *(__u8 *)ptr;
+                                                       if(tp->snd_wscale > 14) {
+                                                               if(net_ratelimit())
+                                                                       printk("tcp_parse_options: Illegal window "
+                                                                              "scaling value %d >14 received.",
+                                                                              tp->snd_wscale);
+                                                               tp->snd_wscale = 14;
+                                                       }
+                                               }
+                                       break;
+                               case TCPOPT_TIMESTAMP:
+                                       if(opsize==TCPOLEN_TIMESTAMP) {
+                                               if ((estab && tp->tstamp_ok) ||
+                                                   (!estab && sysctl_tcp_timestamps)) {
+                                                       tp->saw_tstamp = 1;
+                                                       tp->rcv_tsval = ntohl(*(__u32 *)ptr);
+                                                       tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
+                                               }
+                                       }
+                                       break;
+                               case TCPOPT_SACK_PERM:
+                                       if(opsize==TCPOLEN_SACK_PERM && th->syn && !estab) {
+                                               if (sysctl_tcp_sack) {
+                                                       tp->sack_ok = 1;
+                                                       tcp_sack_reset(tp);
+                                               }
+                                       }
+                                       break;
+
+                               case TCPOPT_SACK:
+                                       if((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) &&
+                                          !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) &&
+                                          tp->sack_ok) {
+                                               TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
+                                       }
+                               };
+                               ptr+=opsize-2;
+                               length-=opsize;
+               };
+       }
+#endif
+}
+
+/* Fast parse options. This hopes to only see timestamps.
+ * If it is wrong it falls back on tcp_parse_options().
+ */
+static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, struct tcp_opt *tp)
+{
+#if 0
+       if (th->doff == sizeof(struct tcphdr)>>2) {
+               tp->saw_tstamp = 0;
+               return 0;
+       } else if (tp->tstamp_ok &&
+                  th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
+               __u32 *ptr = (__u32 *)(th + 1);
+               if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+                                 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+                       tp->saw_tstamp = 1;
+                       ++ptr;
+                       tp->rcv_tsval = ntohl(*ptr);
+                       ++ptr;
+                       tp->rcv_tsecr = ntohl(*ptr);
+                       return 1;
+               }
+       }
+       tcp_parse_options(skb, tp, 1);
+       return 1;
+#else
+  return 0;
+#endif
+}
+
+extern __inline__ void
+tcp_store_ts_recent(struct tcp_opt *tp)
+{
+#if 0
+       tp->ts_recent = tp->rcv_tsval;
+       tp->ts_recent_stamp = xtime.tv_sec;
+#endif
+}
+
+extern __inline__ void
+tcp_replace_ts_recent(struct tcp_opt *tp, u32 seq)
+{
+#if 0
+       if (tp->saw_tstamp && !after(seq, tp->rcv_wup)) {
+               /* PAWS bug workaround wrt. ACK frames, the PAWS discard
+                * extra check below makes sure this can only happen
+                * for pure ACK frames.  -DaveM
+                *
+                * Not only, also it occurs for expired timestamps.
+                */
+
+               if((s32)(tp->rcv_tsval - tp->ts_recent) >= 0 ||
+                  xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_24DAYS)
+                       tcp_store_ts_recent(tp);
+       }
+#endif
+}
+
+/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
+ *
+ * It is not fatal. If this ACK does _not_ change critical state (seqs, window)
+ * it can pass through stack. So, the following predicate verifies that
+ * this segment is not used for anything but congestion avoidance or
+ * fast retransmit. Moreover, we even are able to eliminate most of such
+ * second order effects, if we apply some small "replay" window (~RTO)
+ * to timestamp space.
+ *
+ * All these measures still do not guarantee that we reject wrapped ACKs
+ * on networks with high bandwidth, when sequence space is recycled fastly,
+ * but it guarantees that such events will be very rare and do not affect
+ * connection seriously. This doesn't look nice, but alas, PAWS is really
+ * buggy extension.
+ *
+ * [ Later note. Even worse! It is buggy for segments _with_ data. RFC
+ * states that events when retransmit arrives after original data are rare.
+ * It is a blatant lie. VJ forgot about fast retransmit! 8)8) It is
+ * the biggest problem on large power networks even with minor reordering.
+ * OK, let's give it small replay window. If peer clock is even 1hz, it is safe
+ * up to bandwidth of 18Gigabit/sec. 8) ]
+ */
+
+static int tcp_disordered_ack(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       struct tcphdr *th = skb->h.th;
+       u32 seq = TCP_SKB_CB(skb)->seq;
+       u32 ack = TCP_SKB_CB(skb)->ack_seq;
+
+       return (/* 1. Pure ACK with correct sequence number. */
+               (th->ack && seq == TCP_SKB_CB(skb)->end_seq && seq == tp->rcv_nxt) &&
+
+               /* 2. ... and duplicate ACK. */
+               ack == tp->snd_una &&
+
+               /* 3. ... and does not update window. */
+               !tcp_may_update_window(tp, ack, seq, ntohs(th->window)<<tp->snd_wscale) &&
+
+               /* 4. ... and sits in replay window. */
+               (s32)(tp->ts_recent - tp->rcv_tsval) <= (tp->rto*1024)/HZ);
+#endif
+}
+
+extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       return ((s32)(tp->ts_recent - tp->rcv_tsval) > TCP_PAWS_WINDOW &&
+               xtime.tv_sec < tp->ts_recent_stamp + TCP_PAWS_24DAYS &&
+               !tcp_disordered_ack(tp, skb));
+#else
+  return 0;
+#endif
+}
+
+/* Check segment sequence number for validity.
+ *
+ * Segment controls are considered valid, if the segment
+ * fits to the window after truncation to the window. Acceptability
+ * of data (and SYN, FIN, of course) is checked separately.
+ * See tcp_data_queue(), for example.
+ *
+ * Also, controls (RST is main one) are accepted using RCV.WUP instead
+ * of RCV.NXT. Peer still did not advance his SND.UNA when we
+ * delayed ACK, so that hisSND.UNA<=ourRCV.WUP.
+ * (borrowed from freebsd)
+ */
+
+static inline int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+       return  !before(end_seq, tp->rcv_wup) &&
+               !after(seq, tp->rcv_nxt + tcp_receive_window(tp));
+#else
+  return 0;
+#endif
+}
+
+/* When we get a reset we do this. */
+static void tcp_reset(struct sock *sk)
+{
+#if 0
+       /* We want the right error as BSD sees it (and indeed as we do). */
+       switch (sk->state) {
+               case TCP_SYN_SENT:
+                       sk->err = ECONNREFUSED;
+                       break;
+               case TCP_CLOSE_WAIT:
+                       sk->err = EPIPE;
+                       break;
+               case TCP_CLOSE:
+                       return;
+               default:
+                       sk->err = ECONNRESET;
+       }
+
+       if (!sk->dead)
+               sk->error_report(sk);
+
+       tcp_done(sk);
+#endif
+}
+
+/*
+ *     Process the FIN bit. This now behaves as it is supposed to work
+ *     and the FIN takes effect when it is validly part of sequence
+ *     space. Not before when we get holes.
+ *
+ *     If we are ESTABLISHED, a received fin moves us to CLOSE-WAIT
+ *     (and thence onto LAST-ACK and finally, CLOSE, we never enter
+ *     TIME-WAIT)
+ *
+ *     If we are in FINWAIT-1, a received FIN indicates simultaneous
+ *     close and we go into CLOSING (and later onto TIME-WAIT)
+ *
+ *     If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
+ */
+static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       tcp_schedule_ack(tp);
+
+       sk->shutdown |= RCV_SHUTDOWN;
+       sk->done = 1;
+
+       switch(sk->state) {
+               case TCP_SYN_RECV:
+               case TCP_ESTABLISHED:
+                       /* Move to CLOSE_WAIT */
+                       tcp_set_state(sk, TCP_CLOSE_WAIT);
+                       tp->ack.pingpong = 1;
+                       break;
+
+               case TCP_CLOSE_WAIT:
+               case TCP_CLOSING:
+                       /* Received a retransmission of the FIN, do
+                        * nothing.
+                        */
+                       break;
+               case TCP_LAST_ACK:
+                       /* RFC793: Remain in the LAST-ACK state. */
+                       break;
+
+               case TCP_FIN_WAIT1:
+                       /* This case occurs when a simultaneous close
+                        * happens, we must ack the received FIN and
+                        * enter the CLOSING state.
+                        */
+                       tcp_send_ack(sk);
+                       tcp_set_state(sk, TCP_CLOSING);
+                       break;
+               case TCP_FIN_WAIT2:
+                       /* Received a FIN -- send ACK and enter TIME_WAIT. */
+                       tcp_send_ack(sk);
+                       tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+                       break;
+               default:
+                       /* Only TCP_LISTEN and TCP_CLOSE are left, in these
+                        * cases we should never reach this piece of code.
+                        */
+                       printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
+                       break;
+       };
+
+       /* It _is_ possible, that we have something out-of-order _after_ FIN.
+        * Probably, we should reset in this case. For now drop them.
+        */
+       __skb_queue_purge(&tp->out_of_order_queue);
+       if (tp->sack_ok)
+               tcp_sack_reset(tp);
+       tcp_mem_reclaim(sk);
+
+       if (!sk->dead) {
+               sk->state_change(sk);
+
+               /* Do not send POLL_HUP for half duplex close. */
+               if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE)
+                       sk_wake_async(sk, 1, POLL_HUP);
+               else
+                       sk_wake_async(sk, 1, POLL_IN);
+       }
+#endif
+}
+
+static __inline__ int
+tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, u32 end_seq)
+{
+#if 0
+       if (!after(seq, sp->end_seq) && !after(sp->start_seq, end_seq)) {
+               if (before(seq, sp->start_seq))
+                       sp->start_seq = seq;
+               if (after(end_seq, sp->end_seq))
+                       sp->end_seq = end_seq;
+               return 1;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ void tcp_dsack_set(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+       if (tp->sack_ok && sysctl_tcp_dsack) {
+               if (before(seq, tp->rcv_nxt))
+                       NET_INC_STATS_BH(TCPDSACKOldSent);
+               else
+                       NET_INC_STATS_BH(TCPDSACKOfoSent);
+
+               tp->dsack = 1;
+               tp->duplicate_sack[0].start_seq = seq;
+               tp->duplicate_sack[0].end_seq = end_seq;
+               tp->eff_sacks = min(tp->num_sacks+1, 4-tp->tstamp_ok);
+       }
+#endif
+}
+
+static __inline__ void tcp_dsack_extend(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+       if (!tp->dsack)
+               tcp_dsack_set(tp, seq, end_seq);
+       else
+               tcp_sack_extend(tp->duplicate_sack, seq, end_seq);
+#endif
+}
+
+static void tcp_send_dupack(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+           before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+               NET_INC_STATS_BH(DelayedACKLost);
+               tcp_enter_quickack_mode(tp);
+
+               if (tp->sack_ok && sysctl_tcp_dsack) {
+                       u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+                       if (after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt))
+                               end_seq = tp->rcv_nxt;
+                       tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, end_seq);
+               }
+       }
+
+       tcp_send_ack(sk);
+#endif
+}
+
+/* These routines update the SACK block as out-of-order packets arrive or
+ * in-order packets close up the sequence space.
+ */
+static void tcp_sack_maybe_coalesce(struct tcp_opt *tp)
+{
+#if 0
+       int this_sack;
+       struct tcp_sack_block *sp = &tp->selective_acks[0];
+       struct tcp_sack_block *swalk = sp+1;
+
+       /* See if the recent change to the first SACK eats into
+        * or hits the sequence space of other SACK blocks, if so coalesce.
+        */
+       for (this_sack = 1; this_sack < tp->num_sacks; ) {
+               if (tcp_sack_extend(sp, swalk->start_seq, swalk->end_seq)) {
+                       int i;
+
+                       /* Zap SWALK, by moving every further SACK up by one slot.
+                        * Decrease num_sacks.
+                        */
+                       tp->num_sacks--;
+                       tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+                       for(i=this_sack; i < tp->num_sacks; i++)
+                               sp[i] = sp[i+1];
+                       continue;
+               }
+               this_sack++, swalk++;
+       }
+#endif
+}
+
+static __inline__ void tcp_sack_swap(struct tcp_sack_block *sack1, struct tcp_sack_block *sack2)
+{
+#if 0
+       __u32 tmp;
+
+       tmp = sack1->start_seq;
+       sack1->start_seq = sack2->start_seq;
+       sack2->start_seq = tmp;
+
+       tmp = sack1->end_seq;
+       sack1->end_seq = sack2->end_seq;
+       sack2->end_seq = tmp;
+#endif
+}
+
+static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct tcp_sack_block *sp = &tp->selective_acks[0];
+       int cur_sacks = tp->num_sacks;
+       int this_sack;
+
+       if (!cur_sacks)
+               goto new_sack;
+
+       for (this_sack=0; this_sack<cur_sacks; this_sack++, sp++) {
+               if (tcp_sack_extend(sp, seq, end_seq)) {
+                       /* Rotate this_sack to the first one. */
+                       for (; this_sack>0; this_sack--, sp--)
+                               tcp_sack_swap(sp, sp-1);
+                       if (cur_sacks > 1)
+                               tcp_sack_maybe_coalesce(tp);
+                       return;
+               }
+       }
+
+       /* Could not find an adjacent existing SACK, build a new one,
+        * put it at the front, and shift everyone else down.  We
+        * always know there is at least one SACK present already here.
+        *
+        * If the sack array is full, forget about the last one.
+        */
+       if (this_sack >= 4) {
+               this_sack--;
+               tp->num_sacks--;
+               sp--;
+       }
+       for(; this_sack > 0; this_sack--, sp--)
+               *sp = *(sp-1);
+
+new_sack:
+       /* Build the new head SACK, and we're done. */
+       sp->start_seq = seq;
+       sp->end_seq = end_seq;
+       tp->num_sacks++;
+       tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+#endif
+}
+
+/* RCV.NXT advances, some SACKs should be eaten. */
+
+static void tcp_sack_remove(struct tcp_opt *tp)
+{
+#if 0
+       struct tcp_sack_block *sp = &tp->selective_acks[0];
+       int num_sacks = tp->num_sacks;
+       int this_sack;
+
+       /* Empty ofo queue, hence, all the SACKs are eaten. Clear. */
+       if (skb_queue_len(&tp->out_of_order_queue) == 0) {
+               tp->num_sacks = 0;
+               tp->eff_sacks = tp->dsack;
+               return;
+       }
+
+       for(this_sack = 0; this_sack < num_sacks; ) {
+               /* Check if the start of the sack is covered by RCV.NXT. */
+               if (!before(tp->rcv_nxt, sp->start_seq)) {
+                       int i;
+
+                       /* RCV.NXT must cover all the block! */
+                       BUG_TRAP(!before(tp->rcv_nxt, sp->end_seq));
+
+                       /* Zap this SACK, by moving forward any other SACKS. */
+                       for (i=this_sack+1; i < num_sacks; i++)
+                               tp->selective_acks[i-1] = tp->selective_acks[i];
+                       num_sacks--;
+                       continue;
+               }
+               this_sack++;
+               sp++;
+       }
+       if (num_sacks != tp->num_sacks) {
+               tp->num_sacks = num_sacks;
+               tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+       }
+#endif
+}
+
+/* This one checks to see if we can put data from the
+ * out_of_order queue into the receive_queue.
+ */
+static void tcp_ofo_queue(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       __u32 dsack_high = tp->rcv_nxt;
+       struct sk_buff *skb;
+
+       while ((skb = skb_peek(&tp->out_of_order_queue)) != NULL) {
+               if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+                       break;
+
+               if (before(TCP_SKB_CB(skb)->seq, dsack_high)) {
+                       __u32 dsack = dsack_high;
+                       if (before(TCP_SKB_CB(skb)->end_seq, dsack_high))
+                               dsack_high = TCP_SKB_CB(skb)->end_seq;
+                       tcp_dsack_extend(tp, TCP_SKB_CB(skb)->seq, dsack);
+               }
+
+               if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+                       SOCK_DEBUG(sk, "ofo packet was already received \n");
+                       __skb_unlink(skb, skb->list);
+                       __kfree_skb(skb);
+                       continue;
+               }
+               SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n",
+                          tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+                          TCP_SKB_CB(skb)->end_seq);
+
+               __skb_unlink(skb, skb->list);
+               __skb_queue_tail(&sk->receive_queue, skb);
+               tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               if(skb->h.th->fin)
+                       tcp_fin(skb, sk, skb->h.th);
+       }
+#endif
+}
+
+static inline int tcp_rmem_schedule(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       return (int)skb->truesize <= sk->forward_alloc ||
+               tcp_mem_schedule(sk, skb->truesize, 1);
+#else
+  return 0;
+#endif
+}
+
+static int tcp_prune_queue(struct sock *sk);
+
+static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcphdr *th = skb->h.th;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int eaten = -1;
+
+       if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
+               goto drop;
+
+       th = skb->h.th;
+       __skb_pull(skb, th->doff*4);
+
+       TCP_ECN_accept_cwr(tp, skb);
+
+       if (tp->dsack) {
+               tp->dsack = 0;
+               tp->eff_sacks = min_t(unsigned int, tp->num_sacks, 4-tp->tstamp_ok);
+       }
+
+       /*  Queue data for delivery to the user.
+        *  Packets in sequence go to the receive queue.
+        *  Out of sequence packets to the out_of_order_queue.
+        */
+       if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+               if (tcp_receive_window(tp) == 0)
+                       goto out_of_window;
+
+               /* Ok. In sequence. In window. */
+               if (tp->ucopy.task == current &&
+                   tp->copied_seq == tp->rcv_nxt &&
+                   tp->ucopy.len &&
+                   sk->lock.users &&
+                   !tp->urg_data) {
+                       int chunk = min_t(unsigned int, skb->len, tp->ucopy.len);
+
+                       __set_current_state(TASK_RUNNING);
+
+                       local_bh_enable();
+                       if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) {
+                               tp->ucopy.len -= chunk;
+                               tp->copied_seq += chunk;
+                               eaten = (chunk == skb->len && !th->fin);
+                       }
+                       local_bh_disable();
+               }
+
+               if (eaten <= 0) {
+queue_and_out:
+                       if (eaten < 0 &&
+                           (atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
+                            !tcp_rmem_schedule(sk, skb))) {
+                               if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb))
+                                       goto drop;
+                       }
+                       tcp_set_owner_r(skb, sk);
+                       __skb_queue_tail(&sk->receive_queue, skb);
+               }
+               tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               if(skb->len)
+                       tcp_event_data_recv(sk, tp, skb);
+               if(th->fin)
+                       tcp_fin(skb, sk, th);
+
+               if (skb_queue_len(&tp->out_of_order_queue)) {
+                       tcp_ofo_queue(sk);
+
+                       /* RFC2581. 4.2. SHOULD send immediate ACK, when
+                        * gap in queue is filled.
+                        */
+                       if (skb_queue_len(&tp->out_of_order_queue) == 0)
+                               tp->ack.pingpong = 0;
+               }
+
+               if(tp->num_sacks)
+                       tcp_sack_remove(tp);
+
+               tcp_fast_path_check(sk, tp);
+
+               if (eaten > 0) {
+                       __kfree_skb(skb);
+               } else if (!sk->dead)
+                       sk->data_ready(sk, 0);
+               return;
+       }
+
+       if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+               /* A retransmit, 2nd most common case.  Force an immediate ack. */
+               NET_INC_STATS_BH(DelayedACKLost);
+               tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+out_of_window:
+               tcp_enter_quickack_mode(tp);
+               tcp_schedule_ack(tp);
+drop:
+               __kfree_skb(skb);
+               return;
+       }
+
+       /* Out of window. F.e. zero window probe. */
+       if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt+tcp_receive_window(tp)))
+               goto out_of_window;
+
+       tcp_enter_quickack_mode(tp);
+
+       if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+               /* Partial packet, seq < rcv_next < end_seq */
+               SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n",
+                          tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+                          TCP_SKB_CB(skb)->end_seq);
+
+               tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, tp->rcv_nxt);
+               
+               /* If window is closed, drop tail of packet. But after
+                * remembering D-SACK for its head made in previous line.
+                */
+               if (!tcp_receive_window(tp))
+                       goto out_of_window;
+               goto queue_and_out;
+       }
+
+       TCP_ECN_check_ce(tp, skb);
+
+       if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
+           !tcp_rmem_schedule(sk, skb)) {
+               if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb))
+                       goto drop;
+       }
+
+       /* Disable header prediction. */
+       tp->pred_flags = 0;
+       tcp_schedule_ack(tp);
+
+       SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
+                  tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+       tcp_set_owner_r(skb, sk);
+
+       if (skb_peek(&tp->out_of_order_queue) == NULL) {
+               /* Initial out of order segment, build 1 SACK. */
+               if(tp->sack_ok) {
+                       tp->num_sacks = 1;
+                       tp->dsack = 0;
+                       tp->eff_sacks = 1;
+                       tp->selective_acks[0].start_seq = TCP_SKB_CB(skb)->seq;
+                       tp->selective_acks[0].end_seq = TCP_SKB_CB(skb)->end_seq;
+               }
+               __skb_queue_head(&tp->out_of_order_queue,skb);
+       } else {
+               struct sk_buff *skb1=tp->out_of_order_queue.prev;
+               u32 seq = TCP_SKB_CB(skb)->seq;
+               u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+               if (seq == TCP_SKB_CB(skb1)->end_seq) {
+                       __skb_append(skb1, skb);
+
+                       if (tp->num_sacks == 0 ||
+                           tp->selective_acks[0].end_seq != seq)
+                               goto add_sack;
+
+                       /* Common case: data arrive in order after hole. */
+                       tp->selective_acks[0].end_seq = end_seq;
+                       return;
+               }
+
+               /* Find place to insert this segment. */
+               do {
+                       if (!after(TCP_SKB_CB(skb1)->seq, seq))
+                               break;
+               } while ((skb1=skb1->prev) != (struct sk_buff*)&tp->out_of_order_queue);
+
+               /* Do skb overlap to previous one? */
+               if (skb1 != (struct sk_buff*)&tp->out_of_order_queue &&
+                   before(seq, TCP_SKB_CB(skb1)->end_seq)) {
+                       if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
+                               /* All the bits are present. Drop. */
+                               __kfree_skb(skb);
+                               tcp_dsack_set(tp, seq, end_seq);
+                               goto add_sack;
+                       }
+                       if (after(seq, TCP_SKB_CB(skb1)->seq)) {
+                               /* Partial overlap. */
+                               tcp_dsack_set(tp, seq, TCP_SKB_CB(skb1)->end_seq);
+                       } else {
+                               skb1 = skb1->prev;
+                       }
+               }
+               __skb_insert(skb, skb1, skb1->next, &tp->out_of_order_queue);
+               
+               /* And clean segments covered by new one as whole. */
+               while ((skb1 = skb->next) != (struct sk_buff*)&tp->out_of_order_queue &&
+                      after(end_seq, TCP_SKB_CB(skb1)->seq)) {
+                      if (before(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
+                              tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, end_seq);
+                              break;
+                      }
+                      __skb_unlink(skb1, skb1->list);
+                      tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq);
+                      __kfree_skb(skb1);
+               }
+
+add_sack:
+               if (tp->sack_ok)
+                       tcp_sack_new_ofo_skb(sk, seq, end_seq);
+       }
+#endif
+}
+
+/* Collapse contiguous sequence of skbs head..tail with
+ * sequence numbers start..end.
+ * Segments with FIN/SYN are not collapsed (only because this
+ * simplifies code)
+ */
+static void
+tcp_collapse(struct sock *sk, struct sk_buff *head,
+            struct sk_buff *tail, u32 start, u32 end)
+{
+#if 0
+       struct sk_buff *skb;
+
+       /* First, check that queue is collapsable and find
+        * the point where collapsing can be useful. */
+       for (skb = head; skb != tail; ) {
+               /* No new bits? It is possible on ofo queue. */
+               if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
+                       struct sk_buff *next = skb->next;
+                       __skb_unlink(skb, skb->list);
+                       __kfree_skb(skb);
+                       NET_INC_STATS_BH(TCPRcvCollapsed);
+                       skb = next;
+                       continue;
+               }
+
+               /* The first skb to collapse is:
+                * - not SYN/FIN and
+                * - bloated or contains data before "start" or
+                *   overlaps to the next one.
+                */
+               if (!skb->h.th->syn && !skb->h.th->fin &&
+                   (tcp_win_from_space(skb->truesize) > skb->len ||
+                    before(TCP_SKB_CB(skb)->seq, start) ||
+                    (skb->next != tail &&
+                     TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb->next)->seq)))
+                       break;
+
+               /* Decided to skip this, advance start seq. */
+               start = TCP_SKB_CB(skb)->end_seq;
+               skb = skb->next;
+       }
+       if (skb == tail || skb->h.th->syn || skb->h.th->fin)
+               return;
+
+       while (before(start, end)) {
+               struct sk_buff *nskb;
+               int header = skb_headroom(skb);
+               int copy = (PAGE_SIZE - sizeof(struct sk_buff) -
+                           sizeof(struct skb_shared_info) - header - 31)&~15;
+
+               /* Too big header? This can happen with IPv6. */
+               if (copy < 0)
+                       return;
+               if (end-start < copy)
+                       copy = end-start;
+               nskb = alloc_skb(copy+header, GFP_ATOMIC);
+               if (!nskb)
+                       return;
+               skb_reserve(nskb, header);
+               memcpy(nskb->head, skb->head, header);
+               nskb->nh.raw = nskb->head + (skb->nh.raw-skb->head);
+               nskb->h.raw = nskb->head + (skb->h.raw-skb->head);
+               nskb->mac.raw = nskb->head + (skb->mac.raw-skb->head);
+               memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
+               TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
+               __skb_insert(nskb, skb->prev, skb, skb->list);
+               tcp_set_owner_r(nskb, sk);
+
+               /* Copy data, releasing collapsed skbs. */
+               while (copy > 0) {
+                       int offset = start - TCP_SKB_CB(skb)->seq;
+                       int size = TCP_SKB_CB(skb)->end_seq - start;
+
+                       if (offset < 0) BUG();
+                       if (size > 0) {
+                               size = min(copy, size);
+                               if (skb_copy_bits(skb, offset, skb_put(nskb, size), size))
+                                       BUG();
+                               TCP_SKB_CB(nskb)->end_seq += size;
+                               copy -= size;
+                               start += size;
+                       }
+                       if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
+                               struct sk_buff *next = skb->next;
+                               __skb_unlink(skb, skb->list);
+                               __kfree_skb(skb);
+                               NET_INC_STATS_BH(TCPRcvCollapsed);
+                               skb = next;
+                               if (skb == tail || skb->h.th->syn || skb->h.th->fin)
+                                       return;
+                       }
+               }
+       }
+#endif
+}
+
+/* Collapse ofo queue. Algorithm: select contiguous sequence of skbs
+ * and tcp_collapse() them until all the queue is collapsed.
+ */
+static void tcp_collapse_ofo_queue(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb = skb_peek(&tp->out_of_order_queue);
+       struct sk_buff *head;
+       u32 start, end;
+
+       if (skb == NULL)
+               return;
+
+       start = TCP_SKB_CB(skb)->seq;
+       end = TCP_SKB_CB(skb)->end_seq;
+       head = skb;
+
+       for (;;) {
+               skb = skb->next;
+
+               /* Segment is terminated when we see gap or when
+                * we are at the end of all the queue. */
+               if (skb == (struct sk_buff *)&tp->out_of_order_queue ||
+                   after(TCP_SKB_CB(skb)->seq, end) ||
+                   before(TCP_SKB_CB(skb)->end_seq, start)) {
+                       tcp_collapse(sk, head, skb, start, end);
+                       head = skb;
+                       if (skb == (struct sk_buff *)&tp->out_of_order_queue)
+                               break;
+                       /* Start new segment */
+                       start = TCP_SKB_CB(skb)->seq;
+                       end = TCP_SKB_CB(skb)->end_seq;
+               } else {
+                       if (before(TCP_SKB_CB(skb)->seq, start))
+                               start = TCP_SKB_CB(skb)->seq;
+                       if (after(TCP_SKB_CB(skb)->end_seq, end))
+                               end = TCP_SKB_CB(skb)->end_seq;
+               }
+       }
+#endif
+}
+
+/* Reduce allocated memory if we can, trying to get
+ * the socket within its memory limits again.
+ *
+ * Return less than zero if we should start dropping frames
+ * until the socket owning process reads some of the data
+ * to stabilize the situation.
+ */
+static int tcp_prune_queue(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; 
+
+       SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
+
+       NET_INC_STATS_BH(PruneCalled);
+
+       if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf)
+               tcp_clamp_window(sk, tp);
+       else if (tcp_memory_pressure)
+               tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
+
+       tcp_collapse_ofo_queue(sk);
+       tcp_collapse(sk, sk->receive_queue.next,
+                    (struct sk_buff*)&sk->receive_queue,
+                    tp->copied_seq, tp->rcv_nxt);
+       tcp_mem_reclaim(sk);
+
+       if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf)
+               return 0;
+
+       /* Collapsing did not help, destructive actions follow.
+        * This must not ever occur. */
+
+       /* First, purge the out_of_order queue. */
+       if (skb_queue_len(&tp->out_of_order_queue)) {
+               net_statistics[smp_processor_id()*2].OfoPruned += skb_queue_len(&tp->out_of_order_queue);
+               __skb_queue_purge(&tp->out_of_order_queue);
+
+               /* Reset SACK state.  A conforming SACK implementation will
+                * do the same at a timeout based retransmit.  When a connection
+                * is in a sad state like this, we care only about integrity
+                * of the connection not performance.
+                */
+               if(tp->sack_ok)
+                       tcp_sack_reset(tp);
+               tcp_mem_reclaim(sk);
+       }
+
+       if(atomic_read(&sk->rmem_alloc) <= sk->rcvbuf)
+               return 0;
+
+       /* If we are really being abused, tell the caller to silently
+        * drop receive data on the floor.  It will get retransmitted
+        * and hopefully then we'll have sufficient space.
+        */
+       NET_INC_STATS_BH(RcvPruned);
+
+       /* Massive buffer overcommit. */
+       tp->pred_flags = 0;
+       return -1;
+#else
+  return 0;
+#endif
+}
+
+
+/* RFC2861, slow part. Adjust cwnd, after it was not full during one rto.
+ * As additional protections, we do not touch cwnd in retransmission phases,
+ * and if application hit its sndbuf limit recently.
+ */
+void tcp_cwnd_application_limited(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       if (tp->ca_state == TCP_CA_Open &&
+           sk->socket && !test_bit(SOCK_NOSPACE, &sk->socket->flags)) {
+               /* Limited by application or receiver window. */
+               u32 win_used = max(tp->snd_cwnd_used, 2U);
+               if (win_used < tp->snd_cwnd) {
+                       tp->snd_ssthresh = tcp_current_ssthresh(tp);
+                       tp->snd_cwnd = (tp->snd_cwnd+win_used)>>1;
+               }
+               tp->snd_cwnd_used = 0;
+       }
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+
+/* When incoming ACK allowed to free some skb from write_queue,
+ * we remember this event in flag tp->queue_shrunk and wake up socket
+ * on the exit from tcp input handler.
+ */
+static void tcp_new_space(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       if (tp->packets_out < tp->snd_cwnd &&
+           !(sk->userlocks&SOCK_SNDBUF_LOCK) &&
+           !tcp_memory_pressure &&
+           atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
+               int sndmem, demanded;
+
+               sndmem = tp->mss_clamp+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+               demanded = max_t(unsigned int, tp->snd_cwnd, tp->reordering+1);
+               sndmem *= 2*demanded;
+               if (sndmem > sk->sndbuf)
+                       sk->sndbuf = min(sndmem, sysctl_tcp_wmem[2]);
+               tp->snd_cwnd_stamp = tcp_time_stamp;
+       }
+
+       sk->write_space(sk);
+#endif
+}
+
+static inline void tcp_check_space(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       if (tp->queue_shrunk) {
+               tp->queue_shrunk = 0;
+               if (sk->socket && test_bit(SOCK_NOSPACE, &sk->socket->flags))
+                       tcp_new_space(sk);
+       }
+#endif
+}
+
+static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) ||
+           tcp_packets_in_flight(tp) >= tp->snd_cwnd ||
+           tcp_write_xmit(sk, tp->nonagle))
+               tcp_check_probe_timer(sk, tp);
+#endif
+}
+
+static __inline__ void tcp_data_snd_check(struct sock *sk)
+{
+#if 0
+       struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head;
+
+       if (skb != NULL)
+               __tcp_data_snd_check(sk, skb);
+       tcp_check_space(sk);
+#endif
+}
+
+/*
+ * Check if sending an ack is needed.
+ */
+static __inline__ void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+           /* More than one full frame received... */
+       if (((tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss
+            /* ... and right edge of window advances far enough.
+             * (tcp_recvmsg() will send ACK otherwise). Or...
+             */
+            && __tcp_select_window(sk) >= tp->rcv_wnd) ||
+           /* We ACK each frame or... */
+           tcp_in_quickack_mode(tp) ||
+           /* We have out of order data. */
+           (ofo_possible &&
+            skb_peek(&tp->out_of_order_queue) != NULL)) {
+               /* Then ack it now */
+               tcp_send_ack(sk);
+       } else {
+               /* Else, send delayed ack. */
+               tcp_send_delayed_ack(sk);
+       }
+#endif
+}
+
+static __inline__ void tcp_ack_snd_check(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       if (!tcp_ack_scheduled(tp)) {
+               /* We sent a data segment already. */
+               return;
+       }
+       __tcp_ack_snd_check(sk, 1);
+#endif
+}
+
+/*
+ *     This routine is only called when we have urgent data
+ *     signalled. Its the 'slow' part of tcp_urg. It could be
+ *     moved inline now as tcp_urg is only called from one
+ *     place. We handle URGent data wrong. We have to - as
+ *     BSD still doesn't use the correction from RFC961.
+ *     For 1003.1g we should support a new option TCP_STDURG to permit
+ *     either form (or just set the sysctl tcp_stdurg).
+ */
+static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       u32 ptr = ntohs(th->urg_ptr);
+
+       if (ptr && !sysctl_tcp_stdurg)
+               ptr--;
+       ptr += ntohl(th->seq);
+
+       /* Ignore urgent data that we've already seen and read. */
+       if (after(tp->copied_seq, ptr))
+               return;
+
+       /* Do not replay urg ptr.
+        *
+        * NOTE: interesting situation not covered by specs.
+        * Misbehaving sender may send urg ptr, pointing to segment,
+        * which we already have in ofo queue. We are not able to fetch
+        * such data and will stay in TCP_URG_NOTYET until will be eaten
+        * by recvmsg(). Seems, we are not obliged to handle such wicked
+        * situations. But it is worth to think about possibility of some
+        * DoSes using some hypothetical application level deadlock.
+        */
+       if (before(ptr, tp->rcv_nxt))
+               return;
+
+       /* Do we already have a newer (or duplicate) urgent pointer? */
+       if (tp->urg_data && !after(ptr, tp->urg_seq))
+               return;
+
+       /* Tell the world about our new urgent pointer. */
+       if (sk->proc != 0) {
+               if (sk->proc > 0)
+                       kill_proc(sk->proc, SIGURG, 1);
+               else
+                       kill_pg(-sk->proc, SIGURG, 1);
+               sk_wake_async(sk, 3, POLL_PRI);
+       }
+
+       /* We may be adding urgent data when the last byte read was
+        * urgent. To do this requires some care. We cannot just ignore
+        * tp->copied_seq since we would read the last urgent byte again
+        * as data, nor can we alter copied_seq until this data arrives
+        * or we break the sematics of SIOCATMARK (and thus sockatmark())
+        *
+        * NOTE. Double Dutch. Rendering to plain English: author of comment
+        * above did something sort of  send("A", MSG_OOB); send("B", MSG_OOB);
+        * and expect that both A and B disappear from stream. This is _wrong_.
+        * Though this happens in BSD with high probability, this is occasional.
+        * Any application relying on this is buggy. Note also, that fix "works"
+        * only in this artificial test. Insert some normal data between A and B and we will
+        * decline of BSD again. Verdict: it is better to remove to trap
+        * buggy users.
+        */
+       if (tp->urg_seq == tp->copied_seq && tp->urg_data &&
+           !sk->urginline &&
+           tp->copied_seq != tp->rcv_nxt) {
+               struct sk_buff *skb = skb_peek(&sk->receive_queue);
+               tp->copied_seq++;
+               if (skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq)) {
+                       __skb_unlink(skb, skb->list);
+                       __kfree_skb(skb);
+               }
+       }
+
+       tp->urg_data = TCP_URG_NOTYET;
+       tp->urg_seq = ptr;
+
+       /* Disable header prediction. */
+       tp->pred_flags = 0;
+#endif
+}
+
+/* This is the 'fast' part of urgent handling. */
+static inline void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /* Check if we get a new urgent pointer - normally not. */
+       if (th->urg)
+               tcp_check_urg(sk,th);
+
+       /* Do we wait for any urgent data? - normally not... */
+       if (tp->urg_data == TCP_URG_NOTYET) {
+               u32 ptr = tp->urg_seq - ntohl(th->seq) + (th->doff*4) - th->syn;
+
+               /* Is the urgent pointer pointing into this packet? */   
+               if (ptr < skb->len) {
+                       u8 tmp;
+                       if (skb_copy_bits(skb, ptr, &tmp, 1))
+                               BUG();
+                       tp->urg_data = TCP_URG_VALID | tmp;
+                       if (!sk->dead)
+                               sk->data_ready(sk,0);
+               }
+       }
+#endif
+}
+
+static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int chunk = skb->len - hlen;
+       int err;
+
+       local_bh_enable();
+       if (skb->ip_summed==CHECKSUM_UNNECESSARY)
+               err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
+       else
+               err = skb_copy_and_csum_datagram_iovec(skb, hlen, tp->ucopy.iov);
+
+       if (!err) {
+               tp->ucopy.len -= chunk;
+               tp->copied_seq += chunk;
+       }
+
+       local_bh_disable();
+       return err;
+#else
+  return 0;
+#endif
+}
+
+static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       int result;
+
+       if (sk->lock.users) {
+               local_bh_enable();
+               result = __tcp_checksum_complete(skb);
+               local_bh_disable();
+       } else {
+               result = __tcp_checksum_complete(skb);
+       }
+       return result;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int
+tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+               __tcp_checksum_complete_user(sk, skb);
+#else
+  return 0;
+#endif
+}
+
+/*
+ *     TCP receive function for the ESTABLISHED state. 
+ *
+ *     It is split into a fast path and a slow path. The fast path is 
+ *     disabled when:
+ *     - A zero window was announced from us - zero window probing
+ *        is only handled properly in the slow path. 
+ *     - Out of order segments arrived.
+ *     - Urgent data is expected.
+ *     - There is no buffer space left
+ *     - Unexpected TCP flags/window values/header lengths are received
+ *       (detected by checking the TCP header against pred_flags) 
+ *     - Data is sent in both directions. Fast path only supports pure senders
+ *       or pure receivers (this means either the sequence number or the ack
+ *       value must stay constant)
+ *     - Unexpected TCP option.
+ *
+ *     When these conditions are not satisfied it drops into a standard 
+ *     receive procedure patterned after RFC793 to handle all cases.
+ *     The first three cases are guaranteed by proper pred_flags setting,
+ *     the rest is checked inline. Fast processing is turned on in 
+ *     tcp_data_queue when everything is OK.
+ */
+int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+                       struct tcphdr *th, unsigned len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /*
+        *      Header prediction.
+        *      The code losely follows the one in the famous 
+        *      "30 instruction TCP receive" Van Jacobson mail.
+        *      
+        *      Van's trick is to deposit buffers into socket queue 
+        *      on a device interrupt, to call tcp_recv function
+        *      on the receive process context and checksum and copy
+        *      the buffer to user space. smart...
+        *
+        *      Our current scheme is not silly either but we take the 
+        *      extra cost of the net_bh soft interrupt processing...
+        *      We do checksum and copy also but from device to kernel.
+        */
+
+       tp->saw_tstamp = 0;
+
+       /*      pred_flags is 0xS?10 << 16 + snd_wnd
+        *      if header_predition is to be made
+        *      'S' will always be tp->tcp_header_len >> 2
+        *      '?' will be 0 for the fast path, otherwise pred_flags is 0 to
+        *  turn it off (when there are holes in the receive 
+        *       space for instance)
+        *      PSH flag is ignored.
+        */
+
+       if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags &&
+               TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+               int tcp_header_len = tp->tcp_header_len;
+
+               /* Timestamp header prediction: tcp_header_len
+                * is automatically equal to th->doff*4 due to pred_flags
+                * match.
+                */
+
+               /* Check timestamp */
+               if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) {
+                       __u32 *ptr = (__u32 *)(th + 1);
+
+                       /* No? Slow path! */
+                       if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+                                          | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
+                               goto slow_path;
+
+                       tp->saw_tstamp = 1;
+                       ++ptr; 
+                       tp->rcv_tsval = ntohl(*ptr);
+                       ++ptr;
+                       tp->rcv_tsecr = ntohl(*ptr);
+
+                       /* If PAWS failed, check it more carefully in slow path */
+                       if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0)
+                               goto slow_path;
+
+                       /* DO NOT update ts_recent here, if checksum fails
+                        * and timestamp was corrupted part, it will result
+                        * in a hung connection since we will drop all
+                        * future packets due to the PAWS test.
+                        */
+               }
+
+               if (len <= tcp_header_len) {
+                       /* Bulk data transfer: sender */
+                       if (len == tcp_header_len) {
+                               /* Predicted packet is in window by definition.
+                                * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+                                * Hence, check seq<=rcv_wup reduces to:
+                                */
+                               if (tcp_header_len ==
+                                   (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
+                                   tp->rcv_nxt == tp->rcv_wup)
+                                       tcp_store_ts_recent(tp);
+                               /* We know that such packets are checksummed
+                                * on entry.
+                                */
+                               tcp_ack(sk, skb, 0);
+                               __kfree_skb(skb); 
+                               tcp_data_snd_check(sk);
+                               return 0;
+                       } else { /* Header too small */
+                               TCP_INC_STATS_BH(TcpInErrs);
+                               goto discard;
+                       }
+               } else {
+                       int eaten = 0;
+
+                       if (tp->ucopy.task == current &&
+                           tp->copied_seq == tp->rcv_nxt &&
+                           len - tcp_header_len <= tp->ucopy.len &&
+                           sk->lock.users) {
+                               __set_current_state(TASK_RUNNING);
+
+                               if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) {
+                                       /* Predicted packet is in window by definition.
+                                        * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+                                        * Hence, check seq<=rcv_wup reduces to:
+                                        */
+                                       if (tcp_header_len ==
+                                           (sizeof(struct tcphdr) +
+                                            TCPOLEN_TSTAMP_ALIGNED) &&
+                                           tp->rcv_nxt == tp->rcv_wup)
+                                               tcp_store_ts_recent(tp);
+
+                                       __skb_pull(skb, tcp_header_len);
+                                       tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+                                       NET_INC_STATS_BH(TCPHPHitsToUser);
+                                       eaten = 1;
+                               }
+                       }
+                       if (!eaten) {
+                               if (tcp_checksum_complete_user(sk, skb))
+                                       goto csum_error;
+
+                               /* Predicted packet is in window by definition.
+                                * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+                                * Hence, check seq<=rcv_wup reduces to:
+                                */
+                               if (tcp_header_len ==
+                                   (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
+                                   tp->rcv_nxt == tp->rcv_wup)
+                                       tcp_store_ts_recent(tp);
+
+                               if ((int)skb->truesize > sk->forward_alloc)
+                                       goto step5;
+
+                               NET_INC_STATS_BH(TCPHPHits);
+
+                               /* Bulk data transfer: receiver */
+                               __skb_pull(skb,tcp_header_len);
+                               __skb_queue_tail(&sk->receive_queue, skb);
+                               tcp_set_owner_r(skb, sk);
+                               tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+                       }
+
+                       tcp_event_data_recv(sk, tp, skb);
+
+                       if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) {
+                               /* Well, only one small jumplet in fast path... */
+                               tcp_ack(sk, skb, FLAG_DATA);
+                               tcp_data_snd_check(sk);
+                               if (!tcp_ack_scheduled(tp))
+                                       goto no_ack;
+                       }
+
+                       if (eaten) {
+                               if (tcp_in_quickack_mode(tp)) {
+                                       tcp_send_ack(sk);
+                               } else {
+                                       tcp_send_delayed_ack(sk);
+                               }
+                       } else {
+                               __tcp_ack_snd_check(sk, 0);
+                       }
+
+no_ack:
+                       if (eaten)
+                               __kfree_skb(skb);
+                       else
+                               sk->data_ready(sk, 0);
+                       return 0;
+               }
+       }
+
+slow_path:
+       if (len < (th->doff<<2) || tcp_checksum_complete_user(sk, skb))
+               goto csum_error;
+
+       /*
+        * RFC1323: H1. Apply PAWS check first.
+        */
+       if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp &&
+           tcp_paws_discard(tp, skb)) {
+               if (!th->rst) {
+                       NET_INC_STATS_BH(PAWSEstabRejected);
+                       tcp_send_dupack(sk, skb);
+                       goto discard;
+               }
+               /* Resets are accepted even if PAWS failed.
+
+                  ts_recent update must be made after we are sure
+                  that the packet is in window.
+                */
+       }
+
+       /*
+        *      Standard slow path.
+        */
+
+       if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
+               /* RFC793, page 37: "In all states except SYN-SENT, all reset
+                * (RST) segments are validated by checking their SEQ-fields."
+                * And page 69: "If an incoming segment is not acceptable,
+                * an acknowledgment should be sent in reply (unless the RST bit
+                * is set, if so drop the segment and return)".
+                */
+               if (!th->rst)
+                       tcp_send_dupack(sk, skb);
+               goto discard;
+       }
+
+       if(th->rst) {
+               tcp_reset(sk);
+               goto discard;
+       }
+
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
+       if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+               TCP_INC_STATS_BH(TcpInErrs);
+               NET_INC_STATS_BH(TCPAbortOnSyn);
+               tcp_reset(sk);
+               return 1;
+       }
+
+step5:
+       if(th->ack)
+               tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+       /* Process urgent data. */
+       tcp_urg(sk, skb, th);
+
+       /* step 7: process the segment text */
+       tcp_data_queue(sk, skb);
+
+       tcp_data_snd_check(sk);
+       tcp_ack_snd_check(sk);
+       return 0;
+
+csum_error:
+       TCP_INC_STATS_BH(TcpInErrs);
+
+discard:
+       __kfree_skb(skb);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
+                                        struct tcphdr *th, unsigned len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int saved_clamp = tp->mss_clamp;
+
+       tcp_parse_options(skb, tp, 0);
+
+       if (th->ack) {
+               /* rfc793:
+                * "If the state is SYN-SENT then
+                *    first check the ACK bit
+                *      If the ACK bit is set
+                *        If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
+                *        a reset (unless the RST bit is set, if so drop
+                *        the segment and return)"
+                *
+                *  We do not send data with SYN, so that RFC-correct
+                *  test reduces to:
+                */
+               if (TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt)
+                       goto reset_and_undo;
+
+               if (tp->saw_tstamp && tp->rcv_tsecr &&
+                   !between(tp->rcv_tsecr, tp->retrans_stamp, tcp_time_stamp)) {
+                       NET_INC_STATS_BH(PAWSActiveRejected);
+                       goto reset_and_undo;
+               }
+
+               /* Now ACK is acceptable.
+                *
+                * "If the RST bit is set
+                *    If the ACK was acceptable then signal the user "error:
+                *    connection reset", drop the segment, enter CLOSED state,
+                *    delete TCB, and return."
+                */
+
+               if (th->rst) {
+                       tcp_reset(sk);
+                       goto discard;
+               }
+
+               /* rfc793:
+                *   "fifth, if neither of the SYN or RST bits is set then
+                *    drop the segment and return."
+                *
+                *    See note below!
+                *                                        --ANK(990513)
+                */
+               if (!th->syn)
+                       goto discard_and_undo;
+
+               /* rfc793:
+                *   "If the SYN bit is on ...
+                *    are acceptable then ...
+                *    (our SYN has been ACKed), change the connection
+                *    state to ESTABLISHED..."
+                */
+
+               TCP_ECN_rcv_synack(tp, th);
+
+               tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+               tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+               /* Ok.. it's good. Set up sequence numbers and
+                * move to established.
+                */
+               tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1;
+               tp->rcv_wup = TCP_SKB_CB(skb)->seq+1;
+
+               /* RFC1323: The window in SYN & SYN/ACK segments is
+                * never scaled.
+                */
+               tp->snd_wnd = ntohs(th->window);
+               tcp_init_wl(tp, TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(skb)->seq);
+
+               if (tp->wscale_ok == 0) {
+                       tp->snd_wscale = tp->rcv_wscale = 0;
+                       tp->window_clamp = min(tp->window_clamp, 65535U);
+               }
+
+               if (tp->saw_tstamp) {
+                       tp->tstamp_ok = 1;
+                       tp->tcp_header_len =
+                               sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+                       tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
+                       tcp_store_ts_recent(tp);
+               } else {
+                       tp->tcp_header_len = sizeof(struct tcphdr);
+               }
+
+               if (tp->sack_ok && sysctl_tcp_fack)
+                       tp->sack_ok |= 2;
+
+               tcp_sync_mss(sk, tp->pmtu_cookie);
+               tcp_initialize_rcv_mss(sk);
+               tcp_init_metrics(sk);
+               tcp_init_buffer_space(sk);
+
+               if (sk->keepopen)
+                       tcp_reset_keepalive_timer(sk, keepalive_time_when(tp));
+
+               if (tp->snd_wscale == 0)
+                       __tcp_fast_path_on(tp, tp->snd_wnd);
+               else
+                       tp->pred_flags = 0;
+
+               /* Remember, tcp_poll() does not lock socket!
+                * Change state from SYN-SENT only after copied_seq
+                * is initialized. */
+               tp->copied_seq = tp->rcv_nxt;
+               mb();
+               tcp_set_state(sk, TCP_ESTABLISHED);
+
+               if(!sk->dead) {
+                       sk->state_change(sk);
+                       sk_wake_async(sk, 0, POLL_OUT);
+               }
+
+               if (tp->write_pending || tp->defer_accept || tp->ack.pingpong) {
+                       /* Save one ACK. Data will be ready after
+                        * several ticks, if write_pending is set.
+                        *
+                        * It may be deleted, but with this feature tcpdumps
+                        * look so _wonderfully_ clever, that I was not able
+                        * to stand against the temptation 8)     --ANK
+                        */
+                       tcp_schedule_ack(tp);
+                       tp->ack.lrcvtime = tcp_time_stamp;
+                       tp->ack.ato = TCP_ATO_MIN;
+                       tcp_incr_quickack(tp);
+                       tcp_enter_quickack_mode(tp);
+                       tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+
+discard:
+                       __kfree_skb(skb);
+                       return 0;
+               } else {
+                       tcp_send_ack(sk);
+               }
+               return -1;
+       }
+
+       /* No ACK in the segment */
+
+       if (th->rst) {
+               /* rfc793:
+                * "If the RST bit is set
+                *
+                *      Otherwise (no ACK) drop the segment and return."
+                */
+
+               goto discard_and_undo;
+       }
+
+       /* PAWS check. */
+       if (tp->ts_recent_stamp && tp->saw_tstamp && tcp_paws_check(tp, 0))
+               goto discard_and_undo;
+
+       if (th->syn) {
+               /* We see SYN without ACK. It is attempt of
+                * simultaneous connect with crossed SYNs.
+                * Particularly, it can be connect to self.
+                */
+               tcp_set_state(sk, TCP_SYN_RECV);
+
+               if (tp->saw_tstamp) {
+                       tp->tstamp_ok = 1;
+                       tcp_store_ts_recent(tp);
+                       tp->tcp_header_len =
+                               sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+               } else {
+                       tp->tcp_header_len = sizeof(struct tcphdr);
+               }
+
+               tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+               tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
+
+               /* RFC1323: The window in SYN & SYN/ACK segments is
+                * never scaled.
+                */
+               tp->snd_wnd = ntohs(th->window);
+               tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+               tp->max_window = tp->snd_wnd;
+
+               tcp_sync_mss(sk, tp->pmtu_cookie);
+               tcp_initialize_rcv_mss(sk);
+
+               TCP_ECN_rcv_syn(tp, th);
+
+               tcp_send_synack(sk);
+#if 0
+               /* Note, we could accept data and URG from this segment.
+                * There are no obstacles to make this.
+                *
+                * However, if we ignore data in ACKless segments sometimes,
+                * we have no reasons to accept it sometimes.
+                * Also, seems the code doing it in step6 of tcp_rcv_state_process
+                * is not flawless. So, discard packet for sanity.
+                * Uncomment this return to process the data.
+                */
+               return -1;
+#else
+               goto discard;
+#endif
+       }
+       /* "fifth, if neither of the SYN or RST bits is set then
+        * drop the segment and return."
+        */
+
+discard_and_undo:
+       tcp_clear_options(tp);
+       tp->mss_clamp = saved_clamp;
+       goto discard;
+
+reset_and_undo:
+       tcp_clear_options(tp);
+       tp->mss_clamp = saved_clamp;
+       return 1;
+#else
+  return 0;
+#endif
+}
+
+
+/*
+ *     This function implements the receiving procedure of RFC 793 for
+ *     all states except ESTABLISHED and TIME_WAIT. 
+ *     It's called from both tcp_v4_rcv and tcp_v6_rcv and should be
+ *     address independent.
+ */
+       
+int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+                         struct tcphdr *th, unsigned len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int queued = 0;
+
+       tp->saw_tstamp = 0;
+
+       switch (sk->state) {
+       case TCP_CLOSE:
+               goto discard;
+
+       case TCP_LISTEN:
+               if(th->ack)
+                       return 1;
+
+               if(th->rst)
+                       goto discard;
+
+               if(th->syn) {
+                       if(tp->af_specific->conn_request(sk, skb) < 0)
+                               return 1;
+
+                       /* Now we have several options: In theory there is 
+                        * nothing else in the frame. KA9Q has an option to 
+                        * send data with the syn, BSD accepts data with the
+                        * syn up to the [to be] advertised window and 
+                        * Solaris 2.1 gives you a protocol error. For now 
+                        * we just ignore it, that fits the spec precisely 
+                        * and avoids incompatibilities. It would be nice in
+                        * future to drop through and process the data.
+                        *
+                        * Now that TTCP is starting to be used we ought to 
+                        * queue this data.
+                        * But, this leaves one open to an easy denial of
+                        * service attack, and SYN cookies can't defend
+                        * against this problem. So, we drop the data
+                        * in the interest of security over speed.
+                        */
+                       goto discard;
+               }
+               goto discard;
+
+       case TCP_SYN_SENT:
+               queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
+               if (queued >= 0)
+                       return queued;
+
+               /* Do step6 onward by hand. */
+               tcp_urg(sk, skb, th);
+               __kfree_skb(skb);
+               tcp_data_snd_check(sk);
+               return 0;
+       }
+
+       if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp &&
+           tcp_paws_discard(tp, skb)) {
+               if (!th->rst) {
+                       NET_INC_STATS_BH(PAWSEstabRejected);
+                       tcp_send_dupack(sk, skb);
+                       goto discard;
+               }
+               /* Reset is accepted even if it did not pass PAWS. */
+       }
+
+       /* step 1: check sequence number */
+       if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
+               if (!th->rst)
+                       tcp_send_dupack(sk, skb);
+               goto discard;
+       }
+
+       /* step 2: check RST bit */
+       if(th->rst) {
+               tcp_reset(sk);
+               goto discard;
+       }
+
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
+       /* step 3: check security and precedence [ignored] */
+
+       /*      step 4:
+        *
+        *      Check for a SYN in window.
+        */
+       if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+               NET_INC_STATS_BH(TCPAbortOnSyn);
+               tcp_reset(sk);
+               return 1;
+       }
+
+       /* step 5: check the ACK field */
+       if (th->ack) {
+               int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+               switch(sk->state) {
+               case TCP_SYN_RECV:
+                       if (acceptable) {
+                               tp->copied_seq = tp->rcv_nxt;
+                               mb();
+                               tcp_set_state(sk, TCP_ESTABLISHED);
+                               sk->state_change(sk);
+
+                               /* Note, that this wakeup is only for marginal
+                                * crossed SYN case. Passively open sockets
+                                * are not waked up, because sk->sleep == NULL
+                                * and sk->socket == NULL.
+                                */
+                               if (sk->socket) {
+                                       sk_wake_async(sk,0,POLL_OUT);
+                               }
+
+                               tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
+                               tp->snd_wnd = ntohs(th->window) << tp->snd_wscale;
+                               tcp_init_wl(tp, TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(skb)->seq);
+
+                               /* tcp_ack considers this ACK as duplicate
+                                * and does not calculate rtt.
+                                * Fix it at least with timestamps.
+                                */
+                               if (tp->saw_tstamp && tp->rcv_tsecr && !tp->srtt)
+                                       tcp_ack_saw_tstamp(tp, 0);
+
+                               if (tp->tstamp_ok)
+                                       tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
+
+                               tcp_init_metrics(sk);
+                               tcp_initialize_rcv_mss(sk);
+                               tcp_init_buffer_space(sk);
+                               tcp_fast_path_on(tp);
+                       } else {
+                               return 1;
+                       }
+                       break;
+
+               case TCP_FIN_WAIT1:
+                       if (tp->snd_una == tp->write_seq) {
+                               tcp_set_state(sk, TCP_FIN_WAIT2);
+                               sk->shutdown |= SEND_SHUTDOWN;
+                               dst_confirm(sk->dst_cache);
+
+                               if (!sk->dead) {
+                                       /* Wake up lingering close() */
+                                       sk->state_change(sk);
+                               } else {
+                                       int tmo;
+
+                                       if (tp->linger2 < 0 ||
+                                           (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+                                            after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
+                                               tcp_done(sk);
+                                               NET_INC_STATS_BH(TCPAbortOnData);
+                                               return 1;
+                                       }
+
+                                       tmo = tcp_fin_time(tp);
+                                       if (tmo > TCP_TIMEWAIT_LEN) {
+                                               tcp_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
+                                       } else if (th->fin || sk->lock.users) {
+                                               /* Bad case. We could lose such FIN otherwise.
+                                                * It is not a big problem, but it looks confusing
+                                                * and not so rare event. We still can lose it now,
+                                                * if it spins in bh_lock_sock(), but it is really
+                                                * marginal case.
+                                                */
+                                               tcp_reset_keepalive_timer(sk, tmo);
+                                       } else {
+                                               tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+                                               goto discard;
+                                       }
+                               }
+                       }
+                       break;
+
+               case TCP_CLOSING:
+                       if (tp->snd_una == tp->write_seq) {
+                               tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+                               goto discard;
+                       }
+                       break;
+
+               case TCP_LAST_ACK:
+                       if (tp->snd_una == tp->write_seq) {
+                               tcp_update_metrics(sk);
+                               tcp_done(sk);
+                               goto discard;
+                       }
+                       break;
+               }
+       } else
+               goto discard;
+
+       /* step 6: check the URG bit */
+       tcp_urg(sk, skb, th);
+
+       /* step 7: process the segment text */
+       switch (sk->state) {
+       case TCP_CLOSE_WAIT:
+       case TCP_CLOSING:
+       case TCP_LAST_ACK:
+               if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+                       break;
+       case TCP_FIN_WAIT1:
+       case TCP_FIN_WAIT2:
+               /* RFC 793 says to queue data in these states,
+                * RFC 1122 says we MUST send a reset. 
+                * BSD 4.4 also does reset.
+                */
+               if (sk->shutdown & RCV_SHUTDOWN) {
+                       if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+                           after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+                               NET_INC_STATS_BH(TCPAbortOnData);
+                               tcp_reset(sk);
+                               return 1;
+                       }
+               }
+               /* Fall through */
+       case TCP_ESTABLISHED: 
+               tcp_data_queue(sk, skb);
+               queued = 1;
+               break;
+       }
+
+       /* tcp_data could move socket to TIME-WAIT */
+       if (sk->state != TCP_CLOSE) {
+               tcp_data_snd_check(sk);
+               tcp_ack_snd_check(sk);
+       }
+
+       if (!queued) { 
+discard:
+               __kfree_skb(skb);
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
diff --git a/drivers/net/tcpip/transport/tcp/tcp_ipv4.c b/drivers/net/tcpip/transport/tcp/tcp_ipv4.c
new file mode 100755 (executable)
index 0000000..caddc67
--- /dev/null
@@ -0,0 +1,2523 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        transport/tcp/tcp_ipv4.c
+ * PURPOSE:     Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version:    $Id$
+ *
+ *             IPv4 specific functions
+ *
+ *
+ *             code split from:
+ *             linux/ipv4/tcp.c
+ *             linux/ipv4/tcp_input.c
+ *             linux/ipv4/tcp_output.c
+ *
+ *             See tcp.c for author information
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Changes:
+ *             David S. Miller :       New socket lookup architecture.
+ *                                     This code is dedicated to John Dyson.
+ *             David S. Miller :       Change semantics of established hash,
+ *                                     half is devoted to TIME_WAIT sockets
+ *                                     and the rest go in the other half.
+ *             Andi Kleen :            Add support for syncookies and fixed
+ *                                     some bugs: ip options weren't passed to
+ *                                     the TCP layer, missed a check for an ACK bit.
+ *             Andi Kleen :            Implemented fast path mtu discovery.
+ *                                     Fixed many serious bugs in the
+ *                                     open_request handling and moved
+ *                                     most of it into the af independent code.
+ *                                     Added tail drop and some other bugfixes.
+ *                                     Added new listen sematics.
+ *             Mike McLagan    :       Routing by source
+ *     Juan Jose Ciarlante:            ip_dynaddr bits
+ *             Andi Kleen:             various fixes.
+ *     Vitaly E. Lavrov        :       Transparent proxy revived after year coma.
+ *     Andi Kleen              :       Fix new listen.
+ *     Andi Kleen              :       Fix accept error reporting.
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/random.h>
+#include <linux/cache.h>
+#include <linux/init.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/ipv6.h>
+#include <net/inet_common.h>
+
+#include <linux/inet.h>
+#include <linux/stddef.h>
+#include <linux/ipsec.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+extern int sysctl_ip_dynaddr;
+extern int sysctl_ip_default_ttl;
+int sysctl_tcp_tw_reuse = 0;
+
+/* Check TCP sequence numbers in ICMP packets. */
+#define ICMP_MIN_LENGTH 8
+
+/* Socket used for sending RSTs */     
+#if 0
+static struct inode tcp_inode;
+static struct socket *tcp_socket=&tcp_inode.u.socket_i;
+#endif
+
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, 
+                      struct sk_buff *skb);
+
+/*
+ * ALL members must be initialised to prevent gcc-2.7.2.3 miscompilation
+ */
+#if 0
+struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = {
+       __tcp_ehash:          NULL,
+       __tcp_bhash:          NULL,
+       __tcp_bhash_size:     0,
+       __tcp_ehash_size:     0,
+       __tcp_listening_hash: { NULL, },
+       __tcp_lhash_lock:     RW_LOCK_UNLOCKED,
+       __tcp_lhash_users:    ATOMIC_INIT(0),
+       __tcp_lhash_wait:
+         __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.__tcp_lhash_wait),
+       __tcp_portalloc_lock: SPIN_LOCK_UNLOCKED
+};
+#endif
+
+/*
+ * This array holds the first and last local port number.
+ * For high-usage systems, use sysctl to change this to
+ * 32768-61000
+ */
+int sysctl_local_port_range[2] = { 1024, 4999 };
+int tcp_port_rover = (1024 - 1);
+
+static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
+                                __u32 faddr, __u16 fport)
+{
+       int h = ((laddr ^ lport) ^ (faddr ^ fport));
+       h ^= h>>16;
+       h ^= h>>8;
+       return h & (tcp_ehash_size - 1);
+}
+
+static __inline__ int tcp_sk_hashfn(struct sock *sk)
+{
+       __u32 laddr = sk->rcv_saddr;
+       __u16 lport = sk->num;
+       __u32 faddr = sk->daddr;
+       __u16 fport = sk->dport;
+
+       return tcp_hashfn(laddr, lport, faddr, fport);
+}
+
+/* Allocate and initialize a new TCP local port bind bucket.
+ * The bindhash mutex for snum's hash chain must be held here.
+ */
+struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
+                                         unsigned short snum)
+{
+#if 0
+       struct tcp_bind_bucket *tb;
+
+       tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC);
+       if(tb != NULL) {
+               tb->port = snum;
+               tb->fastreuse = 0;
+               tb->owners = NULL;
+               if((tb->next = head->chain) != NULL)
+                       tb->next->pprev = &tb->next;
+               head->chain = tb;
+               tb->pprev = &head->chain;
+       }
+       return tb;
+#else
+  return NULL;
+#endif
+}
+
+/* Caller must disable local BH processing. */
+static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+#if 0
+       struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(child->num)];
+       struct tcp_bind_bucket *tb;
+
+       spin_lock(&head->lock);
+       tb = (struct tcp_bind_bucket *)sk->prev;
+       if ((child->bind_next = tb->owners) != NULL)
+               tb->owners->bind_pprev = &child->bind_next;
+       tb->owners = child;
+       child->bind_pprev = &tb->owners;
+       child->prev = (struct sock *) tb;
+       spin_unlock(&head->lock);
+#endif
+}
+
+__inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+#if 0
+       local_bh_disable();
+       __tcp_inherit_port(sk, child);
+       local_bh_enable();
+#endif
+}
+
+static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, unsigned short snum)
+{
+#if 0
+       sk->num = snum;
+       if ((sk->bind_next = tb->owners) != NULL)
+               tb->owners->bind_pprev = &sk->bind_next;
+       tb->owners = sk;
+       sk->bind_pprev = &tb->owners;
+       sk->prev = (struct sock *) tb;
+#endif
+}
+
+static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
+{
+#if 0
+       struct sock *sk2 = tb->owners;
+       int sk_reuse = sk->reuse;
+       
+       for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+               if (sk != sk2 &&
+                   sk2->reuse <= 1 &&
+                   sk->bound_dev_if == sk2->bound_dev_if) {
+                       if (!sk_reuse   ||
+                           !sk2->reuse ||
+                           sk2->state == TCP_LISTEN) {
+                               if (!sk2->rcv_saddr     ||
+                                   !sk->rcv_saddr      ||
+                                   (sk2->rcv_saddr == sk->rcv_saddr))
+                                       break;
+                       }
+               }
+       }
+       return sk2 != NULL;
+#else
+  return 0;
+#endif
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
+{
+#if 0
+       struct tcp_bind_hashbucket *head;
+       struct tcp_bind_bucket *tb;
+       int ret;
+
+       local_bh_disable();
+       if (snum == 0) {
+               int low = sysctl_local_port_range[0];
+               int high = sysctl_local_port_range[1];
+               int remaining = (high - low) + 1;
+               int rover;
+
+               spin_lock(&tcp_portalloc_lock);
+               rover = tcp_port_rover;
+               do {    rover++;
+                       if ((rover < low) || (rover > high))
+                               rover = low;
+                       head = &tcp_bhash[tcp_bhashfn(rover)];
+                       spin_lock(&head->lock);
+                       for (tb = head->chain; tb; tb = tb->next)
+                               if (tb->port == rover)
+                                       goto next;
+                       break;
+               next:
+                       spin_unlock(&head->lock);
+               } while (--remaining > 0);
+               tcp_port_rover = rover;
+               spin_unlock(&tcp_portalloc_lock);
+
+               /* Exhausted local port range during search? */
+               ret = 1;
+               if (remaining <= 0)
+                       goto fail;
+
+               /* OK, here is the one we will use.  HEAD is
+                * non-NULL and we hold it's mutex.
+                */
+               snum = rover;
+               tb = NULL;
+       } else {
+               head = &tcp_bhash[tcp_bhashfn(snum)];
+               spin_lock(&head->lock);
+               for (tb = head->chain; tb != NULL; tb = tb->next)
+                       if (tb->port == snum)
+                               break;
+       }
+       if (tb != NULL && tb->owners != NULL) {
+               if (sk->reuse > 1)
+                       goto success;
+               if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
+                       goto success;
+               } else {
+                       ret = 1;
+                       if (tcp_bind_conflict(sk, tb))
+                               goto fail_unlock;
+               }
+       }
+       ret = 1;
+       if (tb == NULL &&
+           (tb = tcp_bucket_create(head, snum)) == NULL)
+                       goto fail_unlock;
+       if (tb->owners == NULL) {
+               if (sk->reuse && sk->state != TCP_LISTEN)
+                       tb->fastreuse = 1;
+               else
+                       tb->fastreuse = 0;
+       } else if (tb->fastreuse &&
+                  ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+               tb->fastreuse = 0;
+success:
+       if (sk->prev == NULL)
+               tcp_bind_hash(sk, tb, snum);
+       BUG_TRAP(sk->prev == (struct sock *) tb);
+       ret = 0;
+
+fail_unlock:
+       spin_unlock(&head->lock);
+fail:
+       local_bh_enable();
+       return ret;
+#else
+  return 0;
+#endif
+}
+
+/* Get rid of any references to a local port held by the
+ * given sock.
+ */
+__inline__ void __tcp_put_port(struct sock *sk)
+{
+#if 0
+       struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(sk->num)];
+       struct tcp_bind_bucket *tb;
+
+       spin_lock(&head->lock);
+       tb = (struct tcp_bind_bucket *) sk->prev;
+       if (sk->bind_next)
+               sk->bind_next->bind_pprev = sk->bind_pprev;
+       *(sk->bind_pprev) = sk->bind_next;
+       sk->prev = NULL;
+       sk->num = 0;
+       if (tb->owners == NULL) {
+               if (tb->next)
+                       tb->next->pprev = tb->pprev;
+               *(tb->pprev) = tb->next;
+               kmem_cache_free(tcp_bucket_cachep, tb);
+       }
+       spin_unlock(&head->lock);
+#endif
+}
+
+void tcp_put_port(struct sock *sk)
+{
+#if 0
+       local_bh_disable();
+       __tcp_put_port(sk);
+       local_bh_enable();
+#endif
+}
+
+/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
+ * Look, when several writers sleep and reader wakes them up, all but one
+ * immediately hit write lock and grab all the cpus. Exclusive sleep solves
+ * this, _but_ remember, it adds useless work on UP machines (wake up each
+ * exclusive lock release). It should be ifdefed really.
+ */
+
+void tcp_listen_wlock(void)
+{
+#if 0
+       write_lock(&tcp_lhash_lock);
+
+       if (atomic_read(&tcp_lhash_users)) {
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue_exclusive(&tcp_lhash_wait, &wait);
+               for (;;) {
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       if (atomic_read(&tcp_lhash_users) == 0)
+                               break;
+                       write_unlock_bh(&tcp_lhash_lock);
+                       schedule();
+                       write_lock_bh(&tcp_lhash_lock);
+               }
+
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&tcp_lhash_wait, &wait);
+       }
+#endif
+}
+
+static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
+{
+#if 0
+       struct sock **skp;
+       rwlock_t *lock;
+
+       BUG_TRAP(sk->pprev==NULL);
+       if(listen_possible && sk->state == TCP_LISTEN) {
+               skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+               lock = &tcp_lhash_lock;
+               tcp_listen_wlock();
+       } else {
+               skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))].chain;
+               lock = &tcp_ehash[sk->hashent].lock;
+               write_lock(lock);
+       }
+       if((sk->next = *skp) != NULL)
+               (*skp)->pprev = &sk->next;
+       *skp = sk;
+       sk->pprev = skp;
+       sock_prot_inc_use(sk->prot);
+       write_unlock(lock);
+       if (listen_possible && sk->state == TCP_LISTEN)
+               wake_up(&tcp_lhash_wait);
+#endif
+}
+
+static void tcp_v4_hash(struct sock *sk)
+{
+#if 0
+       if (sk->state != TCP_CLOSE) {
+               local_bh_disable();
+               __tcp_v4_hash(sk, 1);
+               local_bh_enable();
+       }
+#endif
+}
+
+void tcp_unhash(struct sock *sk)
+{
+#if 0
+       rwlock_t *lock;
+
+       if (!sk->pprev)
+               goto ende;
+
+       if (sk->state == TCP_LISTEN) {
+               local_bh_disable();
+               tcp_listen_wlock();
+               lock = &tcp_lhash_lock;
+       } else {
+               struct tcp_ehash_bucket *head = &tcp_ehash[sk->hashent];
+               lock = &head->lock;
+               write_lock_bh(&head->lock);
+       }
+
+       if(sk->pprev) {
+               if(sk->next)
+                       sk->next->pprev = sk->pprev;
+               *sk->pprev = sk->next;
+               sk->pprev = NULL;
+               sock_prot_dec_use(sk->prot);
+       }
+       write_unlock_bh(lock);
+
+ ende:
+       if (sk->state == TCP_LISTEN)
+               wake_up(&tcp_lhash_wait);
+#endif
+}
+
+/* Don't inline this cruft.  Here are some nice properties to
+ * exploit here.  The BSD API does not allow a listening TCP
+ * to specify the remote port nor the remote address for the
+ * connection.  So always assume those are both wildcarded
+ * during the search since they can never be otherwise.
+ */
+static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr, unsigned short hnum, int dif)
+{
+#if 0
+       struct sock *result = NULL;
+       int score, hiscore;
+
+       hiscore=0;
+       for(; sk; sk = sk->next) {
+               if(sk->num == hnum) {
+                       __u32 rcv_saddr = sk->rcv_saddr;
+
+                       score = 1;
+                       if(rcv_saddr) {
+                               if (rcv_saddr != daddr)
+                                       continue;
+                               score++;
+                       }
+                       if (sk->bound_dev_if) {
+                               if (sk->bound_dev_if != dif)
+                                       continue;
+                               score++;
+                       }
+                       if (score == 3)
+                               return sk;
+                       if (score > hiscore) {
+                               hiscore = score;
+                               result = sk;
+                       }
+               }
+       }
+       return result;
+#else
+  return NULL;
+#endif
+}
+
+/* Optimize the common listener case. */
+__inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif)
+{
+#if 0
+       struct sock *sk;
+
+       read_lock(&tcp_lhash_lock);
+       sk = tcp_listening_hash[tcp_lhashfn(hnum)];
+       if (sk) {
+               if (sk->num == hnum &&
+                   sk->next == NULL &&
+                   (!sk->rcv_saddr || sk->rcv_saddr == daddr) &&
+                   !sk->bound_dev_if)
+                       goto sherry_cache;
+               sk = __tcp_v4_lookup_listener(sk, daddr, hnum, dif);
+       }
+       if (sk) {
+sherry_cache:
+               sock_hold(sk);
+       }
+       read_unlock(&tcp_lhash_lock);
+       return sk;
+#else
+  return NULL;
+#endif
+}
+
+/* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * Local BH must be disabled here.
+ */
+
+static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport,
+                                                      u32 daddr, u16 hnum, int dif)
+{
+#if 0
+       struct tcp_ehash_bucket *head;
+       TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
+       __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
+       struct sock *sk;
+       int hash;
+
+       /* Optimize here for direct hit, only listening connections can
+        * have wildcards anyways.
+        */
+       hash = tcp_hashfn(daddr, hnum, saddr, sport);
+       head = &tcp_ehash[hash];
+       read_lock(&head->lock);
+       for(sk = head->chain; sk; sk = sk->next) {
+               if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+                       goto hit; /* You sunk my battleship! */
+       }
+
+       /* Must check for a TIME_WAIT'er before going to listener hash. */
+       for(sk = (head + tcp_ehash_size)->chain; sk; sk = sk->next)
+               if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+                       goto hit;
+       read_unlock(&head->lock);
+
+       return NULL;
+
+hit:
+       sock_hold(sk);
+       read_unlock(&head->lock);
+       return sk;
+#else
+  return NULL;
+#endif
+}
+
+static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
+                                          u32 daddr, u16 hnum, int dif)
+{
+#if 0
+       struct sock *sk;
+
+       sk = __tcp_v4_lookup_established(saddr, sport, daddr, hnum, dif);
+
+       if (sk)
+               return sk;
+               
+       return tcp_v4_lookup_listener(daddr, hnum, dif);
+#else
+  return NULL;
+#endif
+}
+
+__inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
+{
+#if 0
+       struct sock *sk;
+
+       local_bh_disable();
+       sk = __tcp_v4_lookup(saddr, sport, daddr, ntohs(dport), dif);
+       local_bh_enable();
+
+       return sk;
+#else
+  return NULL;
+#endif
+}
+
+static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       return secure_tcp_sequence_number(skb->nh.iph->daddr,
+                                         skb->nh.iph->saddr,
+                                         skb->h.th->dest,
+                                         skb->h.th->source);
+#else
+  return 0;
+#endif
+}
+
+/* called with local bh disabled */
+static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
+                                     struct tcp_tw_bucket **twp)
+{
+#if 0
+       u32 daddr = sk->rcv_saddr;
+       u32 saddr = sk->daddr;
+       int dif = sk->bound_dev_if;
+       TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
+       __u32 ports = TCP_COMBINED_PORTS(sk->dport, lport);
+       int hash = tcp_hashfn(daddr, lport, saddr, sk->dport);
+       struct tcp_ehash_bucket *head = &tcp_ehash[hash];
+       struct sock *sk2, **skp;
+       struct tcp_tw_bucket *tw;
+
+       write_lock(&head->lock);
+
+       /* Check TIME-WAIT sockets first. */
+       for(skp = &(head + tcp_ehash_size)->chain; (sk2=*skp) != NULL;
+           skp = &sk2->next) {
+               tw = (struct tcp_tw_bucket*)sk2;
+
+               if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+                       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+                       /* With PAWS, it is safe from the viewpoint
+                          of data integrity. Even without PAWS it
+                          is safe provided sequence spaces do not
+                          overlap i.e. at data rates <= 80Mbit/sec.
+
+                          Actually, the idea is close to VJ's one,
+                          only timestamp cache is held not per host,
+                          but per port pair and TW bucket is used
+                          as state holder.
+
+                          If TW bucket has been already destroyed we
+                          fall back to VJ's scheme and use initial
+                          timestamp retrieved from peer table.
+                        */
+                       if (tw->ts_recent_stamp &&
+                           (!twp || (sysctl_tcp_tw_reuse &&
+                                     xtime.tv_sec - tw->ts_recent_stamp > 1))) {
+                               if ((tp->write_seq = tw->snd_nxt+65535+2) == 0)
+                                       tp->write_seq = 1;
+                               tp->ts_recent = tw->ts_recent;
+                               tp->ts_recent_stamp = tw->ts_recent_stamp;
+                               sock_hold(sk2);
+                               skp = &head->chain;
+                               goto unique;
+                       } else
+                               goto not_unique;
+               }
+       }
+       tw = NULL;
+
+       /* And established part... */
+       for(skp = &head->chain; (sk2=*skp)!=NULL; skp = &sk2->next) {
+               if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+                       goto not_unique;
+       }
+
+unique:
+       /* Must record num and sport now. Otherwise we will see
+        * in hash table socket with a funny identity. */
+       sk->num = lport;
+       sk->sport = htons(lport);
+       BUG_TRAP(sk->pprev==NULL);
+       if ((sk->next = *skp) != NULL)
+               (*skp)->pprev = &sk->next;
+
+       *skp = sk;
+       sk->pprev = skp;
+       sk->hashent = hash;
+       sock_prot_inc_use(sk->prot);
+       write_unlock(&head->lock);
+
+       if (twp) {
+               *twp = tw;
+               NET_INC_STATS_BH(TimeWaitRecycled);
+       } else if (tw) {
+               /* Silly. Should hash-dance instead... */
+               tcp_tw_deschedule(tw);
+               tcp_timewait_kill(tw);
+               NET_INC_STATS_BH(TimeWaitRecycled);
+
+               tcp_tw_put(tw);
+       }
+
+       return 0;
+
+not_unique:
+       write_unlock(&head->lock);
+       return -EADDRNOTAVAIL;
+#else
+  return 0;
+#endif
+}
+
+/*
+ * Bind a port for a connect operation and hash it.
+ */
+static int tcp_v4_hash_connect(struct sock *sk)
+{
+#if 0
+       unsigned short snum = sk->num;
+       struct tcp_bind_hashbucket *head;
+       struct tcp_bind_bucket *tb;
+
+       if (snum == 0) {
+               int rover;
+               int low = sysctl_local_port_range[0];
+               int high = sysctl_local_port_range[1];
+               int remaining = (high - low) + 1;
+               struct tcp_tw_bucket *tw = NULL;
+
+               local_bh_disable();
+
+               /* TODO. Actually it is not so bad idea to remove
+                * tcp_portalloc_lock before next submission to Linus.
+                * As soon as we touch this place at all it is time to think.
+                *
+                * Now it protects single _advisory_ variable tcp_port_rover,
+                * hence it is mostly useless.
+                * Code will work nicely if we just delete it, but
+                * I am afraid in contented case it will work not better or
+                * even worse: another cpu just will hit the same bucket
+                * and spin there.
+                * So some cpu salt could remove both contention and
+                * memory pingpong. Any ideas how to do this in a nice way?
+                */
+               spin_lock(&tcp_portalloc_lock);
+               rover = tcp_port_rover;
+
+               do {
+                       rover++;
+                       if ((rover < low) || (rover > high))
+                               rover = low;
+                       head = &tcp_bhash[tcp_bhashfn(rover)];
+                       spin_lock(&head->lock);         
+
+                       /* Does not bother with rcv_saddr checks,
+                        * because the established check is already
+                        * unique enough.
+                        */
+                       for (tb = head->chain; tb; tb = tb->next) {
+                               if (tb->port == rover) {
+                                       BUG_TRAP(tb->owners != NULL);
+                                       if (tb->fastreuse >= 0)
+                                               goto next_port;
+                                       if (!__tcp_v4_check_established(sk, rover, &tw))
+                                               goto ok;
+                                       goto next_port;
+                               }
+                       }
+
+                       tb = tcp_bucket_create(head, rover);
+                       if (!tb) {
+                               spin_unlock(&head->lock);
+                               break;
+                       }
+                       tb->fastreuse = -1;
+                       goto ok;
+
+               next_port:
+                       spin_unlock(&head->lock);
+               } while (--remaining > 0);
+               tcp_port_rover = rover;
+               spin_unlock(&tcp_portalloc_lock);
+
+               local_bh_enable();
+
+               return -EADDRNOTAVAIL;
+
+       ok:
+               /* All locks still held and bhs disabled */
+               tcp_port_rover = rover;
+               spin_unlock(&tcp_portalloc_lock);
+
+               tcp_bind_hash(sk, tb, rover);
+               if (!sk->pprev) {
+                       sk->sport = htons(rover);
+                       __tcp_v4_hash(sk, 0);
+               }
+               spin_unlock(&head->lock);
+
+               if (tw) {
+                       tcp_tw_deschedule(tw);
+                       tcp_timewait_kill(tw);
+                       tcp_tw_put(tw);
+               }
+
+               local_bh_enable();
+               return 0;
+       }
+
+       head  = &tcp_bhash[tcp_bhashfn(snum)];
+       tb  = (struct tcp_bind_bucket *)sk->prev;
+       spin_lock_bh(&head->lock);
+       if (tb->owners == sk && sk->bind_next == NULL) {
+               __tcp_v4_hash(sk, 0);
+               spin_unlock_bh(&head->lock);
+               return 0;
+       } else {
+               int ret;
+               spin_unlock(&head->lock);
+               /* No definite answer... Walk to established hash table */
+               ret = __tcp_v4_check_established(sk, snum, NULL);
+               local_bh_enable();
+               return ret;
+       }
+#else
+  return 0;
+#endif
+}
+
+/* This will initiate an outgoing connection. */
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
+       struct rtable *rt;
+       u32 daddr, nexthop;
+       int tmp;
+       int err;
+
+       if (addr_len < sizeof(struct sockaddr_in))
+               return(-EINVAL);
+
+       if (usin->sin_family != AF_INET)
+               return(-EAFNOSUPPORT);
+
+       nexthop = daddr = usin->sin_addr.s_addr;
+       if (sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr) {
+               if (daddr == 0)
+                       return -EINVAL;
+               nexthop = sk->protinfo.af_inet.opt->faddr;
+       }
+
+       tmp = ip_route_connect(&rt, nexthop, sk->saddr,
+                              RT_CONN_FLAGS(sk), sk->bound_dev_if);
+       if (tmp < 0)
+               return tmp;
+
+       if (rt->rt_flags&(RTCF_MULTICAST|RTCF_BROADCAST)) {
+               ip_rt_put(rt);
+               return -ENETUNREACH;
+       }
+
+       __sk_dst_set(sk, &rt->u.dst);
+       sk->route_caps = rt->u.dst.dev->features;
+
+       if (!sk->protinfo.af_inet.opt || !sk->protinfo.af_inet.opt->srr)
+               daddr = rt->rt_dst;
+
+       if (!sk->saddr)
+               sk->saddr = rt->rt_src;
+       sk->rcv_saddr = sk->saddr;
+
+       if (tp->ts_recent_stamp && sk->daddr != daddr) {
+               /* Reset inherited state */
+               tp->ts_recent = 0;
+               tp->ts_recent_stamp = 0;
+               tp->write_seq = 0;
+       }
+
+       if (sysctl_tcp_tw_recycle &&
+           !tp->ts_recent_stamp &&
+           rt->rt_dst == daddr) {
+               struct inet_peer *peer = rt_get_peer(rt);
+
+               /* VJ's idea. We save last timestamp seen from
+                * the destination in peer table, when entering state TIME-WAIT
+                * and initialize ts_recent from it, when trying new connection.
+                */
+
+               if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
+                       tp->ts_recent_stamp = peer->tcp_ts_stamp;
+                       tp->ts_recent = peer->tcp_ts;
+               }
+       }
+
+       sk->dport = usin->sin_port;
+       sk->daddr = daddr;
+
+       tp->ext_header_len = 0;
+       if (sk->protinfo.af_inet.opt)
+               tp->ext_header_len = sk->protinfo.af_inet.opt->optlen;
+
+       tp->mss_clamp = 536;
+
+       /* Socket identity is still unknown (sport may be zero).
+        * However we set state to SYN-SENT and not releasing socket
+        * lock select source port, enter ourselves into the hash tables and
+        * complete initalization after this.
+        */
+       tcp_set_state(sk, TCP_SYN_SENT);
+       err = tcp_v4_hash_connect(sk);
+       if (err)
+               goto failure;
+
+       if (!tp->write_seq)
+               tp->write_seq = secure_tcp_sequence_number(sk->saddr, sk->daddr,
+                                                          sk->sport, usin->sin_port);
+
+       sk->protinfo.af_inet.id = tp->write_seq^jiffies;
+
+       err = tcp_connect(sk);
+       if (err)
+               goto failure;
+
+       return 0;
+
+failure:
+       tcp_set_state(sk, TCP_CLOSE);
+       __sk_dst_reset(sk);
+       sk->route_caps = 0;
+       sk->dport = 0;
+       return err;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ int tcp_v4_iif(struct sk_buff *skb)
+{
+#if 0
+       return ((struct rtable*)skb->dst)->rt_iif;
+#else
+  return 0;
+#endif
+}
+
+static __inline__ unsigned tcp_v4_synq_hash(u32 raddr, u16 rport)
+{
+#if 0
+       unsigned h = raddr ^ rport;
+       h ^= h>>16;
+       h ^= h>>8;
+       return h&(TCP_SYNQ_HSIZE-1);
+#else
+  return 0;
+#endif
+}
+
+static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, 
+                                             struct open_request ***prevp,
+                                             __u16 rport,
+                                             __u32 raddr, __u32 laddr)
+{
+#if 0
+       struct tcp_listen_opt *lopt = tp->listen_opt;
+       struct open_request *req, **prev;  
+
+       for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport)];
+            (req = *prev) != NULL;
+            prev = &req->dl_next) {
+               if (req->rmt_port == rport &&
+                   req->af.v4_req.rmt_addr == raddr &&
+                   req->af.v4_req.loc_addr == laddr &&
+                   TCP_INET_FAMILY(req->class->family)) {
+                       BUG_TRAP(req->sk == NULL);
+                       *prevp = prev;
+                       return req; 
+               }
+       }
+
+       return NULL;
+#else
+  return NULL;
+#endif
+}
+
+static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct tcp_listen_opt *lopt = tp->listen_opt;
+       unsigned h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port);
+
+       req->expires = jiffies + TCP_TIMEOUT_INIT;
+       req->retrans = 0;
+       req->sk = NULL;
+       req->dl_next = lopt->syn_table[h];
+
+       write_lock(&tp->syn_wait_lock);
+       lopt->syn_table[h] = req;
+       write_unlock(&tp->syn_wait_lock);
+
+       tcp_synq_added(sk);
+#endif
+}
+
+
+/* 
+ * This routine does path mtu discovery as defined in RFC1191.
+ */
+static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip, unsigned mtu)
+{
+#if 0
+       struct dst_entry *dst;
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
+        * send out by Linux are always <576bytes so they should go through
+        * unfragmented).
+        */
+       if (sk->state == TCP_LISTEN)
+               return; 
+
+       /* We don't check in the destentry if pmtu discovery is forbidden
+        * on this route. We just assume that no packet_to_big packets
+        * are send back when pmtu discovery is not active.
+        * There is a small race when the user changes this flag in the
+        * route, but I think that's acceptable.
+        */
+       if ((dst = __sk_dst_check(sk, 0)) == NULL)
+               return;
+
+       ip_rt_update_pmtu(dst, mtu);
+
+       /* Something is about to be wrong... Remember soft error
+        * for the case, if this connection will not able to recover.
+        */
+       if (mtu < dst->pmtu && ip_dont_fragment(sk, dst))
+               sk->err_soft = EMSGSIZE;
+
+       if (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT &&
+           tp->pmtu_cookie > dst->pmtu) {
+               tcp_sync_mss(sk, dst->pmtu);
+
+               /* Resend the TCP packet because it's  
+                * clear that the old packet has been
+                * dropped. This is the new "fast" path mtu
+                * discovery.
+                */
+               tcp_simple_retransmit(sk);
+       } /* else let the usual retransmit timer handle it */
+#endif
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition.  If err < 0 then the socket should
+ * be closed and the error returned to the user.  If err > 0
+ * it's just the icmp type << 8 | icmp code.  After adjustment
+ * header points to the first 8 bytes of the tcp header.  We need
+ * to find the appropriate port.
+ *
+ * The locking strategy used here is very "optimistic". When
+ * someone else accesses the socket the ICMP is just dropped
+ * and for some paths there is no check at all.
+ * A more general error queue to queue errors for later handling
+ * is probably better.
+ *
+ */
+
+void tcp_v4_err(struct sk_buff *skb, u32 info)
+{
+#if 0
+       struct iphdr *iph = (struct iphdr*)skb->data;
+       struct tcphdr *th = (struct tcphdr*)(skb->data+(iph->ihl<<2));
+       struct tcp_opt *tp;
+       int type = skb->h.icmph->type;
+       int code = skb->h.icmph->code;
+       struct sock *sk;
+       __u32 seq;
+       int err;
+
+       if (skb->len < (iph->ihl << 2) + 8) {
+               ICMP_INC_STATS_BH(IcmpInErrors); 
+               return;
+       }
+
+       sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, tcp_v4_iif(skb));
+       if (sk == NULL) {
+               ICMP_INC_STATS_BH(IcmpInErrors);
+               return;
+       }
+       if (sk->state == TCP_TIME_WAIT) {
+               tcp_tw_put((struct tcp_tw_bucket*)sk);
+               return;
+       }
+
+       bh_lock_sock(sk);
+       /* If too many ICMPs get dropped on busy
+        * servers this needs to be solved differently.
+        */
+       if (sk->lock.users != 0)
+               NET_INC_STATS_BH(LockDroppedIcmps);
+
+       if (sk->state == TCP_CLOSE)
+               goto out;
+
+       tp = &sk->tp_pinfo.af_tcp;
+       seq = ntohl(th->seq);
+       if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
+               NET_INC_STATS(OutOfWindowIcmps);
+               goto out;
+       }
+
+       switch (type) {
+       case ICMP_SOURCE_QUENCH:
+               /* This is deprecated, but if someone generated it,
+                * we have no reasons to ignore it.
+                */
+               if (sk->lock.users == 0)
+                       tcp_enter_cwr(tp);
+               goto out;
+       case ICMP_PARAMETERPROB:
+               err = EPROTO;
+               break; 
+       case ICMP_DEST_UNREACH:
+               if (code > NR_ICMP_UNREACH)
+                       goto out;
+
+               if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+                       if (sk->lock.users == 0)
+                               do_pmtu_discovery(sk, iph, info);
+                       goto out;
+               }
+
+               err = icmp_err_convert[code].errno;
+               break;
+       case ICMP_TIME_EXCEEDED:
+               err = EHOSTUNREACH;
+               break;
+       default:
+               goto out;
+       }
+
+       switch (sk->state) {
+               struct open_request *req, **prev;
+       case TCP_LISTEN:
+               if (sk->lock.users != 0)
+                       goto out;
+
+               req = tcp_v4_search_req(tp, &prev,
+                                       th->dest,
+                                       iph->daddr, iph->saddr); 
+               if (!req)
+                       goto out;
+
+               /* ICMPs are not backlogged, hence we cannot get
+                  an established socket here.
+                */
+               BUG_TRAP(req->sk == NULL);
+
+               if (seq != req->snt_isn) {
+                       NET_INC_STATS_BH(OutOfWindowIcmps);
+                       goto out;
+               }
+
+               /* 
+                * Still in SYN_RECV, just remove it silently.
+                * There is no good way to pass the error to the newly
+                * created socket, and POSIX does not want network
+                * errors returned from accept(). 
+                */ 
+               tcp_synq_drop(sk, req, prev);
+               goto out;
+
+       case TCP_SYN_SENT:
+       case TCP_SYN_RECV:  /* Cannot happen.
+                              It can f.e. if SYNs crossed.
+                            */ 
+               if (sk->lock.users == 0) {
+                       TCP_INC_STATS_BH(TcpAttemptFails);
+                       sk->err = err;
+
+                       sk->error_report(sk);
+
+                       tcp_done(sk);
+               } else {
+                       sk->err_soft = err;
+               }
+               goto out;
+       }
+
+       /* If we've already connected we will keep trying
+        * until we time out, or the user gives up.
+        *
+        * rfc1122 4.2.3.9 allows to consider as hard errors
+        * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
+        * but it is obsoleted by pmtu discovery).
+        *
+        * Note, that in modern internet, where routing is unreliable
+        * and in each dark corner broken firewalls sit, sending random
+        * errors ordered by their masters even this two messages finally lose
+        * their original sense (even Linux sends invalid PORT_UNREACHs)
+        *
+        * Now we are in compliance with RFCs.
+        *                                                      --ANK (980905)
+        */
+
+       if (sk->lock.users == 0 && sk->protinfo.af_inet.recverr) {
+               sk->err = err;
+               sk->error_report(sk);
+       } else  { /* Only an error on timeout */
+               sk->err_soft = err;
+       }
+
+out:
+       bh_unlock_sock(sk);
+       sock_put(sk);
+#endif
+}
+
+/* This routine computes an IPv4 TCP checksum. */
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, 
+                      struct sk_buff *skb)
+{
+#if 0
+       if (skb->ip_summed == CHECKSUM_HW) {
+               th->check = ~tcp_v4_check(th, len, sk->saddr, sk->daddr, 0);
+               skb->csum = offsetof(struct tcphdr, check);
+       } else {
+               th->check = tcp_v4_check(th, len, sk->saddr, sk->daddr,
+                                        csum_partial((char *)th, th->doff<<2, skb->csum));
+       }
+#endif
+}
+
+/*
+ *     This routine will send an RST to the other tcp.
+ *
+ *     Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
+ *                   for reset.
+ *     Answer: if a packet caused RST, it is not for a socket
+ *             existing in our system, if it is matched to a socket,
+ *             it is just duplicate segment or bug in other side's TCP.
+ *             So that we build reply only basing on parameters
+ *             arrived with segment.
+ *     Exception: precedence violation. We do not implement it in any case.
+ */
+
+static void tcp_v4_send_reset(struct sk_buff *skb)
+{
+#if 0
+       struct tcphdr *th = skb->h.th;
+       struct tcphdr rth;
+       struct ip_reply_arg arg;
+
+       /* Never send a reset in response to a reset. */
+       if (th->rst)
+               return;
+
+       if (((struct rtable*)skb->dst)->rt_type != RTN_LOCAL)
+               return;
+
+       /* Swap the send and the receive. */
+       memset(&rth, 0, sizeof(struct tcphdr)); 
+       rth.dest = th->source;
+       rth.source = th->dest; 
+       rth.doff = sizeof(struct tcphdr)/4;
+       rth.rst = 1;
+
+       if (th->ack) {
+               rth.seq = th->ack_seq;
+       } else {
+               rth.ack = 1;
+               rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
+                                   + skb->len - (th->doff<<2));
+       }
+
+       memset(&arg, 0, sizeof arg); 
+       arg.iov[0].iov_base = (unsigned char *)&rth; 
+       arg.iov[0].iov_len  = sizeof rth;
+       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, 
+                                     skb->nh.iph->saddr, /*XXX*/
+                                     sizeof(struct tcphdr),
+                                     IPPROTO_TCP,
+                                     0); 
+       arg.n_iov = 1;
+       arg.csumoffset = offsetof(struct tcphdr, check) / 2; 
+
+       tcp_socket->sk->protinfo.af_inet.ttl = sysctl_ip_default_ttl;
+       ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
+
+       TCP_INC_STATS_BH(TcpOutSegs);
+       TCP_INC_STATS_BH(TcpOutRsts);
+#endif
+}
+
+/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
+   outside socket context is ugly, certainly. What can I do?
+ */
+
+static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
+{
+#if 0
+       struct tcphdr *th = skb->h.th;
+       struct {
+               struct tcphdr th;
+               u32 tsopt[3];
+       } rep;
+       struct ip_reply_arg arg;
+
+       memset(&rep.th, 0, sizeof(struct tcphdr));
+       memset(&arg, 0, sizeof arg);
+
+       arg.iov[0].iov_base = (unsigned char *)&rep; 
+       arg.iov[0].iov_len  = sizeof(rep.th);
+       arg.n_iov = 1;
+       if (ts) {
+               rep.tsopt[0] = htonl((TCPOPT_NOP << 24) |
+                                    (TCPOPT_NOP << 16) |
+                                    (TCPOPT_TIMESTAMP << 8) |
+                                    TCPOLEN_TIMESTAMP);
+               rep.tsopt[1] = htonl(tcp_time_stamp);
+               rep.tsopt[2] = htonl(ts);
+               arg.iov[0].iov_len = sizeof(rep);
+       }
+
+       /* Swap the send and the receive. */
+       rep.th.dest = th->source;
+       rep.th.source = th->dest; 
+       rep.th.doff = arg.iov[0].iov_len/4;
+       rep.th.seq = htonl(seq);
+       rep.th.ack_seq = htonl(ack);
+       rep.th.ack = 1;
+       rep.th.window = htons(win);
+
+       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, 
+                                     skb->nh.iph->saddr, /*XXX*/
+                                     arg.iov[0].iov_len,
+                                     IPPROTO_TCP,
+                                     0);
+       arg.csumoffset = offsetof(struct tcphdr, check) / 2; 
+
+       ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
+
+       TCP_INC_STATS_BH(TcpOutSegs);
+#endif
+}
+
+static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+
+       tcp_v4_send_ack(skb, tw->snd_nxt, tw->rcv_nxt,
+                       tw->rcv_wnd>>tw->rcv_wscale, tw->ts_recent);
+
+       tcp_tw_put(tw);
+#endif
+}
+
+static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req)
+{
+#if 0
+       tcp_v4_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd,
+                       req->ts_recent);
+#endif
+}
+
+static struct dst_entry* tcp_v4_route_req(struct sock *sk, struct open_request *req)
+{
+#if 0
+       struct rtable *rt;
+       struct ip_options *opt;
+
+       opt = req->af.v4_req.opt;
+       if(ip_route_output(&rt, ((opt && opt->srr) ?
+                                opt->faddr :
+                                req->af.v4_req.rmt_addr),
+                          req->af.v4_req.loc_addr,
+                          RT_CONN_FLAGS(sk), sk->bound_dev_if)) {
+               IP_INC_STATS_BH(IpOutNoRoutes);
+               return NULL;
+       }
+       if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
+               ip_rt_put(rt);
+               IP_INC_STATS_BH(IpOutNoRoutes);
+               return NULL;
+       }
+       return &rt->u.dst;
+#else
+  return NULL;
+#endif
+}
+
+/*
+ *     Send a SYN-ACK after having received an ACK. 
+ *     This still operates on a open_request only, not on a big
+ *     socket.
+ */ 
+static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
+                             struct dst_entry *dst)
+{
+#if 0
+       int err = -1;
+       struct sk_buff * skb;
+
+       /* First, grab a route. */
+       if (dst == NULL &&
+           (dst = tcp_v4_route_req(sk, req)) == NULL)
+               goto out;
+
+       skb = tcp_make_synack(sk, dst, req);
+
+       if (skb) {
+               struct tcphdr *th = skb->h.th;
+
+               th->check = tcp_v4_check(th, skb->len,
+                                        req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr,
+                                        csum_partial((char *)th, skb->len, skb->csum));
+
+               err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
+                                           req->af.v4_req.rmt_addr, req->af.v4_req.opt);
+               if (err == NET_XMIT_CN)
+                       err = 0;
+       }
+
+out:
+       dst_release(dst);
+       return err;
+#else
+  return 0;
+#endif
+}
+
+/*
+ *     IPv4 open_request destructor.
+ */ 
+static void tcp_v4_or_free(struct open_request *req)
+{
+#if 0
+       if (req->af.v4_req.opt)
+               kfree(req->af.v4_req.opt);
+#endif
+}
+
+static inline void syn_flood_warning(struct sk_buff *skb)
+{
+#if 0
+       static unsigned long warntime;
+       
+       if (jiffies - warntime > HZ*60) {
+               warntime = jiffies;
+               printk(KERN_INFO 
+                      "possible SYN flooding on port %d. Sending cookies.\n",  
+                      ntohs(skb->h.th->dest));
+       }
+#endif
+}
+
+/* 
+ * Save and compile IPv4 options into the open_request if needed. 
+ */
+static inline struct ip_options * 
+tcp_v4_save_options(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct ip_options *opt = &(IPCB(skb)->opt);
+       struct ip_options *dopt = NULL; 
+
+       if (opt && opt->optlen) {
+               int opt_size = optlength(opt); 
+               dopt = kmalloc(opt_size, GFP_ATOMIC);
+               if (dopt) {
+                       if (ip_options_echo(dopt, skb)) {
+                               kfree(dopt);
+                               dopt = NULL;
+                       }
+               }
+       }
+       return dopt;
+#else
+  return NULL;
+#endif
+}
+
+/* 
+ * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
+ * One SYN_RECV socket costs about 80bytes on a 32bit machine.
+ * It would be better to replace it with a global counter for all sockets
+ * but then some measure against one socket starving all other sockets
+ * would be needed.
+ *
+ * It was 128 by default. Experiments with real servers show, that
+ * it is absolutely not enough even at 100conn/sec. 256 cures most
+ * of problems. This value is adjusted to 128 for very small machines
+ * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
+ * Further increasing requires to change hash table size.
+ */
+int sysctl_max_syn_backlog = 256; 
+
+#if 0
+struct or_calltable or_ipv4 = {
+       PF_INET,
+       tcp_v4_send_synack,
+       tcp_v4_or_send_ack,
+       tcp_v4_or_free,
+       tcp_v4_send_reset
+};
+#endif
+
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_opt tp;
+       struct open_request *req;
+       __u32 saddr = skb->nh.iph->saddr;
+       __u32 daddr = skb->nh.iph->daddr;
+       __u32 isn = TCP_SKB_CB(skb)->when;
+       struct dst_entry *dst = NULL;
+#ifdef CONFIG_SYN_COOKIES
+       int want_cookie = 0;
+#else
+#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
+#endif
+
+       /* Never answer to SYNs send to broadcast or multicast */
+       if (((struct rtable *)skb->dst)->rt_flags & 
+           (RTCF_BROADCAST|RTCF_MULTICAST))
+               goto drop; 
+
+       /* TW buckets are converted to open requests without
+        * limitations, they conserve resources and peer is
+        * evidently real one.
+        */
+       if (tcp_synq_is_full(sk) && !isn) {
+#ifdef CONFIG_SYN_COOKIES
+               if (sysctl_tcp_syncookies) {
+                       want_cookie = 1; 
+               } else
+#endif
+               goto drop;
+       }
+
+       /* Accept backlog is full. If we have already queued enough
+        * of warm entries in syn queue, drop request. It is better than
+        * clogging syn queue with openreqs with exponentially increasing
+        * timeout.
+        */
+       if (tcp_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+               goto drop;
+
+       req = tcp_openreq_alloc();
+       if (req == NULL)
+               goto drop;
+
+       tcp_clear_options(&tp);
+       tp.mss_clamp = 536;
+       tp.user_mss = sk->tp_pinfo.af_tcp.user_mss;
+
+       tcp_parse_options(skb, &tp, 0);
+
+       if (want_cookie) {
+               tcp_clear_options(&tp);
+               tp.saw_tstamp = 0;
+       }
+
+       if (tp.saw_tstamp && tp.rcv_tsval == 0) {
+               /* Some OSes (unknown ones, but I see them on web server, which
+                * contains information interesting only for windows'
+                * users) do not send their stamp in SYN. It is easy case.
+                * We simply do not advertise TS support.
+                */
+               tp.saw_tstamp = 0;
+               tp.tstamp_ok = 0;
+       }
+       tp.tstamp_ok = tp.saw_tstamp;
+
+       tcp_openreq_init(req, &tp, skb);
+
+       req->af.v4_req.loc_addr = daddr;
+       req->af.v4_req.rmt_addr = saddr;
+       req->af.v4_req.opt = tcp_v4_save_options(sk, skb);
+       req->class = &or_ipv4;
+       if (!want_cookie)
+               TCP_ECN_create_request(req, skb->h.th);
+
+       if (want_cookie) {
+#ifdef CONFIG_SYN_COOKIES
+               syn_flood_warning(skb);
+#endif
+               isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+       } else if (isn == 0) {
+               struct inet_peer *peer = NULL;
+
+               /* VJ's idea. We save last timestamp seen
+                * from the destination in peer table, when entering
+                * state TIME-WAIT, and check against it before
+                * accepting new connection request.
+                *
+                * If "isn" is not zero, this request hit alive
+                * timewait bucket, so that all the necessary checks
+                * are made in the function processing timewait state.
+                */
+               if (tp.saw_tstamp &&
+                   sysctl_tcp_tw_recycle &&
+                   (dst = tcp_v4_route_req(sk, req)) != NULL &&
+                   (peer = rt_get_peer((struct rtable*)dst)) != NULL &&
+                   peer->v4daddr == saddr) {
+                       if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
+                           (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
+                               NET_INC_STATS_BH(PAWSPassiveRejected);
+                               dst_release(dst);
+                               goto drop_and_free;
+                       }
+               }
+               /* Kill the following clause, if you dislike this way. */
+               else if (!sysctl_tcp_syncookies &&
+                        (sysctl_max_syn_backlog - tcp_synq_len(sk)
+                         < (sysctl_max_syn_backlog>>2)) &&
+                        (!peer || !peer->tcp_ts_stamp) &&
+                        (!dst || !dst->rtt)) {
+                       /* Without syncookies last quarter of
+                        * backlog is filled with destinations, proven to be alive.
+                        * It means that we continue to communicate
+                        * to destinations, already remembered
+                        * to the moment of synflood.
+                        */
+                       NETDEBUG(if (net_ratelimit()) \
+                               printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \
+                                       NIPQUAD(saddr), ntohs(skb->h.th->source)));
+                       dst_release(dst);
+                       goto drop_and_free;
+               }
+
+               isn = tcp_v4_init_sequence(sk, skb);
+       }
+       req->snt_isn = isn;
+
+       if (tcp_v4_send_synack(sk, req, dst))
+               goto drop_and_free;
+
+       if (want_cookie) {
+               tcp_openreq_free(req); 
+       } else {
+               tcp_v4_synq_add(sk, req);
+       }
+       return 0;
+
+drop_and_free:
+       tcp_openreq_free(req); 
+drop:
+       TCP_INC_STATS_BH(TcpAttemptFails);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+
+/* 
+ * The three way handshake has completed - we got a valid synack - 
+ * now create the new socket. 
+ */
+struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+                                  struct open_request *req,
+                                  struct dst_entry *dst)
+{
+#if 0
+       struct tcp_opt *newtp;
+       struct sock *newsk;
+
+       if (tcp_acceptq_is_full(sk))
+               goto exit_overflow;
+
+       if (dst == NULL &&
+           (dst = tcp_v4_route_req(sk, req)) == NULL)
+               goto exit;
+
+       newsk = tcp_create_openreq_child(sk, req, skb);
+       if (!newsk)
+               goto exit;
+
+       newsk->dst_cache = dst;
+       newsk->route_caps = dst->dev->features;
+
+       newtp = &(newsk->tp_pinfo.af_tcp);
+       newsk->daddr = req->af.v4_req.rmt_addr;
+       newsk->saddr = req->af.v4_req.loc_addr;
+       newsk->rcv_saddr = req->af.v4_req.loc_addr;
+       newsk->protinfo.af_inet.opt = req->af.v4_req.opt;
+       req->af.v4_req.opt = NULL;
+       newsk->protinfo.af_inet.mc_index = tcp_v4_iif(skb);
+       newsk->protinfo.af_inet.mc_ttl = skb->nh.iph->ttl;
+       newtp->ext_header_len = 0;
+       if (newsk->protinfo.af_inet.opt)
+               newtp->ext_header_len = newsk->protinfo.af_inet.opt->optlen;
+       newsk->protinfo.af_inet.id = newtp->write_seq^jiffies;
+
+       tcp_sync_mss(newsk, dst->pmtu);
+       newtp->advmss = dst->advmss;
+       tcp_initialize_rcv_mss(newsk);
+
+       __tcp_v4_hash(newsk, 0);
+       __tcp_inherit_port(sk, newsk);
+
+       return newsk;
+
+exit_overflow:
+       NET_INC_STATS_BH(ListenOverflows);
+exit:
+       NET_INC_STATS_BH(ListenDrops);
+       dst_release(dst);
+       return NULL;
+#else
+  return NULL;
+#endif
+}
+
+static struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
+{
+#if 0
+       struct open_request *req, **prev;
+       struct tcphdr *th = skb->h.th;
+       struct iphdr *iph = skb->nh.iph;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sock *nsk;
+
+       /* Find possible connection requests. */
+       req = tcp_v4_search_req(tp, &prev,
+                               th->source,
+                               iph->saddr, iph->daddr);
+       if (req)
+               return tcp_check_req(sk, skb, req, prev);
+
+       nsk = __tcp_v4_lookup_established(skb->nh.iph->saddr,
+                                         th->source,
+                                         skb->nh.iph->daddr,
+                                         ntohs(th->dest),
+                                         tcp_v4_iif(skb));
+
+       if (nsk) {
+               if (nsk->state != TCP_TIME_WAIT) {
+                       bh_lock_sock(nsk);
+                       return nsk;
+               }
+               tcp_tw_put((struct tcp_tw_bucket*)nsk);
+               return NULL;
+       }
+
+#ifdef CONFIG_SYN_COOKIES
+       if (!th->rst && !th->syn && th->ack)
+               sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
+#endif
+       return sk;
+#else
+  return NULL;
+#endif
+}
+
+static int tcp_v4_checksum_init(struct sk_buff *skb)
+{
+#if 0
+       if (skb->ip_summed == CHECKSUM_HW) {
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               if (!tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+                                 skb->nh.iph->daddr,skb->csum))
+                       return 0;
+
+               NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
+               skb->ip_summed = CHECKSUM_NONE;
+       }
+       if (skb->len <= 76) {
+               if (tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+                                skb->nh.iph->daddr,
+                                skb_checksum(skb, 0, skb->len, 0)))
+                       return -1;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+       } else {
+               skb->csum = ~tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+                                         skb->nh.iph->daddr,0);
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+
+/* The socket must have it's spinlock held when we get
+ * here.
+ *
+ * We have a potential double-lock case here, so even when
+ * doing backlog processing we use the BH locking scheme.
+ * This is because we cannot sleep with the original spinlock
+ * held.
+ */
+int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+#ifdef CONFIG_FILTER
+       struct sk_filter *filter = sk->filter;
+       if (filter && sk_filter(skb, filter))
+               goto discard;
+#endif /* CONFIG_FILTER */
+
+       IP_INC_STATS_BH(IpInDelivers);
+
+       if (sk->state == TCP_ESTABLISHED) { /* Fast path */
+               TCP_CHECK_TIMER(sk);
+               if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
+                       goto reset;
+               TCP_CHECK_TIMER(sk);
+               return 0; 
+       }
+
+       if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb))
+               goto csum_err;
+
+       if (sk->state == TCP_LISTEN) { 
+               struct sock *nsk = tcp_v4_hnd_req(sk, skb);
+               if (!nsk)
+                       goto discard;
+
+               if (nsk != sk) {
+                       if (tcp_child_process(sk, nsk, skb))
+                               goto reset;
+                       return 0;
+               }
+       }
+
+       TCP_CHECK_TIMER(sk);
+       if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
+               goto reset;
+       TCP_CHECK_TIMER(sk);
+       return 0;
+
+reset:
+       tcp_v4_send_reset(skb);
+discard:
+       kfree_skb(skb);
+       /* Be careful here. If this function gets more complicated and
+        * gcc suffers from register pressure on the x86, sk (in %ebx) 
+        * might be destroyed here. This current version compiles correctly,
+        * but you have been warned.
+        */
+       return 0;
+
+csum_err:
+       TCP_INC_STATS_BH(TcpInErrs);
+       goto discard;
+#else
+  return 0;
+#endif
+}
+
+/*
+ *     From tcp_input.c
+ */
+
+int tcp_v4_rcv(struct sk_buff *skb)
+{
+#if 0
+       struct tcphdr *th;
+       struct sock *sk;
+       int ret;
+
+       if (skb->pkt_type!=PACKET_HOST)
+               goto discard_it;
+
+       /* Count it even if it's bad */
+       TCP_INC_STATS_BH(TcpInSegs);
+
+       if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
+               goto discard_it;
+
+       th = skb->h.th;
+
+       if (th->doff < sizeof(struct tcphdr)/4)
+               goto bad_packet;
+       if (!pskb_may_pull(skb, th->doff*4))
+               goto discard_it;
+
+       /* An explanation is required here, I think.
+        * Packet length and doff are validated by header prediction,
+        * provided case of th->doff==0 is elimineted.
+        * So, we defer the checks. */
+       if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
+            tcp_v4_checksum_init(skb) < 0))
+               goto bad_packet;
+
+       th = skb->h.th;
+       TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+       TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+                                   skb->len - th->doff*4);
+       TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+       TCP_SKB_CB(skb)->when = 0;
+       TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
+       TCP_SKB_CB(skb)->sacked = 0;
+
+       sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
+                            skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb));
+
+       if (!sk)
+               goto no_tcp_socket;
+
+process:
+       if(!ipsec_sk_policy(sk,skb))
+               goto discard_and_relse;
+
+       if (sk->state == TCP_TIME_WAIT)
+               goto do_time_wait;
+
+       skb->dev = NULL;
+
+       bh_lock_sock(sk);
+       ret = 0;
+       if (!sk->lock.users) {
+               if (!tcp_prequeue(sk, skb))
+                       ret = tcp_v4_do_rcv(sk, skb);
+       } else
+               sk_add_backlog(sk, skb);
+       bh_unlock_sock(sk);
+
+       sock_put(sk);
+
+       return ret;
+
+no_tcp_socket:
+       if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
+bad_packet:
+               TCP_INC_STATS_BH(TcpInErrs);
+       } else {
+               tcp_v4_send_reset(skb);
+       }
+
+discard_it:
+       /* Discard frame. */
+       kfree_skb(skb);
+       return 0;
+
+discard_and_relse:
+       sock_put(sk);
+       goto discard_it;
+
+do_time_wait:
+       if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
+               TCP_INC_STATS_BH(TcpInErrs);
+               goto discard_and_relse;
+       }
+       switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
+                                         skb, th, skb->len)) {
+       case TCP_TW_SYN:
+       {
+               struct sock *sk2;
+
+               sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb));
+               if (sk2 != NULL) {
+                       tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
+                       tcp_timewait_kill((struct tcp_tw_bucket *)sk);
+                       tcp_tw_put((struct tcp_tw_bucket *)sk);
+                       sk = sk2;
+                       goto process;
+               }
+               /* Fall through to ACK */
+       }
+       case TCP_TW_ACK:
+               tcp_v4_timewait_ack(sk, skb);
+               break;
+       case TCP_TW_RST:
+               goto no_tcp_socket;
+       case TCP_TW_SUCCESS:;
+       }
+       goto discard_it;
+#endif
+}
+
+/* With per-bucket locks this operation is not-atomic, so that
+ * this version is not worse.
+ */
+static void __tcp_v4_rehash(struct sock *sk)
+{
+#if 0
+       sk->prot->unhash(sk);
+       sk->prot->hash(sk);
+#endif
+}
+
+static int tcp_v4_reselect_saddr(struct sock *sk)
+{
+#if 0
+       int err;
+       struct rtable *rt;
+       __u32 old_saddr = sk->saddr;
+       __u32 new_saddr;
+       __u32 daddr = sk->daddr;
+
+       if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr)
+               daddr = sk->protinfo.af_inet.opt->faddr;
+
+       /* Query new route. */
+       err = ip_route_connect(&rt, daddr, 0,
+                              RT_TOS(sk->protinfo.af_inet.tos)|sk->localroute,
+                              sk->bound_dev_if);
+       if (err)
+               return err;
+
+       __sk_dst_set(sk, &rt->u.dst);
+       sk->route_caps = rt->u.dst.dev->features;
+
+       new_saddr = rt->rt_src;
+
+       if (new_saddr == old_saddr)
+               return 0;
+
+       if (sysctl_ip_dynaddr > 1) {
+               printk(KERN_INFO "tcp_v4_rebuild_header(): shifting sk->saddr "
+                      "from %d.%d.%d.%d to %d.%d.%d.%d\n",
+                      NIPQUAD(old_saddr), 
+                      NIPQUAD(new_saddr));
+       }
+
+       sk->saddr = new_saddr;
+       sk->rcv_saddr = new_saddr;
+
+       /* XXX The only one ugly spot where we need to
+        * XXX really change the sockets identity after
+        * XXX it has entered the hashes. -DaveM
+        *
+        * Besides that, it does not check for connection
+        * uniqueness. Wait for troubles.
+        */
+       __tcp_v4_rehash(sk);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+int tcp_v4_rebuild_header(struct sock *sk)
+{
+#if 0
+       struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
+       u32 daddr;
+       int err;
+
+       /* Route is OK, nothing to do. */
+       if (rt != NULL)
+               return 0;
+
+       /* Reroute. */
+       daddr = sk->daddr;
+       if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr)
+               daddr = sk->protinfo.af_inet.opt->faddr;
+
+       err = ip_route_output(&rt, daddr, sk->saddr,
+                             RT_CONN_FLAGS(sk), sk->bound_dev_if);
+       if (!err) {
+               __sk_dst_set(sk, &rt->u.dst);
+               sk->route_caps = rt->u.dst.dev->features;
+               return 0;
+       }
+
+       /* Routing failed... */
+       sk->route_caps = 0;
+
+       if (!sysctl_ip_dynaddr ||
+           sk->state != TCP_SYN_SENT ||
+           (sk->userlocks & SOCK_BINDADDR_LOCK) ||
+           (err = tcp_v4_reselect_saddr(sk)) != 0)
+               sk->err_soft=-err;
+
+       return err;
+#else
+  return 0;
+#endif
+}
+
+static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
+{
+#if 0
+       struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
+
+       sin->sin_family         = AF_INET;
+       sin->sin_addr.s_addr    = sk->daddr;
+       sin->sin_port           = sk->dport;
+#endif
+}
+
+/* VJ's idea. Save last timestamp seen from this destination
+ * and hold it at least for normal timewait interval to use for duplicate
+ * segment detection in subsequent connections, before they enter synchronized
+ * state.
+ */
+
+int tcp_v4_remember_stamp(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct rtable *rt = (struct rtable*)__sk_dst_get(sk);
+       struct inet_peer *peer = NULL;
+       int release_it = 0;
+
+       if (rt == NULL || rt->rt_dst != sk->daddr) {
+               peer = inet_getpeer(sk->daddr, 1);
+               release_it = 1;
+       } else {
+               if (rt->peer == NULL)
+                       rt_bind_peer(rt, 1);
+               peer = rt->peer;
+       }
+
+       if (peer) {
+               if ((s32)(peer->tcp_ts - tp->ts_recent) <= 0 ||
+                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+                    peer->tcp_ts_stamp <= tp->ts_recent_stamp)) {
+                       peer->tcp_ts_stamp = tp->ts_recent_stamp;
+                       peer->tcp_ts = tp->ts_recent;
+               }
+               if (release_it)
+                       inet_putpeer(peer);
+               return 1;
+       }
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
+{
+#if 0
+       struct inet_peer *peer = NULL;
+
+       peer = inet_getpeer(tw->daddr, 1);
+
+       if (peer) {
+               if ((s32)(peer->tcp_ts - tw->ts_recent) <= 0 ||
+                   (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+                    peer->tcp_ts_stamp <= tw->ts_recent_stamp)) {
+                       peer->tcp_ts_stamp = tw->ts_recent_stamp;
+                       peer->tcp_ts = tw->ts_recent;
+               }
+               inet_putpeer(peer);
+               return 1;
+       }
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+#if 0
+struct tcp_func ipv4_specific = {
+       ip_queue_xmit,
+       tcp_v4_send_check,
+       tcp_v4_rebuild_header,
+       tcp_v4_conn_request,
+       tcp_v4_syn_recv_sock,
+       tcp_v4_remember_stamp,
+       sizeof(struct iphdr),
+
+       ip_setsockopt,
+       ip_getsockopt,
+       v4_addr2sockaddr,
+       sizeof(struct sockaddr_in)
+};
+#endif
+
+/* NOTE: A lot of things set to zero explicitly by call to
+ *       sk_alloc() so need not be done here.
+ */
+static int tcp_v4_init_sock(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       skb_queue_head_init(&tp->out_of_order_queue);
+       tcp_init_xmit_timers(sk);
+       tcp_prequeue_init(tp);
+
+       tp->rto  = TCP_TIMEOUT_INIT;
+       tp->mdev = TCP_TIMEOUT_INIT;
+      
+       /* So many TCP implementations out there (incorrectly) count the
+        * initial SYN frame in their delayed-ACK and congestion control
+        * algorithms that we must have the following bandaid to talk
+        * efficiently to them.  -DaveM
+        */
+       tp->snd_cwnd = 2;
+
+       /* See draft-stevens-tcpca-spec-01 for discussion of the
+        * initialization of these values.
+        */
+       tp->snd_ssthresh = 0x7fffffff;  /* Infinity */
+       tp->snd_cwnd_clamp = ~0;
+       tp->mss_cache = 536;
+
+       tp->reordering = sysctl_tcp_reordering;
+
+       sk->state = TCP_CLOSE;
+
+       sk->write_space = tcp_write_space;
+       sk->use_write_queue = 1;
+
+       sk->tp_pinfo.af_tcp.af_specific = &ipv4_specific;
+
+       sk->sndbuf = sysctl_tcp_wmem[1];
+       sk->rcvbuf = sysctl_tcp_rmem[1];
+
+       atomic_inc(&tcp_sockets_allocated);
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static int tcp_v4_destroy_sock(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       tcp_clear_xmit_timers(sk);
+
+       /* Cleanup up the write buffer. */
+       tcp_writequeue_purge(sk);
+
+       /* Cleans up our, hopefully empty, out_of_order_queue. */
+       __skb_queue_purge(&tp->out_of_order_queue);
+
+       /* Clean prequeue, it must be empty really */
+       __skb_queue_purge(&tp->ucopy.prequeue);
+
+       /* Clean up a referenced TCP bind bucket. */
+       if(sk->prev != NULL)
+               tcp_put_port(sk);
+
+       /* If sendmsg cached page exists, toss it. */
+       if (tp->sndmsg_page != NULL)
+               __free_page(tp->sndmsg_page);
+
+       atomic_dec(&tcp_sockets_allocated);
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* Proc filesystem TCP sock list dumping. */
+static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid)
+{
+#if 0
+       int ttd = req->expires - jiffies;
+
+       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08X %08X %5d %8d %u %d %p",
+               i,
+               req->af.v4_req.loc_addr,
+               ntohs(sk->sport),
+               req->af.v4_req.rmt_addr,
+               ntohs(req->rmt_port),
+               TCP_SYN_RECV,
+               0,0, /* could print option size, but that is af dependent. */
+               1,   /* timers active (only the expire timer) */  
+               ttd, 
+               req->retrans,
+               uid,
+               0,  /* non standard timer */  
+               0, /* open_requests have no inode */
+               atomic_read(&sk->refcnt),
+               req
+               ); 
+#endif
+}
+
+static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
+{
+#if 0
+       unsigned int dest, src;
+       __u16 destp, srcp;
+       int timer_active;
+       unsigned long timer_expires;
+       struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
+
+       dest  = sp->daddr;
+       src   = sp->rcv_saddr;
+       destp = ntohs(sp->dport);
+       srcp  = ntohs(sp->sport);
+       if (tp->pending == TCP_TIME_RETRANS) {
+               timer_active    = 1;
+               timer_expires   = tp->timeout;
+       } else if (tp->pending == TCP_TIME_PROBE0) {
+               timer_active    = 4;
+               timer_expires   = tp->timeout;
+       } else if (timer_pending(&sp->timer)) {
+               timer_active    = 2;
+               timer_expires   = sp->timer.expires;
+       } else {
+               timer_active    = 0;
+               timer_expires = jiffies;
+       }
+
+       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d",
+               i, src, srcp, dest, destp, sp->state, 
+               tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+               timer_active, timer_expires-jiffies,
+               tp->retransmits,
+               sock_i_uid(sp),
+               tp->probes_out,
+               sock_i_ino(sp),
+               atomic_read(&sp->refcnt), sp,
+               tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+               tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
+               );
+#endif
+}
+
+static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+{
+#if 0
+       unsigned int dest, src;
+       __u16 destp, srcp;
+       int ttd = tw->ttd - jiffies;
+
+       if (ttd < 0)
+               ttd = 0;
+
+       dest  = tw->daddr;
+       src   = tw->rcv_saddr;
+       destp = ntohs(tw->dport);
+       srcp  = ntohs(tw->sport);
+
+       sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+               " %02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
+               i, src, srcp, dest, destp, tw->substate, 0, 0,
+               3, ttd, 0, 0, 0, 0,
+               atomic_read(&tw->refcnt), tw);
+#endif
+}
+
+#define TMPSZ 150
+
+int tcp_get_info(char *buffer, char **start, off_t offset, int length)
+{
+#if 0
+       int len = 0, num = 0, i;
+       off_t begin, pos = 0;
+       char tmpbuf[TMPSZ+1];
+
+       if (offset < TMPSZ)
+               len += sprintf(buffer, "%-*s\n", TMPSZ-1,
+                              "  sl  local_address rem_address   st tx_queue "
+                              "rx_queue tr tm->when retrnsmt   uid  timeout inode");
+
+       pos = TMPSZ;
+
+       /* First, walk listening socket table. */
+       tcp_listen_lock();
+       for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
+               struct sock *sk;
+               struct tcp_listen_opt *lopt;
+               int k;
+
+               for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
+                       struct open_request *req;
+                       int uid;
+                       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+                       if (!TCP_INET_FAMILY(sk->family))
+                               goto skip_listen;
+
+                       pos += TMPSZ;
+                       if (pos >= offset) {
+                               get_tcp_sock(sk, tmpbuf, num);
+                               len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+                               if (pos >= offset + length) {
+                                       tcp_listen_unlock();
+                                       goto out_no_bh;
+                               }
+                       }
+
+skip_listen:
+                       uid = sock_i_uid(sk);
+                       read_lock_bh(&tp->syn_wait_lock);
+                       lopt = tp->listen_opt;
+                       if (lopt && lopt->qlen != 0) {
+                               for (k=0; k<TCP_SYNQ_HSIZE; k++) {
+                                       for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) {
+                                               if (!TCP_INET_FAMILY(req->class->family))
+                                                       continue;
+
+                                               pos += TMPSZ;
+                                               if (pos <= offset)
+                                                       continue;
+                                               get_openreq(sk, req, tmpbuf, num, uid);
+                                               len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+                                               if (pos >= offset + length) {
+                                                       read_unlock_bh(&tp->syn_wait_lock);
+                                                       tcp_listen_unlock();
+                                                       goto out_no_bh;
+                                               }
+                                       }
+                               }
+                       }
+                       read_unlock_bh(&tp->syn_wait_lock);
+
+                       /* Completed requests are in normal socket hash table */
+               }
+       }
+       tcp_listen_unlock();
+
+       local_bh_disable();
+
+       /* Next, walk established hash chain. */
+       for (i = 0; i < tcp_ehash_size; i++) {
+               struct tcp_ehash_bucket *head = &tcp_ehash[i];
+               struct sock *sk;
+               struct tcp_tw_bucket *tw;
+
+               read_lock(&head->lock);
+               for(sk = head->chain; sk; sk = sk->next, num++) {
+                       if (!TCP_INET_FAMILY(sk->family))
+                               continue;
+                       pos += TMPSZ;
+                       if (pos <= offset)
+                               continue;
+                       get_tcp_sock(sk, tmpbuf, num);
+                       len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+                       if (pos >= offset + length) {
+                               read_unlock(&head->lock);
+                               goto out;
+                       }
+               }
+               for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain;
+                    tw != NULL;
+                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
+                       if (!TCP_INET_FAMILY(tw->family))
+                               continue;
+                       pos += TMPSZ;
+                       if (pos <= offset)
+                               continue;
+                       get_timewait_sock(tw, tmpbuf, num);
+                       len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+                       if (pos >= offset + length) {
+                               read_unlock(&head->lock);
+                               goto out;
+                       }
+               }
+               read_unlock(&head->lock);
+       }
+
+out:
+       local_bh_enable();
+out_no_bh:
+
+       begin = len - (pos - offset);
+       *start = buffer + begin;
+       len -= begin;
+       if (len > length)
+               len = length;
+       if (len < 0)
+               len = 0; 
+       return len;
+#endif
+}
+
+struct proto tcp_prot = {
+       name:           "TCP",
+       close:          tcp_close,
+       connect:        tcp_v4_connect,
+       disconnect:     tcp_disconnect,
+       accept:         tcp_accept,
+       ioctl:          tcp_ioctl,
+       init:           tcp_v4_init_sock,
+       destroy:        tcp_v4_destroy_sock,
+       shutdown:       tcp_shutdown,
+       setsockopt:     tcp_setsockopt,
+       getsockopt:     tcp_getsockopt,
+       sendmsg:        tcp_sendmsg,
+       recvmsg:        tcp_recvmsg,
+       backlog_rcv:    tcp_v4_do_rcv,
+       hash:           tcp_v4_hash,
+       unhash:         tcp_unhash,
+       get_port:       tcp_v4_get_port,
+};
+
+
+
+void tcp_v4_init(struct net_proto_family *ops)
+{
+#if 0
+       int err;
+
+       tcp_inode.i_mode = S_IFSOCK;
+       tcp_inode.i_sock = 1;
+       tcp_inode.i_uid = 0;
+       tcp_inode.i_gid = 0;
+       init_waitqueue_head(&tcp_inode.i_wait);
+       init_waitqueue_head(&tcp_inode.u.socket_i.wait);
+
+       tcp_socket->inode = &tcp_inode;
+       tcp_socket->state = SS_UNCONNECTED;
+       tcp_socket->type=SOCK_RAW;
+
+       if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
+               panic("Failed to create the TCP control socket.\n");
+       tcp_socket->sk->allocation=GFP_ATOMIC;
+       tcp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
+
+       /* Unhash it so that IP input processing does not even
+        * see it, we do not wish this socket to see incoming
+        * packets.
+        */
+       tcp_socket->sk->prot->unhash(tcp_socket->sk);
+#endif
+}
diff --git a/drivers/net/tcpip/transport/tcp/tcp_output.c b/drivers/net/tcpip/transport/tcp/tcp_output.c
new file mode 100755 (executable)
index 0000000..01e75fb
--- /dev/null
@@ -0,0 +1,1549 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        transport/tcp/tcp_output.c
+ * PURPOSE:     Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version:    $Id$
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *             Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *             Florian La Roche, <flla@stud.uni-sb.de>
+ *             Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ *             Linus Torvalds, <torvalds@cs.helsinki.fi>
+ *             Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *             Matthew Dillon, <dillon@apollo.west.oic.com>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes:    Pedro Roque     :       Retransmit queue handled by TCP.
+ *                             :       Fragmentation on mtu decrease
+ *                             :       Segment collapse on retransmit
+ *                             :       AF independence
+ *
+ *             Linus Torvalds  :       send_delayed_ack
+ *             David S. Miller :       Charge memory using the right skb
+ *                                     during syn/ack processing.
+ *             David S. Miller :       Output engine completely rewritten.
+ *             Andrea Arcangeli:       SYNACK carry ts_recent in tsecr.
+ *             Cacophonix Gaul :       draft-minshall-nagle-01
+ *             J Hadi Salim    :       ECN support
+ *
+ */
+
+#if 0
+#include <net/tcp.h>
+
+#include <linux/compiler.h>
+#include <linux/smp_lock.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+/* People can turn this off for buggy TCP's found in printers etc. */
+int sysctl_tcp_retrans_collapse = 1;
+
+static __inline__
+void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+       tp->send_head = skb->next;
+       if (tp->send_head == (struct sk_buff *) &sk->write_queue)
+               tp->send_head = NULL;
+       tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+       if (tp->packets_out++ == 0)
+               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+}
+
+/* SND.NXT, if window was not shrunk.
+ * If window has been shrunk, what should we make? It is not clear at all.
+ * Using SND.UNA we will fail to open window, SND.NXT is out of window. :-(
+ * Anything in between SND.UNA...SND.UNA+SND.WND also can be already
+ * invalid. OK, let's make this for now:
+ */
+static __inline__ __u32 tcp_acceptable_seq(struct sock *sk, struct tcp_opt *tp)
+{
+       if (!before(tp->snd_una+tp->snd_wnd, tp->snd_nxt))
+               return tp->snd_nxt;
+       else
+               return tp->snd_una+tp->snd_wnd;
+}
+
+/* Calculate mss to advertise in SYN segment.
+ * RFC1122, RFC1063, draft-ietf-tcpimpl-pmtud-01 state that:
+ *
+ * 1. It is independent of path mtu.
+ * 2. Ideally, it is maximal possible segment size i.e. 65535-40.
+ * 3. For IPv4 it is reasonable to calculate it from maximal MTU of
+ *    attached devices, because some buggy hosts are confused by
+ *    large MSS.
+ * 4. We do not make 3, we advertise MSS, calculated from first
+ *    hop device mtu, but allow to raise it to ip_rt_min_advmss.
+ *    This may be overriden via information stored in routing table.
+ * 5. Value 65535 for MSS is valid in IPv6 and means "as large as possible,
+ *    probably even Jumbo".
+ */
+static __u16 tcp_advertise_mss(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct dst_entry *dst = __sk_dst_get(sk);
+       int mss = tp->advmss;
+
+       if (dst && dst->advmss < mss) {
+               mss = dst->advmss;
+               tp->advmss = mss;
+       }
+
+       return (__u16)mss;
+#else
+  return 0;
+#endif
+}
+
+/* RFC2861. Reset CWND after idle period longer RTO to "restart window".
+ * This is the first part of cwnd validation mechanism. */
+static void tcp_cwnd_restart(struct tcp_opt *tp)
+{
+#if 0
+       s32 delta = tcp_time_stamp - tp->lsndtime;
+       u32 restart_cwnd = tcp_init_cwnd(tp);
+       u32 cwnd = tp->snd_cwnd;
+
+       tp->snd_ssthresh = tcp_current_ssthresh(tp);
+       restart_cwnd = min(restart_cwnd, cwnd);
+
+       while ((delta -= tp->rto) > 0 && cwnd > restart_cwnd)
+               cwnd >>= 1;
+       tp->snd_cwnd = max(cwnd, restart_cwnd);
+       tp->snd_cwnd_stamp = tcp_time_stamp;
+       tp->snd_cwnd_used = 0;
+#endif
+}
+
+static __inline__ void tcp_event_data_sent(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+       u32 now = tcp_time_stamp;
+
+       if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
+               tcp_cwnd_restart(tp);
+
+       tp->lsndtime = now;
+
+       /* If it is a reply for ato after last received
+        * packet, enter pingpong mode.
+        */
+       if ((u32)(now - tp->ack.lrcvtime) < tp->ack.ato)
+               tp->ack.pingpong = 1;
+#endif
+}
+
+static __inline__ void tcp_event_ack_sent(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       tcp_dec_quickack_mode(tp);
+       tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
+#endif
+}
+
+/* Chose a new window to advertise, update state in tcp_opt for the
+ * socket, and return result with RFC1323 scaling applied.  The return
+ * value can be stuffed directly into th->window for an outgoing
+ * frame.
+ */
+static __inline__ u16 tcp_select_window(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       u32 cur_win = tcp_receive_window(tp);
+       u32 new_win = __tcp_select_window(sk);
+
+       /* Never shrink the offered window */
+       if(new_win < cur_win) {
+               /* Danger Will Robinson!
+                * Don't update rcv_wup/rcv_wnd here or else
+                * we will not be able to advertise a zero
+                * window in time.  --DaveM
+                *
+                * Relax Will Robinson.
+                */
+               new_win = cur_win;
+       }
+       tp->rcv_wnd = new_win;
+       tp->rcv_wup = tp->rcv_nxt;
+
+       /* RFC1323 scaling applied */
+       new_win >>= tp->rcv_wscale;
+
+       /* If we advertise zero window, disable fast path. */
+       if (new_win == 0)
+               tp->pred_flags = 0;
+
+       return new_win;
+#else
+  return 0;
+#endif
+}
+
+
+/* This routine actually transmits TCP packets queued in by
+ * tcp_do_sendmsg().  This is used by both the initial
+ * transmission and possible later retransmissions.
+ * All SKB's seen here are completely headerless.  It is our
+ * job to build the TCP header, and pass the packet down to
+ * IP so it can do the same plus pass the packet off to the
+ * device.
+ *
+ * We are working here with either a clone of the original
+ * SKB, or a fresh unique copy made by the retransmit engine.
+ */
+int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       if(skb != NULL) {
+               struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+               struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
+               int tcp_header_size = tp->tcp_header_len;
+               struct tcphdr *th;
+               int sysctl_flags;
+               int err;
+
+#define SYSCTL_FLAG_TSTAMPS    0x1
+#define SYSCTL_FLAG_WSCALE     0x2
+#define SYSCTL_FLAG_SACK       0x4
+
+               sysctl_flags = 0;
+               if (tcb->flags & TCPCB_FLAG_SYN) {
+                       tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
+                       if(sysctl_tcp_timestamps) {
+                               tcp_header_size += TCPOLEN_TSTAMP_ALIGNED;
+                               sysctl_flags |= SYSCTL_FLAG_TSTAMPS;
+                       }
+                       if(sysctl_tcp_window_scaling) {
+                               tcp_header_size += TCPOLEN_WSCALE_ALIGNED;
+                               sysctl_flags |= SYSCTL_FLAG_WSCALE;
+                       }
+                       if(sysctl_tcp_sack) {
+                               sysctl_flags |= SYSCTL_FLAG_SACK;
+                               if(!(sysctl_flags & SYSCTL_FLAG_TSTAMPS))
+                                       tcp_header_size += TCPOLEN_SACKPERM_ALIGNED;
+                       }
+               } else if (tp->eff_sacks) {
+                       /* A SACK is 2 pad bytes, a 2 byte header, plus
+                        * 2 32-bit sequence numbers for each SACK block.
+                        */
+                       tcp_header_size += (TCPOLEN_SACK_BASE_ALIGNED +
+                                           (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
+               }
+               th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+               skb->h.th = th;
+               skb_set_owner_w(skb, sk);
+
+               /* Build TCP header and checksum it. */
+               th->source              = sk->sport;
+               th->dest                = sk->dport;
+               th->seq                 = htonl(tcb->seq);
+               th->ack_seq             = htonl(tp->rcv_nxt);
+               *(((__u16 *)th) + 6)    = htons(((tcp_header_size >> 2) << 12) | tcb->flags);
+               if (tcb->flags & TCPCB_FLAG_SYN) {
+                       /* RFC1323: The window in SYN & SYN/ACK segments
+                        * is never scaled.
+                        */
+                       th->window      = htons(tp->rcv_wnd);
+               } else {
+                       th->window      = htons(tcp_select_window(sk));
+               }
+               th->check               = 0;
+               th->urg_ptr             = 0;
+
+               if (tp->urg_mode &&
+                   between(tp->snd_up, tcb->seq+1, tcb->seq+0xFFFF)) {
+                       th->urg_ptr             = htons(tp->snd_up-tcb->seq);
+                       th->urg                 = 1;
+               }
+
+               if (tcb->flags & TCPCB_FLAG_SYN) {
+                       tcp_syn_build_options((__u32 *)(th + 1),
+                                             tcp_advertise_mss(sk),
+                                             (sysctl_flags & SYSCTL_FLAG_TSTAMPS),
+                                             (sysctl_flags & SYSCTL_FLAG_SACK),
+                                             (sysctl_flags & SYSCTL_FLAG_WSCALE),
+                                             tp->rcv_wscale,
+                                             tcb->when,
+                                             tp->ts_recent);
+               } else {
+                       tcp_build_and_update_options((__u32 *)(th + 1),
+                                                    tp, tcb->when);
+
+                       TCP_ECN_send(sk, tp, skb, tcp_header_size);
+               }
+               tp->af_specific->send_check(sk, th, skb->len, skb);
+
+               if (tcb->flags & TCPCB_FLAG_ACK)
+                       tcp_event_ack_sent(sk);
+
+               if (skb->len != tcp_header_size)
+                       tcp_event_data_sent(tp, skb);
+
+               TCP_INC_STATS(TcpOutSegs);
+
+               err = tp->af_specific->queue_xmit(skb);
+               if (err <= 0)
+                       return err;
+
+               tcp_enter_cwr(tp);
+
+               /* NET_XMIT_CN is special. It does not guarantee,
+                * that this packet is lost. It tells that device
+                * is about to start to drop packets or already
+                * drops some packets of the same priority and
+                * invokes us to send less aggressively.
+                */
+               return err == NET_XMIT_CN ? 0 : err;
+       }
+       return -ENOBUFS;
+#undef SYSCTL_FLAG_TSTAMPS
+#undef SYSCTL_FLAG_WSCALE
+#undef SYSCTL_FLAG_SACK
+#else
+  return 0;
+#endif
+}
+
+
+/* This is the main buffer sending routine. We queue the buffer
+ * and decide whether to queue or transmit now.
+ *
+ * NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames,
+ * otherwise socket can stall.
+ */
+void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigned cur_mss)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /* Advance write_seq and place onto the write_queue. */
+       tp->write_seq = TCP_SKB_CB(skb)->end_seq;
+       __skb_queue_tail(&sk->write_queue, skb);
+       tcp_charge_skb(sk, skb);
+
+       if (!force_queue && tp->send_head == NULL && tcp_snd_test(tp, skb, cur_mss, tp->nonagle)) {
+               /* Send it out now. */
+               TCP_SKB_CB(skb)->when = tcp_time_stamp;
+               if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) {
+                       tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+                       tcp_minshall_update(tp, cur_mss, skb);
+                       if (tp->packets_out++ == 0)
+                               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+                       return;
+               }
+       }
+       /* Queue it, remembering where we must start sending. */
+       if (tp->send_head == NULL)
+               tp->send_head = skb;
+#endif
+}
+
+/* Send _single_ skb sitting at the send head. This function requires
+ * true push pending frames to setup probe timer etc.
+ */
+void tcp_push_one(struct sock *sk, unsigned cur_mss)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb = tp->send_head;
+
+       if (tcp_snd_test(tp, skb, cur_mss, 1)) {
+               /* Send it out now. */
+               TCP_SKB_CB(skb)->when = tcp_time_stamp;
+               if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) {
+                       tp->send_head = NULL;
+                       tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+                       if (tp->packets_out++ == 0)
+                               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+                       return;
+               }
+       }
+#endif
+}
+
+/* Split fragmented skb to two parts at length len. */
+
+static void skb_split(struct sk_buff *skb, struct sk_buff *skb1, u32 len)
+{
+#if 0
+       int i;
+       int pos = skb->len - skb->data_len;
+
+       if (len < pos) {
+               /* Split line is inside header. */
+               memcpy(skb_put(skb1, pos-len), skb->data + len, pos-len);
+
+               /* And move data appendix as is. */
+               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+                       skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
+
+               skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
+               skb_shinfo(skb)->nr_frags = 0;
+
+               skb1->data_len = skb->data_len;
+               skb1->len += skb1->data_len;
+               skb->data_len = 0;
+               skb->len = len;
+               skb->tail = skb->data+len;
+       } else {
+               int k = 0;
+               int nfrags = skb_shinfo(skb)->nr_frags;
+
+               /* Second chunk has no header, nothing to copy. */
+
+               skb_shinfo(skb)->nr_frags = 0;
+               skb1->len = skb1->data_len = skb->len - len;
+               skb->len = len;
+               skb->data_len = len - pos;
+
+               for (i=0; i<nfrags; i++) {
+                       int size = skb_shinfo(skb)->frags[i].size;
+                       if (pos + size > len) {
+                               skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
+
+                               if (pos < len) {
+                                       /* Split frag.
+                                        * We have to variants in this case:
+                                        * 1. Move all the frag to the second
+                                        *    part, if it is possible. F.e.
+                                        *    this approach is mandatory for TUX,
+                                        *    where splitting is expensive.
+                                        * 2. Split is accurately. We make this.
+                                        */
+                                       get_page(skb_shinfo(skb)->frags[i].page);
+                                       skb_shinfo(skb1)->frags[0].page_offset += (len-pos);
+                                       skb_shinfo(skb1)->frags[0].size -= (len-pos);
+                                       skb_shinfo(skb)->frags[i].size = len-pos;
+                                       skb_shinfo(skb)->nr_frags++;
+                               }
+                               k++;
+                       } else {
+                               skb_shinfo(skb)->nr_frags++;
+                       }
+                       pos += size;
+               }
+               skb_shinfo(skb1)->nr_frags = k;
+       }
+#endif
+}
+
+/* Function to create two new TCP segments.  Shrinks the given segment
+ * to the specified size and appends a new segment with the rest of the
+ * packet to the list.  This won't be called frequently, I hope. 
+ * Remember, these are still headerless SKBs at this point.
+ */
+static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct sk_buff *buff;
+       int nsize = skb->len - len;
+       u16 flags;
+
+       if (skb_cloned(skb) &&
+           skb_is_nonlinear(skb) &&
+           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+               return -ENOMEM;
+
+       /* Get a new skb... force flag on. */
+       buff = tcp_alloc_skb(sk, nsize, GFP_ATOMIC);
+       if (buff == NULL)
+               return -ENOMEM; /* We'll just try again later. */
+       tcp_charge_skb(sk, buff);
+
+       /* Correct the sequence numbers. */
+       TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
+       TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq;
+       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
+
+       /* PSH and FIN should only be set in the second packet. */
+       flags = TCP_SKB_CB(skb)->flags;
+       TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
+       TCP_SKB_CB(buff)->flags = flags;
+       TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
+       if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
+               tp->lost_out++;
+               tp->left_out++;
+       }
+       TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
+
+       if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
+               /* Copy and checksum data tail into the new buffer. */
+               buff->csum = csum_partial_copy_nocheck(skb->data + len, skb_put(buff, nsize),
+                                                      nsize, 0);
+
+               skb_trim(skb, len);
+
+               skb->csum = csum_block_sub(skb->csum, buff->csum, len);
+       } else {
+               skb->ip_summed = CHECKSUM_HW;
+               skb_split(skb, buff, len);
+       }
+
+       buff->ip_summed = skb->ip_summed;
+
+       /* Looks stupid, but our code really uses when of
+        * skbs, which it never sent before. --ANK
+        */
+       TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
+
+       /* Link BUFF into the send queue. */
+       __skb_append(skb, buff);
+
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* This function synchronize snd mss to current pmtu/exthdr set.
+
+   tp->user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
+   for TCP options, but includes only bare TCP header.
+
+   tp->mss_clamp is mss negotiated at connection setup.
+   It is minumum of user_mss and mss received with SYN.
+   It also does not include TCP options.
+
+   tp->pmtu_cookie is last pmtu, seen by this function.
+
+   tp->mss_cache is current effective sending mss, including
+   all tcp options except for SACKs. It is evaluated,
+   taking into account current pmtu, but never exceeds
+   tp->mss_clamp.
+
+   NOTE1. rfc1122 clearly states that advertised MSS
+   DOES NOT include either tcp or ip options.
+
+   NOTE2. tp->pmtu_cookie and tp->mss_cache are READ ONLY outside
+   this function.                      --ANK (980731)
+ */
+
+int tcp_sync_mss(struct sock *sk, u32 pmtu)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       int mss_now;
+
+       /* Calculate base mss without TCP options:
+          It is MMS_S - sizeof(tcphdr) of rfc1122
+        */
+
+       mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr);
+
+       /* Clamp it (mss_clamp does not include tcp options) */
+       if (mss_now > tp->mss_clamp)
+               mss_now = tp->mss_clamp;
+
+       /* Now subtract optional transport overhead */
+       mss_now -= tp->ext_header_len;
+
+       /* Then reserve room for full set of TCP options and 8 bytes of data */
+       if (mss_now < 48)
+               mss_now = 48;
+
+       /* Now subtract TCP options size, not including SACKs */
+       mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
+
+       /* Bound mss with half of window */
+       if (tp->max_window && mss_now > (tp->max_window>>1))
+               mss_now = max((tp->max_window>>1), 68U - tp->tcp_header_len);
+
+       /* And store cached results */
+       tp->pmtu_cookie = pmtu;
+       tp->mss_cache = mss_now;
+       return mss_now;
+#else
+  return 0;
+#endif
+}
+
+
+/* This routine writes packets to the network.  It advances the
+ * send_head.  This happens as incoming acks open up the remote
+ * window for us.
+ *
+ * Returns 1, if no segments are in flight and we have queued segments, but
+ * cannot send anything now because of SWS or another problem.
+ */
+int tcp_write_xmit(struct sock *sk, int nonagle)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       unsigned int mss_now;
+
+       /* If we are closed, the bytes will have to remain here.
+        * In time closedown will finish, we empty the write queue and all
+        * will be happy.
+        */
+       if(sk->state != TCP_CLOSE) {
+               struct sk_buff *skb;
+               int sent_pkts = 0;
+
+               /* Account for SACKS, we may need to fragment due to this.
+                * It is just like the real MSS changing on us midstream.
+                * We also handle things correctly when the user adds some
+                * IP options mid-stream.  Silly to do, but cover it.
+                */
+               mss_now = tcp_current_mss(sk); 
+
+               while((skb = tp->send_head) &&
+                     tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb) ? nonagle : 1)) {
+                       if (skb->len > mss_now) {
+                               if (tcp_fragment(sk, skb, mss_now))
+                                       break;
+                       }
+
+                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+                       if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
+                               break;
+                       /* Advance the send_head.  This one is sent out. */
+                       update_send_head(sk, tp, skb);
+                       tcp_minshall_update(tp, mss_now, skb);
+                       sent_pkts = 1;
+               }
+
+               if (sent_pkts) {
+                       tcp_cwnd_validate(sk, tp);
+                       return 0;
+               }
+
+               return !tp->packets_out && tp->send_head;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* This function returns the amount that we can raise the
+ * usable window based on the following constraints
+ *  
+ * 1. The window can never be shrunk once it is offered (RFC 793)
+ * 2. We limit memory per socket
+ *
+ * RFC 1122:
+ * "the suggested [SWS] avoidance algorithm for the receiver is to keep
+ *  RECV.NEXT + RCV.WIN fixed until:
+ *  RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+ *
+ * i.e. don't raise the right edge of the window until you can raise
+ * it at least MSS bytes.
+ *
+ * Unfortunately, the recommended algorithm breaks header prediction,
+ * since header prediction assumes th->window stays fixed.
+ *
+ * Strictly speaking, keeping th->window fixed violates the receiver
+ * side SWS prevention criteria. The problem is that under this rule
+ * a stream of single byte packets will cause the right side of the
+ * window to always advance by a single byte.
+ * 
+ * Of course, if the sender implements sender side SWS prevention
+ * then this will not be a problem.
+ * 
+ * BSD seems to make the following compromise:
+ * 
+ *     If the free space is less than the 1/4 of the maximum
+ *     space available and the free space is less than 1/2 mss,
+ *     then set the window to 0.
+ *     [ Actually, bsd uses MSS and 1/4 of maximal _window_ ]
+ *     Otherwise, just prevent the window from shrinking
+ *     and from being larger than the largest representable value.
+ *
+ * This prevents incremental opening of the window in the regime
+ * where TCP is limited by the speed of the reader side taking
+ * data out of the TCP receive queue. It does nothing about
+ * those cases where the window is constrained on the sender side
+ * because the pipeline is full.
+ *
+ * BSD also seems to "accidentally" limit itself to windows that are a
+ * multiple of MSS, at least until the free space gets quite small.
+ * This would appear to be a side effect of the mbuf implementation.
+ * Combining these two algorithms results in the observed behavior
+ * of having a fixed window size at almost all times.
+ *
+ * Below we obtain similar behavior by forcing the offered window to
+ * a multiple of the mss when it is feasible to do so.
+ *
+ * Note, we don't "adjust" for TIMESTAMP or SACK option bytes.
+ * Regular options like TIMESTAMP are taken into account.
+ */
+u32 __tcp_select_window(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       /* MSS for the peer's data.  Previous verions used mss_clamp
+        * here.  I don't know if the value based on our guesses
+        * of peer's MSS is better for the performance.  It's more correct
+        * but may be worse for the performance because of rcv_mss
+        * fluctuations.  --SAW  1998/11/1
+        */
+       int mss = tp->ack.rcv_mss;
+       int free_space = tcp_space(sk);
+       int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
+       int window;
+
+       if (mss > full_space)
+               mss = full_space; 
+
+       if (free_space < full_space/2) {
+               tp->ack.quick = 0;
+
+               if (tcp_memory_pressure)
+                       tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
+
+               if (free_space < mss)
+                       return 0;
+       }
+
+       if (free_space > tp->rcv_ssthresh)
+               free_space = tp->rcv_ssthresh;
+
+       /* Get the largest window that is a nice multiple of mss.
+        * Window clamp already applied above.
+        * If our current window offering is within 1 mss of the
+        * free space we just keep it. This prevents the divide
+        * and multiply from happening most of the time.
+        * We also don't do any window rounding when the free space
+        * is too small.
+        */
+       window = tp->rcv_wnd;
+       if (window <= free_space - mss || window > free_space)
+               window = (free_space/mss)*mss;
+
+       return window;
+#else
+  return 0;
+#endif
+}
+
+/* Attempt to collapse two adjacent SKB's during retransmission. */
+static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int mss_now)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct sk_buff *next_skb = skb->next;
+
+       /* The first test we must make is that neither of these two
+        * SKB's are still referenced by someone else.
+        */
+       if(!skb_cloned(skb) && !skb_cloned(next_skb)) {
+               int skb_size = skb->len, next_skb_size = next_skb->len;
+               u16 flags = TCP_SKB_CB(skb)->flags;
+
+               /* Also punt if next skb has been SACK'd. */
+               if(TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_ACKED)
+                       return;
+
+               /* Next skb is out of window. */
+               if (after(TCP_SKB_CB(next_skb)->end_seq, tp->snd_una+tp->snd_wnd))
+                       return;
+
+               /* Punt if not enough space exists in the first SKB for
+                * the data in the second, or the total combined payload
+                * would exceed the MSS.
+                */
+               if ((next_skb_size > skb_tailroom(skb)) ||
+                   ((skb_size + next_skb_size) > mss_now))
+                       return;
+
+               /* Ok.  We will be able to collapse the packet. */
+               __skb_unlink(next_skb, next_skb->list);
+
+               if (next_skb->ip_summed == CHECKSUM_HW)
+                       skb->ip_summed = CHECKSUM_HW;
+
+               if (skb->ip_summed != CHECKSUM_HW) {
+                       memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
+                       skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size);
+               }
+
+               /* Update sequence range on original skb. */
+               TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq;
+
+               /* Merge over control information. */
+               flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */
+               TCP_SKB_CB(skb)->flags = flags;
+
+               /* All done, get rid of second SKB and account for it so
+                * packet counting does not break.
+                */
+               TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
+               if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
+                       tp->retrans_out--;
+               if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
+                       tp->lost_out--;
+                       tp->left_out--;
+               }
+               /* Reno case is special. Sigh... */
+               if (!tp->sack_ok && tp->sacked_out) {
+                       tp->sacked_out--;
+                       tp->left_out--;
+               }
+
+               /* Not quite right: it can be > snd.fack, but
+                * it is better to underestimate fackets.
+                */
+               if (tp->fackets_out)
+                       tp->fackets_out--;
+               tcp_free_skb(sk, next_skb);
+               tp->packets_out--;
+       }
+#endif
+}
+
+/* Do a simple retransmit without using the backoff mechanisms in
+ * tcp_timer. This is used for path mtu discovery. 
+ * The socket is already locked here.
+ */ 
+void tcp_simple_retransmit(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb;
+       unsigned int mss = tcp_current_mss(sk);
+       int lost = 0;
+
+       for_retrans_queue(skb, sk, tp) {
+               if (skb->len > mss && 
+                   !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
+                       if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
+                               TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+                               tp->retrans_out--;
+                       }
+                       if (!(TCP_SKB_CB(skb)->sacked&TCPCB_LOST)) {
+                               TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+                               tp->lost_out++;
+                               lost = 1;
+                       }
+               }
+       }
+
+       if (!lost)
+               return;
+
+       tcp_sync_left_out(tp);
+
+       /* Don't muck with the congestion window here.
+        * Reason is that we do not increase amount of _data_
+        * in network, but units changed and effective
+        * cwnd/ssthresh really reduced now.
+        */
+       if (tp->ca_state != TCP_CA_Loss) {
+               tp->high_seq = tp->snd_nxt;
+               tp->snd_ssthresh = tcp_current_ssthresh(tp);
+               tp->prior_ssthresh = 0;
+               tp->undo_marker = 0;
+               tp->ca_state = TCP_CA_Loss;
+       }
+       tcp_xmit_retransmit_queue(sk);
+#endif
+}
+
+/* This retransmits one SKB.  Policy decisions and retransmit queue
+ * state updates are done by the caller.  Returns non-zero if an
+ * error occurred which prevented the send.
+ */
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       unsigned int cur_mss = tcp_current_mss(sk);
+       int err;
+
+       /* Do not sent more than we queued. 1/4 is reserved for possible
+        * copying overhead: frgagmentation, tunneling, mangling etc.
+        */
+       if (atomic_read(&sk->wmem_alloc) > min(sk->wmem_queued+(sk->wmem_queued>>2),sk->sndbuf))
+               return -EAGAIN;
+
+       /* If receiver has shrunk his window, and skb is out of
+        * new window, do not retransmit it. The exception is the
+        * case, when window is shrunk to zero. In this case
+        * our retransmit serves as a zero window probe.
+        */
+       if (!before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)
+           && TCP_SKB_CB(skb)->seq != tp->snd_una)
+               return -EAGAIN;
+
+       if(skb->len > cur_mss) {
+               if(tcp_fragment(sk, skb, cur_mss))
+                       return -ENOMEM; /* We'll try again later. */
+
+               /* New SKB created, account for it. */
+               tp->packets_out++;
+       }
+
+       /* Collapse two adjacent packets if worthwhile and we can. */
+       if(!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) &&
+          (skb->len < (cur_mss >> 1)) &&
+          (skb->next != tp->send_head) &&
+          (skb->next != (struct sk_buff *)&sk->write_queue) &&
+          (skb_shinfo(skb)->nr_frags == 0 && skb_shinfo(skb->next)->nr_frags == 0) &&
+          (sysctl_tcp_retrans_collapse != 0))
+               tcp_retrans_try_collapse(sk, skb, cur_mss);
+
+       if(tp->af_specific->rebuild_header(sk))
+               return -EHOSTUNREACH; /* Routing failure or similar. */
+
+       /* Some Solaris stacks overoptimize and ignore the FIN on a
+        * retransmit when old data is attached.  So strip it off
+        * since it is cheap to do so and saves bytes on the network.
+        */
+       if(skb->len > 0 &&
+          (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+          tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+               if (!pskb_trim(skb, 0)) {
+                       TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+                       skb->ip_summed = CHECKSUM_NONE;
+                       skb->csum = 0;
+               }
+       }
+
+       /* Make a copy, if the first transmission SKB clone we made
+        * is still in somebody's hands, else make a clone.
+        */
+       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
+       err = tcp_transmit_skb(sk, (skb_cloned(skb) ?
+                                   pskb_copy(skb, GFP_ATOMIC):
+                                   skb_clone(skb, GFP_ATOMIC)));
+
+       if (err == 0) {
+               /* Update global TCP statistics. */
+               TCP_INC_STATS(TcpRetransSegs);
+
+#if FASTRETRANS_DEBUG > 0
+               if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
+                       if (net_ratelimit())
+                               printk(KERN_DEBUG "retrans_out leaked.\n");
+               }
+#endif
+               TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
+               tp->retrans_out++;
+
+               /* Save stamp of the first retransmit. */
+               if (!tp->retrans_stamp)
+                       tp->retrans_stamp = TCP_SKB_CB(skb)->when;
+
+               tp->undo_retrans++;
+
+               /* snd_nxt is stored to detect loss of retransmitted segment,
+                * see tcp_input.c tcp_sacktag_write_queue().
+                */
+               TCP_SKB_CB(skb)->ack_seq = tp->snd_nxt;
+       }
+       return err;
+#else
+  return 0;
+#endif
+}
+
+/* This gets called after a retransmit timeout, and the initially
+ * retransmitted data is acknowledged.  It tries to continue
+ * resending the rest of the retransmit queue, until either
+ * we've sent it all or the congestion window limit is reached.
+ * If doing SACK, the first ACK which comes back for a timeout
+ * based retransmit packet might feed us FACK information again.
+ * If so, we use it to avoid unnecessarily retransmissions.
+ */
+void tcp_xmit_retransmit_queue(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb;
+       int packet_cnt = tp->lost_out;
+
+       /* First pass: retransmit lost packets. */
+       if (packet_cnt) {
+               for_retrans_queue(skb, sk, tp) {
+                       __u8 sacked = TCP_SKB_CB(skb)->sacked;
+
+                       if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
+                               return;
+
+                       if (sacked&TCPCB_LOST) {
+                               if (!(sacked&(TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) {
+                                       if (tcp_retransmit_skb(sk, skb))
+                                               return;
+                                       if (tp->ca_state != TCP_CA_Loss)
+                                               NET_INC_STATS_BH(TCPFastRetrans);
+                                       else
+                                               NET_INC_STATS_BH(TCPSlowStartRetrans);
+
+                                       if (skb == skb_peek(&sk->write_queue))
+                                               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+                               }
+
+                               if (--packet_cnt <= 0)
+                                       break;
+                       }
+               }
+       }
+
+       /* OK, demanded retransmission is finished. */
+
+       /* Forward retransmissions are possible only during Recovery. */
+       if (tp->ca_state != TCP_CA_Recovery)
+               return;
+
+       /* No forward retransmissions in Reno are possible. */
+       if (!tp->sack_ok)
+               return;
+
+       /* Yeah, we have to make difficult choice between forward transmission
+        * and retransmission... Both ways have their merits...
+        *
+        * For now we do not retrnamsit anything, while we have some new
+        * segments to send.
+        */
+
+       if (tcp_may_send_now(sk, tp))
+               return;
+
+       packet_cnt = 0;
+
+       for_retrans_queue(skb, sk, tp) {
+               if(++packet_cnt > tp->fackets_out)
+                       break;
+
+               if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
+                       break;
+
+               if(TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
+                       continue;
+
+               /* Ok, retransmit it. */
+               if(tcp_retransmit_skb(sk, skb))
+                       break;
+
+               if (skb == skb_peek(&sk->write_queue))
+                       tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+
+               NET_INC_STATS_BH(TCPForwardRetrans);
+       }
+#endif
+}
+
+
+/* Send a fin.  The caller locks the socket for us.  This cannot be
+ * allowed to fail queueing a FIN frame under any circumstances.
+ */
+void tcp_send_fin(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);    
+       struct sk_buff *skb = skb_peek_tail(&sk->write_queue);
+       unsigned int mss_now;
+       
+       /* Optimization, tack on the FIN if we have a queue of
+        * unsent frames.  But be careful about outgoing SACKS
+        * and IP options.
+        */
+       mss_now = tcp_current_mss(sk); 
+
+       if(tp->send_head != NULL) {
+               TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
+               TCP_SKB_CB(skb)->end_seq++;
+               tp->write_seq++;
+       } else {
+               /* Socket is locked, keep trying until memory is available. */
+               for (;;) {
+                       skb = alloc_skb(MAX_TCP_HEADER, GFP_KERNEL);
+                       if (skb)
+                               break;
+                       yield();
+               }
+
+               /* Reserve space for headers and prepare control bits. */
+               skb_reserve(skb, MAX_TCP_HEADER);
+               skb->csum = 0;
+               TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
+               TCP_SKB_CB(skb)->sacked = 0;
+
+               /* FIN eats a sequence byte, write_seq advanced by tcp_send_skb(). */
+               TCP_SKB_CB(skb)->seq = tp->write_seq;
+               TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+               tcp_send_skb(sk, skb, 1, mss_now);
+       }
+       __tcp_push_pending_frames(sk, tp, mss_now, 1);
+#endif
+}
+
+/* We get here when a process closes a file descriptor (either due to
+ * an explicit close() or as a byproduct of exit()'ing) and there
+ * was unread data in the receive queue.  This behavior is recommended
+ * by draft-ietf-tcpimpl-prob-03.txt section 3.10.  -DaveM
+ */
+void tcp_send_active_reset(struct sock *sk, int priority)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb;
+
+       /* NOTE: No TCP options attached and we never retransmit this. */
+       skb = alloc_skb(MAX_TCP_HEADER, priority);
+       if (!skb) {
+               NET_INC_STATS(TCPAbortFailed);
+               return;
+       }
+
+       /* Reserve space for headers and prepare control bits. */
+       skb_reserve(skb, MAX_TCP_HEADER);
+       skb->csum = 0;
+       TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
+       TCP_SKB_CB(skb)->sacked = 0;
+
+       /* Send it off. */
+       TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
+       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+       if (tcp_transmit_skb(sk, skb))
+               NET_INC_STATS(TCPAbortFailed);
+#endif
+}
+
+/* WARNING: This routine must only be called when we have already sent
+ * a SYN packet that crossed the incoming SYN that caused this routine
+ * to get called. If this assumption fails then the initial rcv_wnd
+ * and rcv_wscale values will not be correct.
+ */
+int tcp_send_synack(struct sock *sk)
+{
+#if 0
+       struct sk_buff* skb;
+
+       skb = skb_peek(&sk->write_queue);
+       if (skb == NULL || !(TCP_SKB_CB(skb)->flags&TCPCB_FLAG_SYN)) {
+               printk(KERN_DEBUG "tcp_send_synack: wrong queue state\n");
+               return -EFAULT;
+       }
+       if (!(TCP_SKB_CB(skb)->flags&TCPCB_FLAG_ACK)) {
+               if (skb_cloned(skb)) {
+                       struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+                       if (nskb == NULL)
+                               return -ENOMEM;
+                       __skb_unlink(skb, &sk->write_queue);
+                       __skb_queue_head(&sk->write_queue, nskb);
+                       tcp_free_skb(sk, skb);
+                       tcp_charge_skb(sk, nskb);
+                       skb = nskb;
+               }
+
+               TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ACK;
+               TCP_ECN_send_synack(&sk->tp_pinfo.af_tcp, skb);
+       }
+       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+       return tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+#else
+  return 0;
+#endif
+}
+
+/*
+ * Prepare a SYN-ACK.
+ */
+struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+                                struct open_request *req)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct tcphdr *th;
+       int tcp_header_size;
+       struct sk_buff *skb;
+
+       skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
+       if (skb == NULL)
+               return NULL;
+
+       /* Reserve space for headers. */
+       skb_reserve(skb, MAX_TCP_HEADER);
+
+       skb->dst = dst_clone(dst);
+
+       tcp_header_size = (sizeof(struct tcphdr) + TCPOLEN_MSS +
+                          (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
+                          (req->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
+                          /* SACK_PERM is in the place of NOP NOP of TS */
+                          ((req->sack_ok && !req->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+       skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+
+       memset(th, 0, sizeof(struct tcphdr));
+       th->syn = 1;
+       th->ack = 1;
+       TCP_ECN_make_synack(req, th);
+       th->source = sk->sport;
+       th->dest = req->rmt_port;
+       TCP_SKB_CB(skb)->seq = req->snt_isn;
+       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+       th->seq = htonl(TCP_SKB_CB(skb)->seq);
+       th->ack_seq = htonl(req->rcv_isn + 1);
+       if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
+               __u8 rcv_wscale; 
+               /* Set this up on the first call only */
+               req->window_clamp = tp->window_clamp ? : dst->window;
+               /* tcp_full_space because it is guaranteed to be the first packet */
+               tcp_select_initial_window(tcp_full_space(sk), 
+                       dst->advmss - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
+                       &req->rcv_wnd,
+                       &req->window_clamp,
+                       req->wscale_ok,
+                       &rcv_wscale);
+               req->rcv_wscale = rcv_wscale; 
+       }
+
+       /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
+       th->window = htons(req->rcv_wnd);
+
+       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+       tcp_syn_build_options((__u32 *)(th + 1), dst->advmss, req->tstamp_ok,
+                             req->sack_ok, req->wscale_ok, req->rcv_wscale,
+                             TCP_SKB_CB(skb)->when,
+                             req->ts_recent);
+
+       skb->csum = 0;
+       th->doff = (tcp_header_size >> 2);
+       TCP_INC_STATS(TcpOutSegs);
+       return skb;
+#else
+  return 0;
+#endif
+}
+
+/* 
+ * Do all connect socket setups that can be done AF independent.
+ */ 
+static inline void tcp_connect_init(struct sock *sk)
+{
+#if 0
+       struct dst_entry *dst = __sk_dst_get(sk);
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /* We'll fix this up when we get a response from the other end.
+        * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
+        */
+       tp->tcp_header_len = sizeof(struct tcphdr) +
+               (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+
+       /* If user gave his TCP_MAXSEG, record it to clamp */
+       if (tp->user_mss)
+               tp->mss_clamp = tp->user_mss;
+       tp->max_window = 0;
+       tcp_sync_mss(sk, dst->pmtu);
+
+       if (!tp->window_clamp)
+               tp->window_clamp = dst->window;
+       tp->advmss = dst->advmss;
+       tcp_initialize_rcv_mss(sk);
+
+       tcp_select_initial_window(tcp_full_space(sk),
+                                 tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
+                                 &tp->rcv_wnd,
+                                 &tp->window_clamp,
+                                 sysctl_tcp_window_scaling,
+                                 &tp->rcv_wscale);
+
+       tp->rcv_ssthresh = tp->rcv_wnd;
+
+       sk->err = 0;
+       sk->done = 0;
+       tp->snd_wnd = 0;
+       tcp_init_wl(tp, tp->write_seq, 0);
+       tp->snd_una = tp->write_seq;
+       tp->snd_sml = tp->write_seq;
+       tp->rcv_nxt = 0;
+       tp->rcv_wup = 0;
+       tp->copied_seq = 0;
+
+       tp->rto = TCP_TIMEOUT_INIT;
+       tp->retransmits = 0;
+       tcp_clear_retrans(tp);
+#endif
+}
+
+/*
+ * Build a SYN and send it off.
+ */ 
+int tcp_connect(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *buff;
+
+       tcp_connect_init(sk);
+
+       buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
+       if (unlikely(buff == NULL))
+               return -ENOBUFS;
+
+       /* Reserve space for headers. */
+       skb_reserve(buff, MAX_TCP_HEADER);
+
+       TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
+       TCP_ECN_send_syn(tp, buff);
+       TCP_SKB_CB(buff)->sacked = 0;
+       buff->csum = 0;
+       TCP_SKB_CB(buff)->seq = tp->write_seq++;
+       TCP_SKB_CB(buff)->end_seq = tp->write_seq;
+       tp->snd_nxt = tp->write_seq;
+       tp->pushed_seq = tp->write_seq;
+
+       /* Send it off. */
+       TCP_SKB_CB(buff)->when = tcp_time_stamp;
+       tp->retrans_stamp = TCP_SKB_CB(buff)->when;
+       __skb_queue_tail(&sk->write_queue, buff);
+       tcp_charge_skb(sk, buff);
+       tp->packets_out++;
+       tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
+       TCP_INC_STATS(TcpActiveOpens);
+
+       /* Timer for repeating the SYN until an answer. */
+       tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+/* Send out a delayed ack, the caller does the policy checking
+ * to see if we should even be here.  See tcp_input.c:tcp_ack_snd_check()
+ * for details.
+ */
+void tcp_send_delayed_ack(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       int ato = tp->ack.ato;
+       unsigned long timeout;
+
+       if (ato > TCP_DELACK_MIN) {
+               int max_ato = HZ/2;
+
+               if (tp->ack.pingpong || (tp->ack.pending&TCP_ACK_PUSHED))
+                       max_ato = TCP_DELACK_MAX;
+
+               /* Slow path, intersegment interval is "high". */
+
+               /* If some rtt estimate is known, use it to bound delayed ack.
+                * Do not use tp->rto here, use results of rtt measurements
+                * directly.
+                */
+               if (tp->srtt) {
+                       int rtt = max(tp->srtt>>3, TCP_DELACK_MIN);
+
+                       if (rtt < max_ato)
+                               max_ato = rtt;
+               }
+
+               ato = min(ato, max_ato);
+       }
+
+       /* Stay within the limit we were given */
+       timeout = jiffies + ato;
+
+       /* Use new timeout only if there wasn't a older one earlier. */
+       if (tp->ack.pending&TCP_ACK_TIMER) {
+               /* If delack timer was blocked or is about to expire,
+                * send ACK now.
+                */
+               if (tp->ack.blocked || time_before_eq(tp->ack.timeout, jiffies+(ato>>2))) {
+                       tcp_send_ack(sk);
+                       return;
+               }
+
+               if (!time_before(timeout, tp->ack.timeout))
+                       timeout = tp->ack.timeout;
+       }
+       tp->ack.pending |= TCP_ACK_SCHED|TCP_ACK_TIMER;
+       tp->ack.timeout = timeout;
+       if (!mod_timer(&tp->delack_timer, timeout))
+               sock_hold(sk);
+#endif
+}
+
+/* This routine sends an ack and also updates the window. */
+void tcp_send_ack(struct sock *sk)
+{
+#if 0
+       /* If we have been reset, we may not send again. */
+       if(sk->state != TCP_CLOSE) {
+               struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+               struct sk_buff *buff;
+
+               /* We are not putting this on the write queue, so
+                * tcp_transmit_skb() will set the ownership to this
+                * sock.
+                */
+               buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
+               if (buff == NULL) {
+                       tcp_schedule_ack(tp);
+                       tp->ack.ato = TCP_ATO_MIN;
+                       tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+                       return;
+               }
+
+               /* Reserve space for headers and prepare control bits. */
+               skb_reserve(buff, MAX_TCP_HEADER);
+               buff->csum = 0;
+               TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
+               TCP_SKB_CB(buff)->sacked = 0;
+
+               /* Send it off, this clears delayed acks for us. */
+               TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
+               TCP_SKB_CB(buff)->when = tcp_time_stamp;
+               tcp_transmit_skb(sk, buff);
+       }
+#else
+  return 0;
+#endif
+}
+
+/* This routine sends a packet with an out of date sequence
+ * number. It assumes the other end will try to ack it.
+ *
+ * Question: what should we make while urgent mode?
+ * 4.4BSD forces sending single byte of data. We cannot send
+ * out of window data, because we have SND.NXT==SND.MAX...
+ *
+ * Current solution: to send TWO zero-length segments in urgent mode:
+ * one is with SEG.SEQ=SND.UNA to deliver urgent pointer, another is
+ * out-of-date with SND.UNA-1 to probe window.
+ */
+static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct sk_buff *skb;
+
+       /* We don't queue it, tcp_transmit_skb() sets ownership. */
+       skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
+       if (skb == NULL) 
+               return -1;
+
+       /* Reserve space for headers and set control bits. */
+       skb_reserve(skb, MAX_TCP_HEADER);
+       skb->csum = 0;
+       TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+       TCP_SKB_CB(skb)->sacked = urgent;
+
+       /* Use a previous sequence.  This should cause the other
+        * end to send an ack.  Don't queue or clone SKB, just
+        * send it.
+        */
+       TCP_SKB_CB(skb)->seq = urgent ? tp->snd_una : tp->snd_una - 1;
+       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+       return tcp_transmit_skb(sk, skb);
+#else
+  return 0;
+#endif
+}
+
+int tcp_write_wakeup(struct sock *sk)
+{
+#if 0
+       if (sk->state != TCP_CLOSE) {
+               struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+               struct sk_buff *skb;
+
+               if ((skb = tp->send_head) != NULL &&
+                   before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
+                       int err;
+                       int mss = tcp_current_mss(sk);
+                       int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
+
+                       if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq))
+                               tp->pushed_seq = TCP_SKB_CB(skb)->end_seq;
+
+                       /* We are probing the opening of a window
+                        * but the window size is != 0
+                        * must have been a result SWS avoidance ( sender )
+                        */
+                       if (seg_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq ||
+                           skb->len > mss) {
+                               seg_size = min(seg_size, mss);
+                               TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+                               if (tcp_fragment(sk, skb, seg_size))
+                                       return -1;
+                       }
+                       TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+                       err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+                       if (!err) {
+                               update_send_head(sk, tp, skb);
+                       }
+                       return err;
+               } else {
+                       if (tp->urg_mode &&
+                           between(tp->snd_up, tp->snd_una+1, tp->snd_una+0xFFFF))
+                               tcp_xmit_probe_skb(sk, TCPCB_URG);
+                       return tcp_xmit_probe_skb(sk, 0);
+               }
+       }
+       return -1;
+#else
+  return 0;
+#endif
+}
+
+/* A window probe timeout has occurred.  If window is not closed send
+ * a partial packet else a zero probe.
+ */
+void tcp_send_probe0(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int err;
+
+       err = tcp_write_wakeup(sk);
+
+       if (tp->packets_out || !tp->send_head) {
+               /* Cancel probe timer, if it is not required. */
+               tp->probes_out = 0;
+               tp->backoff = 0;
+               return;
+       }
+
+       if (err <= 0) {
+               tp->backoff++;
+               tp->probes_out++;
+               tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0, 
+                                     min(tp->rto << tp->backoff, TCP_RTO_MAX));
+       } else {
+               /* If packet was not sent due to local congestion,
+                * do not backoff and do not remember probes_out.
+                * Let local senders to fight for local resources.
+                *
+                * Use accumulated backoff yet.
+                */
+               if (!tp->probes_out)
+                       tp->probes_out=1;
+               tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0, 
+                                     min(tp->rto << tp->backoff, TCP_RESOURCE_PROBE_INTERVAL));
+       }
+#endif
+}
diff --git a/drivers/net/tcpip/transport/tcp/tcp_timer.c b/drivers/net/tcpip/transport/tcp/tcp_timer.c
new file mode 100755 (executable)
index 0000000..031e7d6
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        transport/tcp/tcp_input.c
+ * PURPOSE:     Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version:    $Id$
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *             Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *             Florian La Roche, <flla@stud.uni-sb.de>
+ *             Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ *             Linus Torvalds, <torvalds@cs.helsinki.fi>
+ *             Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *             Matthew Dillon, <dillon@apollo.west.oic.com>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+#if 0
+#include <net/tcp.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_syn_retries = TCP_SYN_RETRIES; 
+int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; 
+//int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
+int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
+//int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
+int sysctl_tcp_retries1 = TCP_RETR1;
+int sysctl_tcp_retries2 = TCP_RETR2;
+int sysctl_tcp_orphan_retries;
+
+static void tcp_write_timer(unsigned long);
+static void tcp_delack_timer(unsigned long);
+static void tcp_keepalive_timer (unsigned long data);
+
+//const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
+
+/*
+ * Using different timers for retransmit, delayed acks and probes
+ * We may wish use just one timer maintaining a list of expire jiffies 
+ * to optimize.
+ */
+
+void tcp_init_xmit_timers(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       init_timer(&tp->retransmit_timer);
+       tp->retransmit_timer.function=&tcp_write_timer;
+       tp->retransmit_timer.data = (unsigned long) sk;
+       tp->pending = 0;
+
+       init_timer(&tp->delack_timer);
+       tp->delack_timer.function=&tcp_delack_timer;
+       tp->delack_timer.data = (unsigned long) sk;
+       tp->ack.pending = 0;
+
+       init_timer(&sk->timer);
+       sk->timer.function=&tcp_keepalive_timer;
+       sk->timer.data = (unsigned long) sk;
+#endif
+}
+
+void tcp_clear_xmit_timers(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       tp->pending = 0;
+       if (timer_pending(&tp->retransmit_timer) &&
+           del_timer(&tp->retransmit_timer))
+               __sock_put(sk);
+
+       tp->ack.pending = 0;
+       tp->ack.blocked = 0;
+       if (timer_pending(&tp->delack_timer) &&
+           del_timer(&tp->delack_timer))
+               __sock_put(sk);
+
+       if(timer_pending(&sk->timer) && del_timer(&sk->timer))
+               __sock_put(sk);
+#endif
+}
+
+static void tcp_write_err(struct sock *sk)
+{
+#if 0
+       sk->err = sk->err_soft ? : ETIMEDOUT;
+       sk->error_report(sk);
+
+       tcp_done(sk);
+       NET_INC_STATS_BH(TCPAbortOnTimeout);
+#endif
+}
+
+/* Do not allow orphaned sockets to eat all our resources.
+ * This is direct violation of TCP specs, but it is required
+ * to prevent DoS attacks. It is called when a retransmission timeout
+ * or zero probe timeout occurs on orphaned socket.
+ *
+ * Criterium is still not confirmed experimentally and may change.
+ * We kill the socket, if:
+ * 1. If number of orphaned sockets exceeds an administratively configured
+ *    limit.
+ * 2. If we have strong memory pressure.
+ */
+static int tcp_out_of_resources(struct sock *sk, int do_reset)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int orphans = atomic_read(&tcp_orphan_count);
+
+       /* If peer does not open window for long time, or did not transmit 
+        * anything for long time, penalize it. */
+       if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
+               orphans <<= 1;
+
+       /* If some dubious ICMP arrived, penalize even more. */
+       if (sk->err_soft)
+               orphans <<= 1;
+
+       if (orphans >= sysctl_tcp_max_orphans ||
+           (sk->wmem_queued > SOCK_MIN_SNDBUF &&
+            atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+               if (net_ratelimit())
+                       printk(KERN_INFO "Out of socket memory\n");
+
+               /* Catch exceptional cases, when connection requires reset.
+                *      1. Last segment was sent recently. */
+               if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
+                   /*  2. Window is closed. */
+                   (!tp->snd_wnd && !tp->packets_out))
+                       do_reset = 1;
+               if (do_reset)
+                       tcp_send_active_reset(sk, GFP_ATOMIC);
+               tcp_done(sk);
+               NET_INC_STATS_BH(TCPAbortOnMemory);
+               return 1;
+       }
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+/* Calculate maximal number or retries on an orphaned socket. */
+static int tcp_orphan_retries(struct sock *sk, int alive)
+{
+#if 0
+       int retries = sysctl_tcp_orphan_retries; /* May be zero. */
+
+       /* We know from an ICMP that something is wrong. */
+       if (sk->err_soft && !alive)
+               retries = 0;
+
+       /* However, if socket sent something recently, select some safe
+        * number of retries. 8 corresponds to >100 seconds with minimal
+        * RTO of 200msec. */
+       if (retries == 0 && alive)
+               retries = 8;
+       return retries;
+#else
+       return 0;
+#endif
+}
+
+/* A write timeout has occurred. Process the after effects. */
+static int tcp_write_timeout(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int retry_until;
+
+       if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
+               if (tp->retransmits)
+                       dst_negative_advice(&sk->dst_cache);
+               retry_until = tp->syn_retries ? : sysctl_tcp_syn_retries;
+       } else {
+               if (tp->retransmits >= sysctl_tcp_retries1) {
+                       /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
+                          hole detection. :-(
+
+                          It is place to make it. It is not made. I do not want
+                          to make it. It is disguisting. It does not work in any
+                          case. Let me to cite the same draft, which requires for
+                          us to implement this:
+
+   "The one security concern raised by this memo is that ICMP black holes
+   are often caused by over-zealous security administrators who block
+   all ICMP messages.  It is vitally important that those who design and
+   deploy security systems understand the impact of strict filtering on
+   upper-layer protocols.  The safest web site in the world is worthless
+   if most TCP implementations cannot transfer data from it.  It would
+   be far nicer to have all of the black holes fixed rather than fixing
+   all of the TCP implementations."
+
+                           Golden words :-).
+                  */
+
+                       dst_negative_advice(&sk->dst_cache);
+               }
+
+               retry_until = sysctl_tcp_retries2;
+               if (sk->dead) {
+                       int alive = (tp->rto < TCP_RTO_MAX);
+                       retry_until = tcp_orphan_retries(sk, alive);
+
+                       if (tcp_out_of_resources(sk, alive || tp->retransmits < retry_until))
+                               return 1;
+               }
+       }
+
+       if (tp->retransmits >= retry_until) {
+               /* Has it gone just too far? */
+               tcp_write_err(sk);
+               return 1;
+       }
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+static void tcp_delack_timer(unsigned long data)
+{
+#if 0
+       struct sock *sk = (struct sock*)data;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       bh_lock_sock(sk);
+       if (sk->lock.users) {
+               /* Try again later. */
+               tp->ack.blocked = 1;
+               NET_INC_STATS_BH(DelayedACKLocked);
+               if (!mod_timer(&tp->delack_timer, jiffies + TCP_DELACK_MIN))
+                       sock_hold(sk);
+               goto out_unlock;
+       }
+
+       tcp_mem_reclaim(sk);
+
+       if (sk->state == TCP_CLOSE || !(tp->ack.pending&TCP_ACK_TIMER))
+               goto out;
+
+       if ((long)(tp->ack.timeout - jiffies) > 0) {
+               if (!mod_timer(&tp->delack_timer, tp->ack.timeout))
+                       sock_hold(sk);
+               goto out;
+       }
+       tp->ack.pending &= ~TCP_ACK_TIMER;
+
+       if (skb_queue_len(&tp->ucopy.prequeue)) {
+               struct sk_buff *skb;
+
+               net_statistics[smp_processor_id()*2].TCPSchedulerFailed += skb_queue_len(&tp->ucopy.prequeue);
+
+               while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
+                       sk->backlog_rcv(sk, skb);
+
+               tp->ucopy.memory = 0;
+       }
+
+       if (tcp_ack_scheduled(tp)) {
+               if (!tp->ack.pingpong) {
+                       /* Delayed ACK missed: inflate ATO. */
+                       tp->ack.ato = min(tp->ack.ato << 1, tp->rto);
+               } else {
+                       /* Delayed ACK missed: leave pingpong mode and
+                        * deflate ATO.
+                        */
+                       tp->ack.pingpong = 0;
+                       tp->ack.ato = TCP_ATO_MIN;
+               }
+               tcp_send_ack(sk);
+               NET_INC_STATS_BH(DelayedACKs);
+       }
+       TCP_CHECK_TIMER(sk);
+
+out:
+       if (tcp_memory_pressure)
+               tcp_mem_reclaim(sk);
+out_unlock:
+       bh_unlock_sock(sk);
+       sock_put(sk);
+#endif
+}
+
+static void tcp_probe_timer(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       int max_probes;
+
+       if (tp->packets_out || !tp->send_head) {
+               tp->probes_out = 0;
+               return;
+       }
+
+       /* *WARNING* RFC 1122 forbids this
+        *
+        * It doesn't AFAIK, because we kill the retransmit timer -AK
+        *
+        * FIXME: We ought not to do it, Solaris 2.5 actually has fixing
+        * this behaviour in Solaris down as a bug fix. [AC]
+        *
+        * Let me to explain. probes_out is zeroed by incoming ACKs
+        * even if they advertise zero window. Hence, connection is killed only
+        * if we received no ACKs for normal connection timeout. It is not killed
+        * only because window stays zero for some time, window may be zero
+        * until armageddon and even later. We are in full accordance
+        * with RFCs, only probe timer combines both retransmission timeout
+        * and probe timeout in one bottle.                             --ANK
+        */
+       max_probes = sysctl_tcp_retries2;
+
+       if (sk->dead) {
+               int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
+               max_probes = tcp_orphan_retries(sk, alive);
+
+               if (tcp_out_of_resources(sk, alive || tp->probes_out <= max_probes))
+                       return;
+       }
+
+       if (tp->probes_out > max_probes) {
+               tcp_write_err(sk);
+       } else {
+               /* Only send another probe if we didn't close things up. */
+               tcp_send_probe0(sk);
+       }
+#endif
+}
+
+/*
+ *     The TCP retransmit timer.
+ */
+
+static void tcp_retransmit_timer(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+       if (tp->packets_out == 0)
+               goto out;
+
+       BUG_TRAP(!skb_queue_empty(&sk->write_queue));
+
+       if (tp->snd_wnd == 0 && !sk->dead &&
+           !((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) {
+               /* Receiver dastardly shrinks window. Our retransmits
+                * become zero probes, but we should not timeout this
+                * connection. If the socket is an orphan, time it out,
+                * we cannot allow such beasts to hang infinitely.
+                */
+#ifdef TCP_DEBUG
+               if (net_ratelimit())
+                       printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
+                              NIPQUAD(sk->daddr), htons(sk->dport), sk->num,
+                              tp->snd_una, tp->snd_nxt);
+#endif
+               if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
+                       tcp_write_err(sk);
+                       goto out;
+               }
+               tcp_enter_loss(sk, 0);
+               tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+               __sk_dst_reset(sk);
+               goto out_reset_timer;
+       }
+
+       if (tcp_write_timeout(sk))
+               goto out;
+
+       if (tp->retransmits == 0) {
+               if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
+                       if (tp->sack_ok) {
+                               if (tp->ca_state == TCP_CA_Recovery)
+                                       NET_INC_STATS_BH(TCPSackRecoveryFail);
+                               else
+                                       NET_INC_STATS_BH(TCPSackFailures);
+                       } else {
+                               if (tp->ca_state == TCP_CA_Recovery)
+                                       NET_INC_STATS_BH(TCPRenoRecoveryFail);
+                               else
+                                       NET_INC_STATS_BH(TCPRenoFailures);
+                       }
+               } else if (tp->ca_state == TCP_CA_Loss) {
+                       NET_INC_STATS_BH(TCPLossFailures);
+               } else {
+                       NET_INC_STATS_BH(TCPTimeouts);
+               }
+       }
+
+       tcp_enter_loss(sk, 0);
+
+       if (tcp_retransmit_skb(sk, skb_peek(&sk->write_queue)) > 0) {
+               /* Retransmission failed because of local congestion,
+                * do not backoff.
+                */
+               if (!tp->retransmits)
+                       tp->retransmits=1;
+               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,
+                                    min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));
+               goto out;
+       }
+
+       /* Increase the timeout each time we retransmit.  Note that
+        * we do not increase the rtt estimate.  rto is initialized
+        * from rtt, but increases here.  Jacobson (SIGCOMM 88) suggests
+        * that doubling rto each time is the least we can get away with.
+        * In KA9Q, Karn uses this for the first few times, and then
+        * goes to quadratic.  netBSD doubles, but only goes up to *64,
+        * and clamps at 1 to 64 sec afterwards.  Note that 120 sec is
+        * defined in the protocol as the maximum possible RTT.  I guess
+        * we'll have to use something other than TCP to talk to the
+        * University of Mars.
+        *
+        * PAWS allows us longer timeouts and large windows, so once
+        * implemented ftp to mars will work nicely. We will have to fix
+        * the 120 second clamps though!
+        */
+       tp->backoff++;
+       tp->retransmits++;
+
+out_reset_timer:
+       tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
+       tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+       if (tp->retransmits > sysctl_tcp_retries1)
+               __sk_dst_reset(sk);
+
+out:;
+#endif
+}
+
+static void tcp_write_timer(unsigned long data)
+{
+#if 0
+       struct sock *sk = (struct sock*)data;
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       int event;
+
+       bh_lock_sock(sk);
+       if (sk->lock.users) {
+               /* Try again later */
+               if (!mod_timer(&tp->retransmit_timer, jiffies + (HZ/20)))
+                       sock_hold(sk);
+               goto out_unlock;
+       }
+
+       if (sk->state == TCP_CLOSE || !tp->pending)
+               goto out;
+
+       if ((long)(tp->timeout - jiffies) > 0) {
+               if (!mod_timer(&tp->retransmit_timer, tp->timeout))
+                       sock_hold(sk);
+               goto out;
+       }
+
+       event = tp->pending;
+       tp->pending = 0;
+
+       switch (event) {
+       case TCP_TIME_RETRANS:
+               tcp_retransmit_timer(sk);
+               break;
+       case TCP_TIME_PROBE0:
+               tcp_probe_timer(sk);
+               break;
+       }
+       TCP_CHECK_TIMER(sk);
+
+out:
+       tcp_mem_reclaim(sk);
+out_unlock:
+       bh_unlock_sock(sk);
+       sock_put(sk);
+#endif
+}
+
+/*
+ *     Timer for listening sockets
+ */
+
+static void tcp_synack_timer(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct tcp_listen_opt *lopt = tp->listen_opt;
+       int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
+       int thresh = max_retries;
+       unsigned long now = jiffies;
+       struct open_request **reqp, *req;
+       int i, budget;
+
+       if (lopt == NULL || lopt->qlen == 0)
+               return;
+
+       /* Normally all the openreqs are young and become mature
+        * (i.e. converted to established socket) for first timeout.
+        * If synack was not acknowledged for 3 seconds, it means
+        * one of the following things: synack was lost, ack was lost,
+        * rtt is high or nobody planned to ack (i.e. synflood).
+        * When server is a bit loaded, queue is populated with old
+        * open requests, reducing effective size of queue.
+        * When server is well loaded, queue size reduces to zero
+        * after several minutes of work. It is not synflood,
+        * it is normal operation. The solution is pruning
+        * too old entries overriding normal timeout, when
+        * situation becomes dangerous.
+        *
+        * Essentially, we reserve half of room for young
+        * embrions; and abort old ones without pity, if old
+        * ones are about to clog our table.
+        */
+       if (lopt->qlen>>(lopt->max_qlen_log-1)) {
+               int young = (lopt->qlen_young<<1);
+
+               while (thresh > 2) {
+                       if (lopt->qlen < young)
+                               break;
+                       thresh--;
+                       young <<= 1;
+               }
+       }
+
+       if (tp->defer_accept)
+               max_retries = tp->defer_accept;
+
+       budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
+       i = lopt->clock_hand;
+
+       do {
+               reqp=&lopt->syn_table[i];
+               while ((req = *reqp) != NULL) {
+                       if ((long)(now - req->expires) >= 0) {
+                               if ((req->retrans < thresh ||
+                                    (req->acked && req->retrans < max_retries))
+                                   && !req->class->rtx_syn_ack(sk, req, NULL)) {
+                                       unsigned long timeo;
+
+                                       if (req->retrans++ == 0)
+                                               lopt->qlen_young--;
+                                       timeo = min((TCP_TIMEOUT_INIT << req->retrans),
+                                                   TCP_RTO_MAX);
+                                       req->expires = now + timeo;
+                                       reqp = &req->dl_next;
+                                       continue;
+                               }
+
+                               /* Drop this request */
+                               write_lock(&tp->syn_wait_lock);
+                               *reqp = req->dl_next;
+                               write_unlock(&tp->syn_wait_lock);
+                               lopt->qlen--;
+                               if (req->retrans == 0)
+                                       lopt->qlen_young--;
+                               tcp_openreq_free(req);
+                               continue;
+                       }
+                       reqp = &req->dl_next;
+               }
+
+               i = (i+1)&(TCP_SYNQ_HSIZE-1);
+
+       } while (--budget > 0);
+
+       lopt->clock_hand = i;
+
+       if (lopt->qlen)
+               tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
+#endif
+}
+
+void tcp_delete_keepalive_timer (struct sock *sk)
+{
+#if 0
+       if (timer_pending(&sk->timer) && del_timer (&sk->timer))
+               __sock_put(sk);
+#endif
+}
+
+void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
+{
+#if 0
+       if (!mod_timer(&sk->timer, jiffies+len))
+               sock_hold(sk);
+#endif
+}
+
+void tcp_set_keepalive(struct sock *sk, int val)
+{
+#if 0
+       if ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))
+               return;
+
+       if (val && !sk->keepopen)
+               tcp_reset_keepalive_timer(sk, keepalive_time_when(&sk->tp_pinfo.af_tcp));
+       else if (!val)
+               tcp_delete_keepalive_timer(sk);
+#endif
+}
+
+
+static void tcp_keepalive_timer (unsigned long data)
+{
+#if 0
+       struct sock *sk = (struct sock *) data;
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       __u32 elapsed;
+
+       /* Only process if socket is not in use. */
+       bh_lock_sock(sk);
+       if (sk->lock.users) {
+               /* Try again later. */ 
+               tcp_reset_keepalive_timer (sk, HZ/20);
+               goto out;
+       }
+
+       if (sk->state == TCP_LISTEN) {
+               tcp_synack_timer(sk);
+               goto out;
+       }
+
+       if (sk->state == TCP_FIN_WAIT2 && sk->dead) {
+               if (tp->linger2 >= 0) {
+                       int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
+
+                       if (tmo > 0) {
+                               tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+                               goto out;
+                       }
+               }
+               tcp_send_active_reset(sk, GFP_ATOMIC);
+               goto death;
+       }
+
+       if (!sk->keepopen || sk->state == TCP_CLOSE)
+               goto out;
+
+       elapsed = keepalive_time_when(tp);
+
+       /* It is alive without keepalive 8) */
+       if (tp->packets_out || tp->send_head)
+               goto resched;
+
+       elapsed = tcp_time_stamp - tp->rcv_tstamp;
+
+       if (elapsed >= keepalive_time_when(tp)) {
+               if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||
+                    (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {
+                       tcp_send_active_reset(sk, GFP_ATOMIC);
+                       tcp_write_err(sk);
+                       goto out;
+               }
+               if (tcp_write_wakeup(sk) <= 0) {
+                       tp->probes_out++;
+                       elapsed = keepalive_intvl_when(tp);
+               } else {
+                       /* If keepalive was lost due to local congestion,
+                        * try harder.
+                        */
+                       elapsed = TCP_RESOURCE_PROBE_INTERVAL;
+               }
+       } else {
+               /* It is tp->rcv_tstamp + keepalive_time_when(tp) */
+               elapsed = keepalive_time_when(tp) - elapsed;
+       }
+
+       TCP_CHECK_TIMER(sk);
+       tcp_mem_reclaim(sk);
+
+resched:
+       tcp_reset_keepalive_timer (sk, elapsed);
+       goto out;
+
+death: 
+       tcp_done(sk);
+
+out:
+       bh_unlock_sock(sk);
+       sock_put(sk);
+#endif
+}
diff --git a/drivers/net/tcpip/transport/tcp/tcpcore.c b/drivers/net/tcpip/transport/tcp/tcpcore.c
new file mode 100755 (executable)
index 0000000..eead0d6
--- /dev/null
@@ -0,0 +1,2783 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS TCP/IP protocol driver
+ * FILE:        transport/tcp/tcpcore.c
+ * PURPOSE:     Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET                An implementation of the TCP/IP protocol suite for the LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version:    $Id$
+ *
+ * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *             Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *             Florian La Roche, <flla@stud.uni-sb.de>
+ *             Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ *             Linus Torvalds, <torvalds@cs.helsinki.fi>
+ *             Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *             Matthew Dillon, <dillon@apollo.west.oic.com>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Jorge Cwik, <jorge@laser.satlink.net>
+ *
+ * Fixes:
+ *             Alan Cox        :       Numerous verify_area() calls
+ *             Alan Cox        :       Set the ACK bit on a reset
+ *             Alan Cox        :       Stopped it crashing if it closed while
+ *                                     sk->inuse=1 and was trying to connect
+ *                                     (tcp_err()).
+ *             Alan Cox        :       All icmp error handling was broken
+ *                                     pointers passed where wrong and the
+ *                                     socket was looked up backwards. Nobody
+ *                                     tested any icmp error code obviously.
+ *             Alan Cox        :       tcp_err() now handled properly. It
+ *                                     wakes people on errors. poll
+ *                                     behaves and the icmp error race
+ *                                     has gone by moving it into sock.c
+ *             Alan Cox        :       tcp_send_reset() fixed to work for
+ *                                     everything not just packets for
+ *                                     unknown sockets.
+ *             Alan Cox        :       tcp option processing.
+ *             Alan Cox        :       Reset tweaked (still not 100%) [Had
+ *                                     syn rule wrong]
+ *             Herp Rosmanith  :       More reset fixes
+ *             Alan Cox        :       No longer acks invalid rst frames.
+ *                                     Acking any kind of RST is right out.
+ *             Alan Cox        :       Sets an ignore me flag on an rst
+ *                                     receive otherwise odd bits of prattle
+ *                                     escape still
+ *             Alan Cox        :       Fixed another acking RST frame bug.
+ *                                     Should stop LAN workplace lockups.
+ *             Alan Cox        :       Some tidyups using the new skb list
+ *                                     facilities
+ *             Alan Cox        :       sk->keepopen now seems to work
+ *             Alan Cox        :       Pulls options out correctly on accepts
+ *             Alan Cox        :       Fixed assorted sk->rqueue->next errors
+ *             Alan Cox        :       PSH doesn't end a TCP read. Switched a
+ *                                     bit to skb ops.
+ *             Alan Cox        :       Tidied tcp_data to avoid a potential
+ *                                     nasty.
+ *             Alan Cox        :       Added some better commenting, as the
+ *                                     tcp is hard to follow
+ *             Alan Cox        :       Removed incorrect check for 20 * psh
+ *     Michael O'Reilly        :       ack < copied bug fix.
+ *     Johannes Stille         :       Misc tcp fixes (not all in yet).
+ *             Alan Cox        :       FIN with no memory -> CRASH
+ *             Alan Cox        :       Added socket option proto entries.
+ *                                     Also added awareness of them to accept.
+ *             Alan Cox        :       Added TCP options (SOL_TCP)
+ *             Alan Cox        :       Switched wakeup calls to callbacks,
+ *                                     so the kernel can layer network
+ *                                     sockets.
+ *             Alan Cox        :       Use ip_tos/ip_ttl settings.
+ *             Alan Cox        :       Handle FIN (more) properly (we hope).
+ *             Alan Cox        :       RST frames sent on unsynchronised
+ *                                     state ack error.
+ *             Alan Cox        :       Put in missing check for SYN bit.
+ *             Alan Cox        :       Added tcp_select_window() aka NET2E
+ *                                     window non shrink trick.
+ *             Alan Cox        :       Added a couple of small NET2E timer
+ *                                     fixes
+ *             Charles Hedrick :       TCP fixes
+ *             Toomas Tamm     :       TCP window fixes
+ *             Alan Cox        :       Small URG fix to rlogin ^C ack fight
+ *             Charles Hedrick :       Rewrote most of it to actually work
+ *             Linus           :       Rewrote tcp_read() and URG handling
+ *                                     completely
+ *             Gerhard Koerting:       Fixed some missing timer handling
+ *             Matthew Dillon  :       Reworked TCP machine states as per RFC
+ *             Gerhard Koerting:       PC/TCP workarounds
+ *             Adam Caldwell   :       Assorted timer/timing errors
+ *             Matthew Dillon  :       Fixed another RST bug
+ *             Alan Cox        :       Move to kernel side addressing changes.
+ *             Alan Cox        :       Beginning work on TCP fastpathing
+ *                                     (not yet usable)
+ *             Arnt Gulbrandsen:       Turbocharged tcp_check() routine.
+ *             Alan Cox        :       TCP fast path debugging
+ *             Alan Cox        :       Window clamping
+ *             Michael Riepe   :       Bug in tcp_check()
+ *             Matt Dillon     :       More TCP improvements and RST bug fixes
+ *             Matt Dillon     :       Yet more small nasties remove from the
+ *                                     TCP code (Be very nice to this man if
+ *                                     tcp finally works 100%) 8)
+ *             Alan Cox        :       BSD accept semantics.
+ *             Alan Cox        :       Reset on closedown bug.
+ *     Peter De Schrijver      :       ENOTCONN check missing in tcp_sendto().
+ *             Michael Pall    :       Handle poll() after URG properly in
+ *                                     all cases.
+ *             Michael Pall    :       Undo the last fix in tcp_read_urg()
+ *                                     (multi URG PUSH broke rlogin).
+ *             Michael Pall    :       Fix the multi URG PUSH problem in
+ *                                     tcp_readable(), poll() after URG
+ *                                     works now.
+ *             Michael Pall    :       recv(...,MSG_OOB) never blocks in the
+ *                                     BSD api.
+ *             Alan Cox        :       Changed the semantics of sk->socket to
+ *                                     fix a race and a signal problem with
+ *                                     accept() and async I/O.
+ *             Alan Cox        :       Relaxed the rules on tcp_sendto().
+ *             Yury Shevchuk   :       Really fixed accept() blocking problem.
+ *             Craig I. Hagan  :       Allow for BSD compatible TIME_WAIT for
+ *                                     clients/servers which listen in on
+ *                                     fixed ports.
+ *             Alan Cox        :       Cleaned the above up and shrank it to
+ *                                     a sensible code size.
+ *             Alan Cox        :       Self connect lockup fix.
+ *             Alan Cox        :       No connect to multicast.
+ *             Ross Biro       :       Close unaccepted children on master
+ *                                     socket close.
+ *             Alan Cox        :       Reset tracing code.
+ *             Alan Cox        :       Spurious resets on shutdown.
+ *             Alan Cox        :       Giant 15 minute/60 second timer error
+ *             Alan Cox        :       Small whoops in polling before an
+ *                                     accept.
+ *             Alan Cox        :       Kept the state trace facility since
+ *                                     it's handy for debugging.
+ *             Alan Cox        :       More reset handler fixes.
+ *             Alan Cox        :       Started rewriting the code based on
+ *                                     the RFC's for other useful protocol
+ *                                     references see: Comer, KA9Q NOS, and
+ *                                     for a reference on the difference
+ *                                     between specifications and how BSD
+ *                                     works see the 4.4lite source.
+ *             A.N.Kuznetsov   :       Don't time wait on completion of tidy
+ *                                     close.
+ *             Linus Torvalds  :       Fin/Shutdown & copied_seq changes.
+ *             Linus Torvalds  :       Fixed BSD port reuse to work first syn
+ *             Alan Cox        :       Reimplemented timers as per the RFC
+ *                                     and using multiple timers for sanity.
+ *             Alan Cox        :       Small bug fixes, and a lot of new
+ *                                     comments.
+ *             Alan Cox        :       Fixed dual reader crash by locking
+ *                                     the buffers (much like datagram.c)
+ *             Alan Cox        :       Fixed stuck sockets in probe. A probe
+ *                                     now gets fed up of retrying without
+ *                                     (even a no space) answer.
+ *             Alan Cox        :       Extracted closing code better
+ *             Alan Cox        :       Fixed the closing state machine to
+ *                                     resemble the RFC.
+ *             Alan Cox        :       More 'per spec' fixes.
+ *             Jorge Cwik      :       Even faster checksumming.
+ *             Alan Cox        :       tcp_data() doesn't ack illegal PSH
+ *                                     only frames. At least one pc tcp stack
+ *                                     generates them.
+ *             Alan Cox        :       Cache last socket.
+ *             Alan Cox        :       Per route irtt.
+ *             Matt Day        :       poll()->select() match BSD precisely on error
+ *             Alan Cox        :       New buffers
+ *             Marc Tamsky     :       Various sk->prot->retransmits and
+ *                                     sk->retransmits misupdating fixed.
+ *                                     Fixed tcp_write_timeout: stuck close,
+ *                                     and TCP syn retries gets used now.
+ *             Mark Yarvis     :       In tcp_read_wakeup(), don't send an
+ *                                     ack if state is TCP_CLOSED.
+ *             Alan Cox        :       Look up device on a retransmit - routes may
+ *                                     change. Doesn't yet cope with MSS shrink right
+ *                                     but its a start!
+ *             Marc Tamsky     :       Closing in closing fixes.
+ *             Mike Shaver     :       RFC1122 verifications.
+ *             Alan Cox        :       rcv_saddr errors.
+ *             Alan Cox        :       Block double connect().
+ *             Alan Cox        :       Small hooks for enSKIP.
+ *             Alexey Kuznetsov:       Path MTU discovery.
+ *             Alan Cox        :       Support soft errors.
+ *             Alan Cox        :       Fix MTU discovery pathological case
+ *                                     when the remote claims no mtu!
+ *             Marc Tamsky     :       TCP_CLOSE fix.
+ *             Colin (G3TNE)   :       Send a reset on syn ack replies in
+ *                                     window but wrong (fixes NT lpd problems)
+ *             Pedro Roque     :       Better TCP window handling, delayed ack.
+ *             Joerg Reuter    :       No modification of locked buffers in
+ *                                     tcp_do_retransmit()
+ *             Eric Schenk     :       Changed receiver side silly window
+ *                                     avoidance algorithm to BSD style
+ *                                     algorithm. This doubles throughput
+ *                                     against machines running Solaris,
+ *                                     and seems to result in general
+ *                                     improvement.
+ *     Stefan Magdalinski      :       adjusted tcp_readable() to fix FIONREAD
+ *     Willy Konynenberg       :       Transparent proxying support.
+ *     Mike McLagan            :       Routing by source
+ *             Keith Owens     :       Do proper merging with partial SKB's in
+ *                                     tcp_do_sendmsg to avoid burstiness.
+ *             Eric Schenk     :       Fix fast close down bug with
+ *                                     shutdown() followed by close().
+ *             Andi Kleen      :       Make poll agree with SIGIO
+ *     Salvatore Sanfilippo    :       Support SO_LINGER with linger == 1 and
+ *                                     lingertime == 0 (RFC 793 ABORT Call)
+ *                                     
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or(at your option) any later version.
+ *
+ * Description of States:
+ *
+ *     TCP_SYN_SENT            sent a connection request, waiting for ack
+ *
+ *     TCP_SYN_RECV            received a connection request, sent ack,
+ *                             waiting for final ack in three-way handshake.
+ *
+ *     TCP_ESTABLISHED         connection established
+ *
+ *     TCP_FIN_WAIT1           our side has shutdown, waiting to complete
+ *                             transmission of remaining buffered data
+ *
+ *     TCP_FIN_WAIT2           all buffered data sent, waiting for remote
+ *                             to shutdown
+ *
+ *     TCP_CLOSING             both sides have shutdown but we still have
+ *                             data we have to finish sending
+ *
+ *     TCP_TIME_WAIT           timeout to catch resent junk before entering
+ *                             closed, can only be entered from FIN_WAIT2
+ *                             or CLOSING.  Required because the other end
+ *                             may not have gotten our last ACK causing it
+ *                             to retransmit the data packet (which we ignore)
+ *
+ *     TCP_CLOSE_WAIT          remote side has shutdown and is waiting for
+ *                             us to finish writing our data and to shutdown
+ *                             (we have to close() to move on to LAST_ACK)
+ *
+ *     TCP_LAST_ACK            out side has shutdown after remote has
+ *                             shutdown.  There may still be data in our
+ *                             buffer that we have to finish sending
+ *
+ *     TCP_CLOSE               socket is finished
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/fs.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+#include <asm/ioctls.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
+
+#ifdef ROS_STATISTICS
+struct tcp_mib tcp_statistics[NR_CPUS*2];
+#endif
+
+kmem_cache_t *tcp_openreq_cachep;
+kmem_cache_t *tcp_bucket_cachep;
+kmem_cache_t *tcp_timewait_cachep;
+
+#if 0
+atomic_t tcp_orphan_count = ATOMIC_INIT(0);
+#endif
+
+int sysctl_tcp_mem[3];
+int sysctl_tcp_wmem[3] = { 4*1024, 16*1024, 128*1024 };
+int sysctl_tcp_rmem[3] = { 4*1024, 87380, 87380*2 };
+
+atomic_t tcp_memory_allocated; /* Current allocated memory. */
+atomic_t tcp_sockets_allocated;        /* Current number of TCP sockets. */
+
+/* Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
+ * All the tcp_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency. */
+int tcp_memory_pressure;
+
+#define TCP_PAGES(amt) (((amt)+TCP_MEM_QUANTUM-1)/TCP_MEM_QUANTUM)
+
+int tcp_mem_schedule(struct sock *sk, int size, int kind)
+{
+       int amt = TCP_PAGES(size);
+
+       sk->forward_alloc += amt*TCP_MEM_QUANTUM;
+       atomic_add(amt, &tcp_memory_allocated);
+
+       /* Under limit. */
+       if (atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
+               if (tcp_memory_pressure)
+                       tcp_memory_pressure = 0;
+               return 1;
+       }
+
+       /* Over hard limit. */
+       if (atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) {
+               tcp_enter_memory_pressure();
+               goto suppress_allocation;
+       }
+
+       /* Under pressure. */
+       if (atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[1])
+               tcp_enter_memory_pressure();
+
+       if (kind) {
+               if (atomic_read(&sk->rmem_alloc) < sysctl_tcp_rmem[0])
+                       return 1;
+       } else {
+               if (sk->wmem_queued < sysctl_tcp_wmem[0])
+                       return 1;
+       }
+
+       if (!tcp_memory_pressure ||
+           sysctl_tcp_mem[2] > atomic_read(&tcp_sockets_allocated)
+           * TCP_PAGES(sk->wmem_queued+atomic_read(&sk->rmem_alloc)+
+                       sk->forward_alloc))
+               return 1;
+
+suppress_allocation:
+
+       if (kind == 0) {
+               tcp_moderate_sndbuf(sk);
+
+               /* Fail only if socket is _under_ its sndbuf.
+                * In this case we cannot block, so that we have to fail.
+                */
+               if (sk->wmem_queued+size >= sk->sndbuf)
+                       return 1;
+       }
+
+       /* Alas. Undo changes. */
+       sk->forward_alloc -= amt*TCP_MEM_QUANTUM;
+       atomic_sub(amt, &tcp_memory_allocated);
+       return 0;
+}
+
+void __tcp_mem_reclaim(struct sock *sk)
+{
+       if (sk->forward_alloc >= TCP_MEM_QUANTUM) {
+               atomic_sub(sk->forward_alloc/TCP_MEM_QUANTUM, &tcp_memory_allocated);
+               sk->forward_alloc &= (TCP_MEM_QUANTUM-1);
+               if (tcp_memory_pressure &&
+                   atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
+                       tcp_memory_pressure = 0;
+       }
+}
+
+void tcp_rfree(struct sk_buff *skb)
+{
+       struct sock *sk = skb->sk;
+
+       atomic_sub(skb->truesize, &sk->rmem_alloc);
+       sk->forward_alloc += skb->truesize;
+}
+
+/*
+ * LISTEN is a special case for poll..
+ */
+static __inline__ unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait)
+{
+       return sk->tp_pinfo.af_tcp.accept_queue ? (POLLIN | POLLRDNORM) : 0;
+}
+
+/*
+ *     Wait for a TCP event.
+ *
+ *     Note that we don't need to lock the socket, as the upper poll layers
+ *     take care of normal races (between the test and the event) and we don't
+ *     go look at any of the socket buffers directly.
+ */
+unsigned int tcp_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+#if 0
+       unsigned int mask;
+       struct sock *sk = sock->sk;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       poll_wait(file, sk->sleep, wait);
+       if (sk->state == TCP_LISTEN)
+               return tcp_listen_poll(sk, wait);
+
+       /* Socket is not locked. We are protected from async events
+          by poll logic and correct handling of state changes
+          made by another threads is impossible in any case.
+        */
+
+       mask = 0;
+       if (sk->err)
+               mask = POLLERR;
+
+       /*
+        * POLLHUP is certainly not done right. But poll() doesn't
+        * have a notion of HUP in just one direction, and for a
+        * socket the read side is more interesting.
+        *
+        * Some poll() documentation says that POLLHUP is incompatible
+        * with the POLLOUT/POLLWR flags, so somebody should check this
+        * all. But careful, it tends to be safer to return too many
+        * bits than too few, and you can easily break real applications
+        * if you don't tell them that something has hung up!
+        *
+        * Check-me.
+        *
+        * Check number 1. POLLHUP is _UNMASKABLE_ event (see UNIX98 and
+        * our fs/select.c). It means that after we received EOF,
+        * poll always returns immediately, making impossible poll() on write()
+        * in state CLOSE_WAIT. One solution is evident --- to set POLLHUP
+        * if and only if shutdown has been made in both directions.
+        * Actually, it is interesting to look how Solaris and DUX
+        * solve this dilemma. I would prefer, if PULLHUP were maskable,
+        * then we could set it on SND_SHUTDOWN. BTW examples given
+        * in Stevens' books assume exactly this behaviour, it explains
+        * why PULLHUP is incompatible with POLLOUT.    --ANK
+        *
+        * NOTE. Check for TCP_CLOSE is added. The goal is to prevent
+        * blocking on fresh not-connected or disconnected socket. --ANK
+        */
+       if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE)
+               mask |= POLLHUP;
+       if (sk->shutdown & RCV_SHUTDOWN)
+               mask |= POLLIN | POLLRDNORM;
+
+       /* Connected? */
+       if ((1 << sk->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
+               /* Potential race condition. If read of tp below will
+                * escape above sk->state, we can be illegally awaken
+                * in SYN_* states. */
+               if ((tp->rcv_nxt != tp->copied_seq) &&
+                   (tp->urg_seq != tp->copied_seq ||
+                    tp->rcv_nxt != tp->copied_seq+1 ||
+                    sk->urginline || !tp->urg_data))
+                       mask |= POLLIN | POLLRDNORM;
+
+               if (!(sk->shutdown & SEND_SHUTDOWN)) {
+                       if (tcp_wspace(sk) >= tcp_min_write_space(sk)) {
+                               mask |= POLLOUT | POLLWRNORM;
+                       } else {  /* send SIGIO later */
+                               set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+                               set_bit(SOCK_NOSPACE, &sk->socket->flags);
+
+                               /* Race breaker. If space is freed after
+                                * wspace test but before the flags are set,
+                                * IO signal will be lost.
+                                */
+                               if (tcp_wspace(sk) >= tcp_min_write_space(sk))
+                                       mask |= POLLOUT | POLLWRNORM;
+                       }
+               }
+
+               if (tp->urg_data & TCP_URG_VALID)
+                       mask |= POLLPRI;
+       }
+       return mask;
+#else
+  return 0;
+#endif
+}
+
+/*
+ *     TCP socket write_space callback.
+ */
+void tcp_write_space(struct sock *sk)
+{
+#if 0
+       struct socket *sock = sk->socket;
+
+       if (tcp_wspace(sk) >= tcp_min_write_space(sk) && sock) {
+               clear_bit(SOCK_NOSPACE, &sock->flags);
+
+               if (sk->sleep && waitqueue_active(sk->sleep))
+                       wake_up_interruptible(sk->sleep);
+
+               if (sock->fasync_list && !(sk->shutdown&SEND_SHUTDOWN))
+                       sock_wake_async(sock, 2, POLL_OUT);
+       }
+#endif
+}
+
+int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int answ;
+
+       switch(cmd) {
+       case SIOCINQ:
+               if (sk->state == TCP_LISTEN)
+                       return(-EINVAL);
+
+               lock_sock(sk);
+               if ((1<<sk->state) & (TCPF_SYN_SENT|TCPF_SYN_RECV))
+                       answ = 0;
+               else if (sk->urginline || !tp->urg_data ||
+                        before(tp->urg_seq,tp->copied_seq) ||
+                        !before(tp->urg_seq,tp->rcv_nxt)) {
+                       answ = tp->rcv_nxt - tp->copied_seq;
+
+                       /* Subtract 1, if FIN is in queue. */
+                       if (answ && !skb_queue_empty(&sk->receive_queue))
+                               answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin;
+               } else
+                       answ = tp->urg_seq - tp->copied_seq;
+               release_sock(sk);
+               break;
+       case SIOCATMARK:
+               {
+                       answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
+                       break;
+               }
+       case SIOCOUTQ:
+               if (sk->state == TCP_LISTEN)
+                       return(-EINVAL);
+
+               if ((1<<sk->state) & (TCPF_SYN_SENT|TCPF_SYN_RECV))
+                       answ = 0;
+               else
+                       answ = tp->write_seq - tp->snd_una;
+               break;
+       default:
+               return(-ENOIOCTLCMD);
+       };
+
+       return put_user(answ, (int *)arg);
+#else
+return 0;
+#endif
+}
+
+
+int tcp_listen_start(struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct tcp_listen_opt *lopt;
+
+       sk->max_ack_backlog = 0;
+       sk->ack_backlog = 0;
+       tp->accept_queue = tp->accept_queue_tail = NULL;
+       tp->syn_wait_lock = RW_LOCK_UNLOCKED;
+       tcp_delack_init(tp);
+
+       lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
+       if (!lopt)
+               return -ENOMEM;
+
+       memset(lopt, 0, sizeof(struct tcp_listen_opt));
+       for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
+               if ((1<<lopt->max_qlen_log) >= sysctl_max_syn_backlog)
+                       break;
+
+       write_lock_bh(&tp->syn_wait_lock);
+       tp->listen_opt = lopt;
+       write_unlock_bh(&tp->syn_wait_lock);
+
+       /* There is race window here: we announce ourselves listening,
+        * but this transition is still not validated by get_port().
+        * It is OK, because this socket enters to hash table only
+        * after validation is complete.
+        */
+       sk->state = TCP_LISTEN;
+       if (sk->prot->get_port(sk, sk->num) == 0) {
+               sk->sport = htons(sk->num);
+
+               sk_dst_reset(sk);
+               sk->prot->hash(sk);
+
+               return 0;
+       }
+
+       sk->state = TCP_CLOSE;
+       write_lock_bh(&tp->syn_wait_lock);
+       tp->listen_opt = NULL;
+       write_unlock_bh(&tp->syn_wait_lock);
+       kfree(lopt);
+       return -EADDRINUSE;
+#endif
+}
+
+/*
+ *     This routine closes sockets which have been at least partially
+ *     opened, but not yet accepted.
+ */
+
+static void tcp_listen_stop (struct sock *sk)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       struct tcp_listen_opt *lopt = tp->listen_opt;
+       struct open_request *acc_req = tp->accept_queue;
+       struct open_request *req;
+       int i;
+
+       tcp_delete_keepalive_timer(sk);
+
+       /* make all the listen_opt local to us */
+       write_lock_bh(&tp->syn_wait_lock);
+       tp->listen_opt =NULL;
+       write_unlock_bh(&tp->syn_wait_lock);
+       tp->accept_queue = tp->accept_queue_tail = NULL;
+
+       if (lopt->qlen) {
+               for (i=0; i<TCP_SYNQ_HSIZE; i++) {
+                       while ((req = lopt->syn_table[i]) != NULL) {
+                               lopt->syn_table[i] = req->dl_next;
+                               lopt->qlen--;
+                               tcp_openreq_free(req);
+
+               /* Following specs, it would be better either to send FIN
+                * (and enter FIN-WAIT-1, it is normal close)
+                * or to send active reset (abort). 
+                * Certainly, it is pretty dangerous while synflood, but it is
+                * bad justification for our negligence 8)
+                * To be honest, we are not able to make either
+                * of the variants now.                 --ANK
+                */
+                       }
+               }
+       }
+       BUG_TRAP(lopt->qlen == 0);
+
+       kfree(lopt);
+
+       while ((req=acc_req) != NULL) {
+               struct sock *child = req->sk;
+
+               acc_req = req->dl_next;
+
+               local_bh_disable();
+               bh_lock_sock(child);
+               BUG_TRAP(child->lock.users==0);
+               sock_hold(child);
+
+               tcp_disconnect(child, O_NONBLOCK);
+
+               sock_orphan(child);
+
+               atomic_inc(&tcp_orphan_count);
+
+               tcp_destroy_sock(child);
+
+               bh_unlock_sock(child);
+               local_bh_enable();
+               sock_put(child);
+
+               tcp_acceptq_removed(sk);
+               tcp_openreq_fastfree(req);
+       }
+       BUG_TRAP(sk->ack_backlog == 0);
+#endif
+}
+
+/*
+ *     Wait for a socket to get into the connected state
+ *
+ *     Note: Must be called with the socket locked.
+ */
+static int wait_for_tcp_connect(struct sock * sk, int flags, long *timeo_p)
+{
+#if 0
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+
+       while((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
+               if(sk->err)
+                       return sock_error(sk);
+               if((1 << sk->state) &
+                  ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
+                       return -EPIPE;
+               if(!*timeo_p)
+                       return -EAGAIN;
+               if(signal_pending(tsk))
+                       return sock_intr_errno(*timeo_p);
+
+               __set_task_state(tsk, TASK_INTERRUPTIBLE);
+               add_wait_queue(sk->sleep, &wait);
+               sk->tp_pinfo.af_tcp.write_pending++;
+
+               release_sock(sk);
+               *timeo_p = schedule_timeout(*timeo_p);
+               lock_sock(sk);
+
+               __set_task_state(tsk, TASK_RUNNING);
+               remove_wait_queue(sk->sleep, &wait);
+               sk->tp_pinfo.af_tcp.write_pending--;
+       }
+       return 0;
+#else
+  return 0;
+#endif
+}
+
+static inline int tcp_memory_free(struct sock *sk)
+{
+       return sk->wmem_queued < sk->sndbuf;
+}
+
+/*
+ *     Wait for more memory for a socket
+ */
+static int wait_for_tcp_memory(struct sock * sk, long *timeo)
+{
+#if 0
+       int err = 0;
+       long vm_wait = 0;
+       long current_timeo = *timeo;
+       DECLARE_WAITQUEUE(wait, current);
+
+       if (tcp_memory_free(sk))
+               current_timeo = vm_wait = (net_random()%(HZ/5))+2;
+
+       add_wait_queue(sk->sleep, &wait);
+       for (;;) {
+               set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               if (sk->err || (sk->shutdown & SEND_SHUTDOWN))
+                       goto do_error;
+               if (!*timeo)
+                       goto do_nonblock;
+               if (signal_pending(current))
+                       goto do_interrupted;
+               clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+               if (tcp_memory_free(sk) && !vm_wait)
+                       break;
+
+               set_bit(SOCK_NOSPACE, &sk->socket->flags);
+               sk->tp_pinfo.af_tcp.write_pending++;
+               release_sock(sk);
+               if (!tcp_memory_free(sk) || vm_wait)
+                       current_timeo = schedule_timeout(current_timeo);
+               lock_sock(sk);
+               sk->tp_pinfo.af_tcp.write_pending--;
+
+               if (vm_wait) {
+                       vm_wait -= current_timeo;
+                       current_timeo = *timeo;
+                       if (current_timeo != MAX_SCHEDULE_TIMEOUT &&
+                           (current_timeo -= vm_wait) < 0)
+                               current_timeo = 0;
+                       vm_wait = 0;
+               }
+               *timeo = current_timeo;
+       }
+out:
+       current->state = TASK_RUNNING;
+       remove_wait_queue(sk->sleep, &wait);
+       return err;
+
+do_error:
+       err = -EPIPE;
+       goto out;
+do_nonblock:
+       err = -EAGAIN;
+       goto out;
+do_interrupted:
+       err = sock_intr_errno(*timeo);
+       goto out;
+#endif
+}
+
+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags);
+
+static inline int
+can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
+{
+#if 0
+       if (i) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+               return page == frag->page &&
+                       off == frag->page_offset+frag->size;
+       }
+       return 0;
+#else
+return 0;
+#endif
+}
+
+static inline void
+fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size)
+{
+       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+       frag->page = page;
+       frag->page_offset = off;
+       frag->size = size;
+       skb_shinfo(skb)->nr_frags = i+1;
+}
+
+static inline void tcp_mark_push(struct tcp_opt *tp, struct sk_buff *skb)
+{
+       TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+       tp->pushed_seq = tp->write_seq;
+}
+
+static inline int forced_push(struct tcp_opt *tp)
+{
+       return after(tp->write_seq, tp->pushed_seq + (tp->max_window>>1));
+}
+
+static inline void
+skb_entail(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+       skb->csum = 0;
+       TCP_SKB_CB(skb)->seq = tp->write_seq;
+       TCP_SKB_CB(skb)->end_seq = tp->write_seq;
+       TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+       TCP_SKB_CB(skb)->sacked = 0;
+       __skb_queue_tail(&sk->write_queue, skb);
+       tcp_charge_skb(sk, skb);
+       if (tp->send_head == NULL)
+               tp->send_head = skb;
+}
+
+static inline void
+tcp_mark_urg(struct tcp_opt *tp, int flags, struct sk_buff *skb)
+{
+#if 0
+       if (flags & MSG_OOB) {
+               tp->urg_mode = 1;
+               tp->snd_up = tp->write_seq;
+               TCP_SKB_CB(skb)->sacked |= TCPCB_URG;
+       }
+#endif
+}
+
+static inline void
+tcp_push(struct sock *sk, struct tcp_opt *tp, int flags, int mss_now, int nonagle)
+{
+#if 0
+       if (tp->send_head) {
+               struct sk_buff *skb = sk->write_queue.prev;
+               if (!(flags&MSG_MORE) || forced_push(tp))
+                       tcp_mark_push(tp, skb);
+               tcp_mark_urg(tp, flags, skb);
+               __tcp_push_pending_frames(sk, tp, mss_now, (flags&MSG_MORE) ? 2 : nonagle);
+       }
+#endif
+}
+
+static int tcp_error(struct sock *sk, int flags, int err)
+{
+#if 0
+       if (err == -EPIPE)
+               err = sock_error(sk) ? : -EPIPE;
+       if (err == -EPIPE && !(flags&MSG_NOSIGNAL))
+               send_sig(SIGPIPE, current, 0);
+       return err;
+#else
+  return 0;
+#endif
+}
+
+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int mss_now;
+       int err;
+       ssize_t copied;
+       long timeo = sock_sndtimeo(sk, flags&MSG_DONTWAIT);
+
+       /* Wait for a connection to finish. */
+       if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+               if((err = wait_for_tcp_connect(sk, 0, &timeo)) != 0)
+                       goto out_err;
+
+       clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+       mss_now = tcp_current_mss(sk);
+       copied = 0;
+
+       err = -EPIPE;
+       if (sk->err || (sk->shutdown & SEND_SHUTDOWN))
+               goto do_error;
+
+       while (psize > 0) {
+               struct sk_buff *skb = sk->write_queue.prev;
+               int offset, size, copy, i;
+               struct page *page;
+
+               page = pages[poffset/PAGE_SIZE];
+               offset = poffset % PAGE_SIZE;
+               size = min_t(size_t, psize, PAGE_SIZE-offset);
+
+               if (tp->send_head==NULL || (copy = mss_now - skb->len) <= 0) {
+new_segment:
+                       if (!tcp_memory_free(sk))
+                               goto wait_for_sndbuf;
+
+                       skb = tcp_alloc_pskb(sk, 0, tp->mss_cache, sk->allocation);
+                       if (skb == NULL)
+                               goto wait_for_memory;
+
+                       skb_entail(sk, tp, skb);
+                       copy = mss_now;
+               }
+
+               if (copy > size)
+                       copy = size;
+
+               i = skb_shinfo(skb)->nr_frags;
+               if (can_coalesce(skb, i, page, offset)) {
+                       skb_shinfo(skb)->frags[i-1].size += copy;
+               } else if (i < MAX_SKB_FRAGS) {
+                       get_page(page);
+                       fill_page_desc(skb, i, page, offset, copy);
+               } else {
+                       tcp_mark_push(tp, skb);
+                       goto new_segment;
+               }
+
+               skb->len += copy;
+               skb->data_len += copy;
+               skb->ip_summed = CHECKSUM_HW;
+               tp->write_seq += copy;
+               TCP_SKB_CB(skb)->end_seq += copy;
+
+               if (!copied)
+                       TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
+
+               copied += copy;
+               poffset += copy;
+               if (!(psize -= copy))
+                       goto out;
+
+               if (skb->len != mss_now || (flags&MSG_OOB))
+                       continue;
+
+               if (forced_push(tp)) {
+                       tcp_mark_push(tp, skb);
+                       __tcp_push_pending_frames(sk, tp, mss_now, 1);
+               } else if (skb == tp->send_head)
+                       tcp_push_one(sk, mss_now);
+               continue;
+
+wait_for_sndbuf:
+               set_bit(SOCK_NOSPACE, &sk->socket->flags);
+wait_for_memory:
+               if (copied)
+                       tcp_push(sk, tp, flags&~MSG_MORE, mss_now, 1);
+
+               if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+                       goto do_error;
+
+               mss_now = tcp_current_mss(sk);
+       }
+
+out:
+       if (copied)
+               tcp_push(sk, tp, flags, mss_now, tp->nonagle);
+       return copied;
+
+do_error:
+       if (copied)
+               goto out;
+out_err:
+       return tcp_error(sk, flags, err);
+#else 
+return 0;
+#endif
+}
+
+ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
+{
+#if 0
+       ssize_t res;
+       struct sock *sk = sock->sk;
+
+#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+
+       if (!(sk->route_caps & NETIF_F_SG) || 
+           !(sk->route_caps & TCP_ZC_CSUM_FLAGS))
+               return sock_no_sendpage(sock, page, offset, size, flags);
+
+#undef TCP_ZC_CSUM_FLAGS
+
+       lock_sock(sk);
+       TCP_CHECK_TIMER(sk);
+       res = do_tcp_sendpages(sk, &page, offset, size, flags);
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return res;
+#else
+  return 0;
+#endif
+}
+
+#define TCP_PAGE(sk)   (sk->tp_pinfo.af_tcp.sndmsg_page)
+#define TCP_OFF(sk)    (sk->tp_pinfo.af_tcp.sndmsg_off)
+
+static inline int
+tcp_copy_to_page(struct sock *sk, char *from, struct sk_buff *skb,
+                struct page *page, int off, int copy)
+{
+       int err = 0;
+       unsigned int csum;
+
+       csum = csum_and_copy_from_user(from, page_address(page)+off,
+                                      copy, 0, &err);
+       if (!err) {
+               if (skb->ip_summed == CHECKSUM_NONE)
+                       skb->csum = csum_block_add(skb->csum, csum, skb->len);
+               skb->len += copy;
+               skb->data_len += copy;
+               skb->truesize += copy;
+               sk->wmem_queued += copy;
+               sk->forward_alloc -= copy;
+       }
+       return err;
+}
+
+static inline int
+skb_add_data(struct sk_buff *skb, char *from, int copy)
+{
+#if 0
+       int err = 0;
+       unsigned int csum;
+       int off = skb->len;
+
+       csum = csum_and_copy_from_user(from, skb_put(skb, copy),
+                                      copy, 0, &err);
+       if (!err) {
+               skb->csum = csum_block_add(skb->csum, csum, off);
+               return 0;
+       }
+
+       __skb_trim(skb, off);
+       return -EFAULT;
+#else
+return 0;
+#endif
+}
+
+static inline int select_size(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+       int tmp = tp->mss_cache;
+
+       if (sk->route_caps&NETIF_F_SG) {
+               int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER);
+
+               if (tmp >= pgbreak && tmp <= pgbreak + (MAX_SKB_FRAGS-1)*PAGE_SIZE)
+                       tmp = pgbreak;
+       }
+       return tmp;
+#else
+  return 0;
+#endif
+}
+
+int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
+{
+#if 0
+       struct iovec *iov;
+       struct tcp_opt *tp;
+       struct sk_buff *skb;
+       int iovlen, flags;
+       int mss_now;
+       int err, copied;
+       long timeo;
+
+       tp = &(sk->tp_pinfo.af_tcp);
+
+       lock_sock(sk);
+       TCP_CHECK_TIMER(sk);
+
+       flags = msg->msg_flags;
+       timeo = sock_sndtimeo(sk, flags&MSG_DONTWAIT);
+
+       /* Wait for a connection to finish. */
+       if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+               if((err = wait_for_tcp_connect(sk, flags, &timeo)) != 0)
+                       goto out_err;
+
+       /* This should be in poll */
+       clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+       mss_now = tcp_current_mss(sk);
+
+       /* Ok commence sending. */
+       iovlen = msg->msg_iovlen;
+       iov = msg->msg_iov;
+       copied = 0;
+
+       err = -EPIPE;
+       if (sk->err || (sk->shutdown&SEND_SHUTDOWN))
+               goto do_error;
+
+       while (--iovlen >= 0) {
+               int seglen=iov->iov_len;
+               unsigned char * from=iov->iov_base;
+
+               iov++;
+
+               while (seglen > 0) {
+                       int copy;
+                       
+                       skb = sk->write_queue.prev;
+
+                       if (tp->send_head == NULL ||
+                           (copy = mss_now - skb->len) <= 0) {
+
+new_segment:
+                               /* Allocate new segment. If the interface is SG,
+                                * allocate skb fitting to single page.
+                                */
+                               if (!tcp_memory_free(sk))
+                                       goto wait_for_sndbuf;
+
+                               skb = tcp_alloc_pskb(sk, select_size(sk, tp), 0, sk->allocation);
+                               if (skb == NULL)
+                                       goto wait_for_memory;
+
+                               skb_entail(sk, tp, skb);
+                               copy = mss_now;
+                       }
+
+                       /* Try to append data to the end of skb. */
+                       if (copy > seglen)
+                               copy = seglen;
+
+                       /* Where to copy to? */
+                       if (skb_tailroom(skb) > 0) {
+                               /* We have some space in skb head. Superb! */
+                               if (copy > skb_tailroom(skb))
+                                       copy = skb_tailroom(skb);
+                               if ((err = skb_add_data(skb, from, copy)) != 0)
+                                       goto do_fault;
+                       } else {
+                               int merge = 0;
+                               int i = skb_shinfo(skb)->nr_frags;
+                               struct page *page = TCP_PAGE(sk);
+                               int off = TCP_OFF(sk);
+
+                               if (can_coalesce(skb, i, page, off) && off != PAGE_SIZE) {
+                                       /* We can extend the last page fragment. */
+                                       merge = 1;
+                               } else if (i == MAX_SKB_FRAGS ||
+                                          (i == 0 && !(sk->route_caps&NETIF_F_SG))) {
+                                       /* Need to add new fragment and cannot
+                                        * do this because interface is non-SG,
+                                        * or because all the page slots are busy.
+                                        */
+                                       tcp_mark_push(tp, skb);
+                                       goto new_segment;
+                               } else if (page) {
+                                       /* If page is cached, align
+                                        * offset to L1 cache boundary
+                                        */
+                                       off = (off+L1_CACHE_BYTES-1)&~(L1_CACHE_BYTES-1);
+                                       if (off == PAGE_SIZE) {
+                                               put_page(page);
+                                               TCP_PAGE(sk) = page = NULL;
+                                       }
+                               }
+
+                               if (!page) {
+                                       /* Allocate new cache page. */
+                                       if (!(page=tcp_alloc_page(sk)))
+                                               goto wait_for_memory;
+                                       off = 0;
+                               }
+
+                               if (copy > PAGE_SIZE-off)
+                                       copy = PAGE_SIZE-off;
+
+                               /* Time to copy data. We are close to the end! */
+                               err = tcp_copy_to_page(sk, from, skb, page, off, copy);
+                               if (err) {
+                                       /* If this page was new, give it to the
+                                        * socket so it does not get leaked.
+                                        */
+                                       if (TCP_PAGE(sk) == NULL) {
+                                               TCP_PAGE(sk) = page;
+                                               TCP_OFF(sk) = 0;
+                                       }
+                                       goto do_error;
+                               }
+
+                               /* Update the skb. */
+                               if (merge) {
+                                       skb_shinfo(skb)->frags[i-1].size += copy;
+                               } else {
+                                       fill_page_desc(skb, i, page, off, copy);
+                                       if (TCP_PAGE(sk)) {
+                                               get_page(page);
+                                       } else if (off + copy < PAGE_SIZE) {
+                                               get_page(page);
+                                               TCP_PAGE(sk) = page;
+                                       }
+                               }
+
+                               TCP_OFF(sk) = off+copy;
+                       }
+
+                       if (!copied)
+                               TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
+
+                       tp->write_seq += copy;
+                       TCP_SKB_CB(skb)->end_seq += copy;
+
+                       from += copy;
+                       copied += copy;
+                       if ((seglen -= copy) == 0 && iovlen == 0)
+                               goto out;
+
+                       if (skb->len != mss_now || (flags&MSG_OOB))
+                               continue;
+
+                       if (forced_push(tp)) {
+                               tcp_mark_push(tp, skb);
+                               __tcp_push_pending_frames(sk, tp, mss_now, 1);
+                       } else if (skb == tp->send_head)
+                               tcp_push_one(sk, mss_now);
+                       continue;
+
+wait_for_sndbuf:
+                       set_bit(SOCK_NOSPACE, &sk->socket->flags);
+wait_for_memory:
+                       if (copied)
+                               tcp_push(sk, tp, flags&~MSG_MORE, mss_now, 1);
+
+                       if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+                               goto do_error;
+
+                       mss_now = tcp_current_mss(sk);
+               }
+       }
+
+out:
+       if (copied)
+               tcp_push(sk, tp, flags, mss_now, tp->nonagle);
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return copied;
+
+do_fault:
+       if (skb->len == 0) {
+               if (tp->send_head == skb)
+                       tp->send_head = NULL;
+               __skb_unlink(skb, skb->list);
+               tcp_free_skb(sk, skb);
+       }
+
+do_error:
+       if (copied)
+               goto out;
+out_err:
+       err = tcp_error(sk, flags, err);
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return err;
+#else
+  return 0;
+#endif
+}
+
+/*
+ *     Handle reading urgent data. BSD has very simple semantics for
+ *     this, no blocking and very strange errors 8)
+ */
+
+static int tcp_recv_urg(struct sock * sk, long timeo,
+                       struct msghdr *msg, int len, int flags, 
+                       int *addr_len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       /* No URG data to read. */
+       if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ)
+               return -EINVAL; /* Yes this is right ! */
+
+       if (sk->state==TCP_CLOSE && !sk->done)
+               return -ENOTCONN;
+
+       if (tp->urg_data & TCP_URG_VALID) {
+               int err = 0; 
+               char c = tp->urg_data;
+
+               if (!(flags & MSG_PEEK))
+                       tp->urg_data = TCP_URG_READ;
+
+               /* Read urgent data. */
+               msg->msg_flags|=MSG_OOB;
+
+               if(len>0) {
+                       if (!(flags & MSG_TRUNC))
+                               err = memcpy_toiovec(msg->msg_iov, &c, 1);
+                       len = 1;
+               } else
+                       msg->msg_flags|=MSG_TRUNC;
+
+               return err ? -EFAULT : len;
+       }
+
+       if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN))
+               return 0;
+
+       /* Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
+        * the available implementations agree in this case:
+        * this call should never block, independent of the
+        * blocking state of the socket.
+        * Mike <pall@rz.uni-karlsruhe.de>
+        */
+       return -EAGAIN;
+#else
+return 0;
+#endif
+}
+
+/*
+ *     Release a skb if it is no longer needed. This routine
+ *     must be called with interrupts disabled or with the
+ *     socket locked so that the sk_buff queue operation is ok.
+ */
+
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
+{
+#if 0
+       __skb_unlink(skb, &sk->receive_queue);
+       __kfree_skb(skb);
+#endif
+}
+
+/* Clean up the receive buffer for full frames taken by the user,
+ * then send an ACK if necessary.  COPIED is the number of bytes
+ * tcp_recvmsg has given to the user so far, it speeds up the
+ * calculation of whether or not we must ACK for the sake of
+ * a window update.
+ */
+static void cleanup_rbuf(struct sock *sk, int copied)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int time_to_ack = 0;
+
+#if TCP_DEBUG
+       struct sk_buff *skb = skb_peek(&sk->receive_queue);
+
+       BUG_TRAP(skb==NULL || before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq));
+#endif
+
+       if (tcp_ack_scheduled(tp)) {
+                  /* Delayed ACKs frequently hit locked sockets during bulk receive. */
+               if (tp->ack.blocked
+                   /* Once-per-two-segments ACK was not sent by tcp_input.c */
+                   || tp->rcv_nxt - tp->rcv_wup > tp->ack.rcv_mss
+                   /*
+                    * If this read emptied read buffer, we send ACK, if
+                    * connection is not bidirectional, user drained
+                    * receive buffer and there was a small segment
+                    * in queue.
+                    */
+                   || (copied > 0 &&
+                       (tp->ack.pending&TCP_ACK_PUSHED) &&
+                       !tp->ack.pingpong &&
+                       atomic_read(&sk->rmem_alloc) == 0)) {
+                       time_to_ack = 1;
+               }
+       }
+
+       /* We send an ACK if we can now advertise a non-zero window
+        * which has been raised "significantly".
+        *
+        * Even if window raised up to infinity, do not send window open ACK
+        * in states, where we will not receive more. It is useless.
+        */
+       if(copied > 0 && !time_to_ack && !(sk->shutdown&RCV_SHUTDOWN)) {
+               __u32 rcv_window_now = tcp_receive_window(tp);
+
+               /* Optimize, __tcp_select_window() is not cheap. */
+               if (2*rcv_window_now <= tp->window_clamp) {
+                       __u32 new_window = __tcp_select_window(sk);
+
+                       /* Send ACK now, if this read freed lots of space
+                        * in our buffer. Certainly, new_window is new window.
+                        * We can advertise it now, if it is not less than current one.
+                        * "Lots" means "at least twice" here.
+                        */
+                       if(new_window && new_window >= 2*rcv_window_now)
+                               time_to_ack = 1;
+               }
+       }
+       if (time_to_ack)
+               tcp_send_ack(sk);
+#endif
+}
+
+/* Now socket state including sk->err is changed only under lock,
+ * hence we may omit checks after joining wait queue.
+ * We check receive queue before schedule() only as optimization;
+ * it is very likely that release_sock() added new data.
+ */
+
+static long tcp_data_wait(struct sock *sk, long timeo)
+{
+#if 0
+       DECLARE_WAITQUEUE(wait, current);
+
+       add_wait_queue(sk->sleep, &wait);
+
+       __set_current_state(TASK_INTERRUPTIBLE);
+
+       set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+       release_sock(sk);
+
+       if (skb_queue_empty(&sk->receive_queue))
+               timeo = schedule_timeout(timeo);
+
+       lock_sock(sk);
+       clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+
+       remove_wait_queue(sk->sleep, &wait);
+       __set_current_state(TASK_RUNNING);
+       return timeo;
+#else
+  return 0;
+#endif
+}
+
+static void tcp_prequeue_process(struct sock *sk)
+{
+#if 0
+       struct sk_buff *skb;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+       net_statistics[smp_processor_id()*2+1].TCPPrequeued += skb_queue_len(&tp->ucopy.prequeue);
+
+       /* RX process wants to run with disabled BHs, though it is not necessary */
+       local_bh_disable();
+       while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
+               sk->backlog_rcv(sk, skb);
+       local_bh_enable();
+
+       /* Clear memory counter. */
+       tp->ucopy.memory = 0;
+#endif
+}
+
+static inline
+struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
+{
+#if 0
+       struct sk_buff *skb;
+       u32 offset;
+
+       skb_queue_walk(&sk->receive_queue, skb) {
+               offset = seq - TCP_SKB_CB(skb)->seq;
+               if (skb->h.th->syn)
+                       offset--;
+               if (offset < skb->len || skb->h.th->fin) {
+                       *off = offset;
+                       return skb;
+               }
+       }
+       return NULL;
+#else
+       return NULL;
+#endif
+}
+
+/*
+ * This routine provides an alternative to tcp_recvmsg() for routines
+ * that would like to handle copying from skbuffs directly in 'sendfile'
+ * fashion.
+ * Note:
+ *     - It is assumed that the socket was locked by the caller.
+ *     - The routine does not block.
+ *     - At present, there is no support for reading OOB data
+ *       or for 'peeking' the socket using this routine
+ *       (although both would be easy to implement).
+ */
+int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+                 sk_read_actor_t recv_actor)
+{
+#if 0
+       struct sk_buff *skb;
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       u32 seq = tp->copied_seq;
+       u32 offset;
+       int copied = 0;
+
+       if (sk->state == TCP_LISTEN)
+               return -ENOTCONN;
+       while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
+               if (offset < skb->len) {
+                       size_t used, len;
+
+                       len = skb->len - offset;
+                       /* Stop reading if we hit a patch of urgent data */
+                       if (tp->urg_data) {
+                               u32 urg_offset = tp->urg_seq - seq;
+                               if (urg_offset < len)
+                                       len = urg_offset;
+                               if (!len)
+                                       break;
+                       }
+                       used = recv_actor(desc, skb, offset, len);
+                       if (used <= len) {
+                               seq += used;
+                               copied += used;
+                               offset += used;
+                       }
+                       if (offset != skb->len)
+                               break;
+               }
+               if (skb->h.th->fin) {
+                       tcp_eat_skb(sk, skb);
+                       ++seq;
+                       break;
+               }
+               tcp_eat_skb(sk, skb);
+               if (!desc->count)
+                       break;
+       }
+       tp->copied_seq = seq;
+       /* Clean up data we have read: This will do ACK frames. */
+       if (copied)
+               cleanup_rbuf(sk, copied);
+       return copied;
+#else
+#endif
+}
+
+/*
+ *     This routine copies from a sock struct into the user buffer. 
+ *
+ *     Technical note: in 2.3 we work on _locked_ socket, so that
+ *     tricks with *seq access order and skb->users are not required.
+ *     Probably, code can be easily improved even more.
+ */
+int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
+               int len, int nonblock, int flags, int *addr_len)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int copied = 0;
+       u32 peek_seq;
+       u32 *seq;
+       unsigned long used;
+       int err;
+       int target;             /* Read at least this many bytes */
+       long timeo;
+       struct task_struct *user_recv = NULL;
+
+       lock_sock(sk);
+
+       TCP_CHECK_TIMER(sk);
+
+       err = -ENOTCONN;
+       if (sk->state == TCP_LISTEN)
+               goto out;
+
+       timeo = sock_rcvtimeo(sk, nonblock);
+
+       /* Urgent data needs to be handled specially. */
+       if (flags & MSG_OOB)
+               goto recv_urg;
+
+       seq = &tp->copied_seq;
+       if (flags & MSG_PEEK) {
+               peek_seq = tp->copied_seq;
+               seq = &peek_seq;
+       }
+
+       target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+
+       do {
+               struct sk_buff * skb;
+               u32 offset;
+
+               /* Are we at urgent data? Stop if we have read anything. */
+               if (copied && tp->urg_data && tp->urg_seq == *seq)
+                       break;
+
+               /* We need to check signals first, to get correct SIGURG
+                * handling. FIXME: Need to check this doesn't impact 1003.1g
+                * and move it down to the bottom of the loop
+                */
+               if (signal_pending(current)) {
+                       if (copied)
+                               break;
+                       copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
+                       break;
+               }
+
+               /* Next get a buffer. */
+
+               skb = skb_peek(&sk->receive_queue);
+               do {
+                       if (!skb)
+                               break;
+
+                       /* Now that we have two receive queues this 
+                        * shouldn't happen.
+                        */
+                       if (before(*seq, TCP_SKB_CB(skb)->seq)) {
+                               printk(KERN_INFO "recvmsg bug: copied %X seq %X\n",
+                                      *seq, TCP_SKB_CB(skb)->seq);
+                               break;
+                       }
+                       offset = *seq - TCP_SKB_CB(skb)->seq;
+                       if (skb->h.th->syn)
+                               offset--;
+                       if (offset < skb->len)
+                               goto found_ok_skb;
+                       if (skb->h.th->fin)
+                               goto found_fin_ok;
+                       BUG_TRAP(flags&MSG_PEEK);
+                       skb = skb->next;
+               } while (skb != (struct sk_buff *)&sk->receive_queue);
+
+               /* Well, if we have backlog, try to process it now yet. */
+
+               if (copied >= target && sk->backlog.tail == NULL)
+                       break;
+
+               if (copied) {
+                       if (sk->err ||
+                           sk->state == TCP_CLOSE ||
+                           (sk->shutdown & RCV_SHUTDOWN) ||
+                           !timeo ||
+                           (flags & MSG_PEEK))
+                               break;
+               } else {
+                       if (sk->done)
+                               break;
+
+                       if (sk->err) {
+                               copied = sock_error(sk);
+                               break;
+                       }
+
+                       if (sk->shutdown & RCV_SHUTDOWN)
+                               break;
+
+                       if (sk->state == TCP_CLOSE) {
+                               if (!sk->done) {
+                                       /* This occurs when user tries to read
+                                        * from never connected socket.
+                                        */
+                                       copied = -ENOTCONN;
+                                       break;
+                               }
+                               break;
+                       }
+
+                       if (!timeo) {
+                               copied = -EAGAIN;
+                               break;
+                       }
+               }
+
+               cleanup_rbuf(sk, copied);
+
+               if (tp->ucopy.task == user_recv) {
+                       /* Install new reader */
+                       if (user_recv == NULL && !(flags&(MSG_TRUNC|MSG_PEEK))) {
+                               user_recv = current;
+                               tp->ucopy.task = user_recv;
+                               tp->ucopy.iov = msg->msg_iov;
+                       }
+
+                       tp->ucopy.len = len;
+
+                       BUG_TRAP(tp->copied_seq == tp->rcv_nxt || (flags&(MSG_PEEK|MSG_TRUNC)));
+
+                       /* Ugly... If prequeue is not empty, we have to
+                        * process it before releasing socket, otherwise
+                        * order will be broken at second iteration.
+                        * More elegant solution is required!!!
+                        *
+                        * Look: we have the following (pseudo)queues:
+                        *
+                        * 1. packets in flight
+                        * 2. backlog
+                        * 3. prequeue
+                        * 4. receive_queue
+                        *
+                        * Each queue can be processed only if the next ones
+                        * are empty. At this point we have empty receive_queue.
+                        * But prequeue _can_ be not empty after second iteration,
+                        * when we jumped to start of loop because backlog
+                        * processing added something to receive_queue.
+                        * We cannot release_sock(), because backlog contains
+                        * packets arrived _after_ prequeued ones.
+                        *
+                        * Shortly, algorithm is clear --- to process all
+                        * the queues in order. We could make it more directly,
+                        * requeueing packets from backlog to prequeue, if
+                        * is not empty. It is more elegant, but eats cycles,
+                        * unfortunately.
+                        */
+                       if (skb_queue_len(&tp->ucopy.prequeue))
+                               goto do_prequeue;
+
+                       /* __ Set realtime policy in scheduler __ */
+               }
+
+               if (copied >= target) {
+                       /* Do not sleep, just process backlog. */
+                       release_sock(sk);
+                       lock_sock(sk);
+               } else {
+                       timeo = tcp_data_wait(sk, timeo);
+               }
+
+               if (user_recv) {
+                       int chunk;
+
+                       /* __ Restore normal policy in scheduler __ */
+
+                       if ((chunk = len - tp->ucopy.len) != 0) {
+                               net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromBacklog += chunk;
+                               len -= chunk;
+                               copied += chunk;
+                       }
+
+                       if (tp->rcv_nxt == tp->copied_seq &&
+                           skb_queue_len(&tp->ucopy.prequeue)) {
+do_prequeue:
+                               tcp_prequeue_process(sk);
+
+                               if ((chunk = len - tp->ucopy.len) != 0) {
+                                       net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromPrequeue += chunk;
+                                       len -= chunk;
+                                       copied += chunk;
+                               }
+                       }
+               }
+               if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {
+                       if (net_ratelimit())
+                               printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n",
+                                      current->comm, current->pid);
+                       peek_seq = tp->copied_seq;
+               }
+               continue;
+
+       found_ok_skb:
+               /* Ok so how much can we use? */
+               used = skb->len - offset;
+               if (len < used)
+                       used = len;
+
+               /* Do we have urgent data here? */
+               if (tp->urg_data) {
+                       u32 urg_offset = tp->urg_seq - *seq;
+                       if (urg_offset < used) {
+                               if (!urg_offset) {
+                                       if (!sk->urginline) {
+                                               ++*seq;
+                                               offset++;
+                                               used--;
+                                               if (!used)
+                                                       goto skip_copy;
+                                       }
+                               } else
+                                       used = urg_offset;
+                       }
+               }
+
+               if (!(flags&MSG_TRUNC)) {
+                       err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, used);
+                       if (err) {
+                               /* Exception. Bailout! */
+                               if (!copied)
+                                       copied = -EFAULT;
+                               break;
+                       }
+               }
+
+               *seq += used;
+               copied += used;
+               len -= used;
+
+skip_copy:
+               if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
+                       tp->urg_data = 0;
+                       tcp_fast_path_check(sk, tp);
+               }
+               if (used + offset < skb->len)
+                       continue;
+
+               if (skb->h.th->fin)
+                       goto found_fin_ok;
+               if (!(flags & MSG_PEEK))
+                       tcp_eat_skb(sk, skb);
+               continue;
+
+       found_fin_ok:
+               /* Process the FIN. */
+               ++*seq;
+               if (!(flags & MSG_PEEK))
+                       tcp_eat_skb(sk, skb);
+               break;
+       } while (len > 0);
+
+       if (user_recv) {
+               if (skb_queue_len(&tp->ucopy.prequeue)) {
+                       int chunk;
+
+                       tp->ucopy.len = copied > 0 ? len : 0;
+
+                       tcp_prequeue_process(sk);
+
+                       if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {
+                               net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromPrequeue += chunk;
+                               len -= chunk;
+                               copied += chunk;
+                       }
+               }
+
+               tp->ucopy.task = NULL;
+               tp->ucopy.len = 0;
+       }
+
+       /* According to UNIX98, msg_name/msg_namelen are ignored
+        * on connected socket. I was just happy when found this 8) --ANK
+        */
+
+       /* Clean up data we have read: This will do ACK frames. */
+       cleanup_rbuf(sk, copied);
+
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return copied;
+
+out:
+       TCP_CHECK_TIMER(sk);
+       release_sock(sk);
+       return err;
+
+recv_urg:
+       err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len);
+       goto out;
+#else
+       return 0;
+#endif
+}
+
+/*
+ *     State processing on a close. This implements the state shift for
+ *     sending our FIN frame. Note that we only send a FIN for some
+ *     states. A shutdown() may have already sent the FIN, or we may be
+ *     closed.
+ */
+
+static unsigned char new_state[16] = {
+  /* current state:        new state:      action:     */
+  /* (Invalid)         */ TCP_CLOSE,
+  /* TCP_ESTABLISHED   */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+  /* TCP_SYN_SENT      */ TCP_CLOSE,
+  /* TCP_SYN_RECV      */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+  /* TCP_FIN_WAIT1     */ TCP_FIN_WAIT1,
+  /* TCP_FIN_WAIT2     */ TCP_FIN_WAIT2,
+  /* TCP_TIME_WAIT     */ TCP_CLOSE,
+  /* TCP_CLOSE         */ TCP_CLOSE,
+  /* TCP_CLOSE_WAIT    */ TCP_LAST_ACK  | TCP_ACTION_FIN,
+  /* TCP_LAST_ACK      */ TCP_LAST_ACK,
+  /* TCP_LISTEN                */ TCP_CLOSE,
+  /* TCP_CLOSING       */ TCP_CLOSING,
+};
+
+static int tcp_close_state(struct sock *sk)
+{
+#if 0
+       int next = (int) new_state[sk->state];
+       int ns = (next & TCP_STATE_MASK);
+
+       tcp_set_state(sk, ns);
+
+       return (next & TCP_ACTION_FIN);
+#else
+       return 0;
+#endif
+}
+
+/*
+ *     Shutdown the sending side of a connection. Much like close except
+ *     that we don't receive shut down or set sk->dead.
+ */
+
+void tcp_shutdown(struct sock *sk, int how)
+{
+#if 0
+       /*      We need to grab some memory, and put together a FIN,
+        *      and then put it into the queue to be sent.
+        *              Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
+        */
+       if (!(how & SEND_SHUTDOWN))
+               return;
+
+       /* If we've already sent a FIN, or it's a closed state, skip this. */
+       if ((1 << sk->state) &
+           (TCPF_ESTABLISHED|TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE_WAIT)) {
+               /* Clear out any half completed packets.  FIN if needed. */
+               if (tcp_close_state(sk))
+                       tcp_send_fin(sk);
+       }
+#endif
+}
+
+
+/*
+ *     Return 1 if we still have things to send in our buffers.
+ */
+
+static inline int closing(struct sock * sk)
+{
+#if 0
+       return ((1 << sk->state) & (TCPF_FIN_WAIT1|TCPF_CLOSING|TCPF_LAST_ACK));
+#else
+       return 0;
+#endif
+}
+
+static __inline__ void tcp_kill_sk_queues(struct sock *sk)
+{
+#if 0
+       /* First the read buffer. */
+       __skb_queue_purge(&sk->receive_queue);
+
+       /* Next, the error queue. */
+       __skb_queue_purge(&sk->error_queue);
+
+       /* Next, the write queue. */
+       BUG_TRAP(skb_queue_empty(&sk->write_queue));
+
+       /* Account for returned memory. */
+       tcp_mem_reclaim(sk);
+
+       BUG_TRAP(sk->wmem_queued == 0);
+       BUG_TRAP(sk->forward_alloc == 0);
+
+       /* It is _impossible_ for the backlog to contain anything
+        * when we get here.  All user references to this socket
+        * have gone away, only the net layer knows can touch it.
+        */
+#endif
+}
+
+/*
+ * At this point, there should be no process reference to this
+ * socket, and thus no user references at all.  Therefore we
+ * can assume the socket waitqueue is inactive and nobody will
+ * try to jump onto it.
+ */
+void tcp_destroy_sock(struct sock *sk)
+{
+#if 0
+       BUG_TRAP(sk->state==TCP_CLOSE);
+       BUG_TRAP(sk->dead);
+
+       /* It cannot be in hash table! */
+       BUG_TRAP(sk->pprev==NULL);
+
+       /* If it has not 0 sk->num, it must be bound */
+       BUG_TRAP(!sk->num || sk->prev!=NULL);
+
+#ifdef TCP_DEBUG
+       if (sk->zapped) {
+               printk(KERN_DEBUG "TCP: double destroy sk=%p\n", sk);
+               sock_hold(sk);
+       }
+       sk->zapped = 1;
+#endif
+
+       sk->prot->destroy(sk);
+
+       tcp_kill_sk_queues(sk);
+
+#ifdef INET_REFCNT_DEBUG
+       if (atomic_read(&sk->refcnt) != 1) {
+               printk(KERN_DEBUG "Destruction TCP %p delayed, c=%d\n", sk, atomic_read(&sk->refcnt));
+       }
+#endif
+
+       atomic_dec(&tcp_orphan_count);
+       sock_put(sk);
+#endif
+}
+
+void tcp_close(struct sock *sk, long timeout)
+{
+#if 0
+       struct sk_buff *skb;
+       int data_was_unread = 0;
+
+       lock_sock(sk);
+       sk->shutdown = SHUTDOWN_MASK;
+
+       if(sk->state == TCP_LISTEN) {
+               tcp_set_state(sk, TCP_CLOSE);
+
+               /* Special case. */
+               tcp_listen_stop(sk);
+
+               goto adjudge_to_death;
+       }
+
+       /*  We need to flush the recv. buffs.  We do this only on the
+        *  descriptor close, not protocol-sourced closes, because the
+        *  reader process may not have drained the data yet!
+        */
+       while((skb=__skb_dequeue(&sk->receive_queue))!=NULL) {
+               u32 len = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq - skb->h.th->fin;
+               data_was_unread += len;
+               __kfree_skb(skb);
+       }
+
+       tcp_mem_reclaim(sk);
+
+       /* As outlined in draft-ietf-tcpimpl-prob-03.txt, section
+        * 3.10, we send a RST here because data was lost.  To
+        * witness the awful effects of the old behavior of always
+        * doing a FIN, run an older 2.1.x kernel or 2.0.x, start
+        * a bulk GET in an FTP client, suspend the process, wait
+        * for the client to advertise a zero window, then kill -9
+        * the FTP client, wheee...  Note: timeout is always zero
+        * in such a case.
+        */
+       if(data_was_unread != 0) {
+               /* Unread data was tossed, zap the connection. */
+               NET_INC_STATS_USER(TCPAbortOnClose);
+               tcp_set_state(sk, TCP_CLOSE);
+               tcp_send_active_reset(sk, GFP_KERNEL);
+       } else if (sk->linger && sk->lingertime==0) {
+               /* Check zero linger _after_ checking for unread data. */
+               sk->prot->disconnect(sk, 0);
+               NET_INC_STATS_USER(TCPAbortOnData);
+       } else if (tcp_close_state(sk)) {
+               /* We FIN if the application ate all the data before
+                * zapping the connection.
+                */
+
+               /* RED-PEN. Formally speaking, we have broken TCP state
+                * machine. State transitions:
+                *
+                * TCP_ESTABLISHED -> TCP_FIN_WAIT1
+                * TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible)
+                * TCP_CLOSE_WAIT -> TCP_LAST_ACK
+                *
+                * are legal only when FIN has been sent (i.e. in window),
+                * rather than queued out of window. Purists blame.
+                *
+                * F.e. "RFC state" is ESTABLISHED,
+                * if Linux state is FIN-WAIT-1, but FIN is still not sent.
+                *
+                * The visible declinations are that sometimes
+                * we enter time-wait state, when it is not required really
+                * (harmless), do not send active resets, when they are
+                * required by specs (TCP_ESTABLISHED, TCP_CLOSE_WAIT, when
+                * they look as CLOSING or LAST_ACK for Linux)
+                * Probably, I missed some more holelets.
+                *                                              --ANK
+                */
+               tcp_send_fin(sk);
+       }
+
+       if (timeout) {
+               struct task_struct *tsk = current;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(sk->sleep, &wait);
+
+               do {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (!closing(sk))
+                               break;
+                       release_sock(sk);
+                       timeout = schedule_timeout(timeout);
+                       lock_sock(sk);
+               } while (!signal_pending(tsk) && timeout);
+
+               tsk->state = TASK_RUNNING;
+               remove_wait_queue(sk->sleep, &wait);
+       }
+
+adjudge_to_death:
+       /* It is the last release_sock in its life. It will remove backlog. */
+       release_sock(sk);
+
+
+       /* Now socket is owned by kernel and we acquire BH lock
+          to finish close. No need to check for user refs.
+        */
+       local_bh_disable();
+       bh_lock_sock(sk);
+       BUG_TRAP(sk->lock.users==0);
+
+       sock_hold(sk);
+       sock_orphan(sk);
+
+       /*      This is a (useful) BSD violating of the RFC. There is a
+        *      problem with TCP as specified in that the other end could
+        *      keep a socket open forever with no application left this end.
+        *      We use a 3 minute timeout (about the same as BSD) then kill
+        *      our end. If they send after that then tough - BUT: long enough
+        *      that we won't make the old 4*rto = almost no time - whoops
+        *      reset mistake.
+        *
+        *      Nope, it was not mistake. It is really desired behaviour
+        *      f.e. on http servers, when such sockets are useless, but
+        *      consume significant resources. Let's do it with special
+        *      linger2 option.                                 --ANK
+        */
+
+       if (sk->state == TCP_FIN_WAIT2) {
+               struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+               if (tp->linger2 < 0) {
+                       tcp_set_state(sk, TCP_CLOSE);
+                       tcp_send_active_reset(sk, GFP_ATOMIC);
+                       NET_INC_STATS_BH(TCPAbortOnLinger);
+               } else {
+                       int tmo = tcp_fin_time(tp);
+
+                       if (tmo > TCP_TIMEWAIT_LEN) {
+                               tcp_reset_keepalive_timer(sk, tcp_fin_time(tp));
+                       } else {
+                               atomic_inc(&tcp_orphan_count);
+                               tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+                               goto out;
+                       }
+               }
+       }
+       if (sk->state != TCP_CLOSE) {
+               tcp_mem_reclaim(sk);
+               if (atomic_read(&tcp_orphan_count) > sysctl_tcp_max_orphans ||
+                   (sk->wmem_queued > SOCK_MIN_SNDBUF &&
+                    atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+                       if (net_ratelimit())
+                               printk(KERN_INFO "TCP: too many of orphaned sockets\n");
+                       tcp_set_state(sk, TCP_CLOSE);
+                       tcp_send_active_reset(sk, GFP_ATOMIC);
+                       NET_INC_STATS_BH(TCPAbortOnMemory);
+               }
+       }
+       atomic_inc(&tcp_orphan_count);
+
+       if (sk->state == TCP_CLOSE)
+               tcp_destroy_sock(sk);
+       /* Otherwise, socket is reprieved until protocol close. */
+
+out:
+       bh_unlock_sock(sk);
+       local_bh_enable();
+       sock_put(sk);
+#endif
+}
+
+/* These states need RST on ABORT according to RFC793 */
+
+extern __inline__ int tcp_need_reset(int state)
+{
+#if 0
+       return ((1 << state) &
+               (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT1|
+                TCPF_FIN_WAIT2|TCPF_SYN_RECV));
+#else
+       return 0;
+#endif
+}
+
+int tcp_disconnect(struct sock *sk, int flags)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       int old_state;
+       int err = 0;
+
+       old_state = sk->state;
+       if (old_state != TCP_CLOSE)
+               tcp_set_state(sk, TCP_CLOSE);
+
+       /* ABORT function of RFC793 */
+       if (old_state == TCP_LISTEN) {
+               tcp_listen_stop(sk);
+       } else if (tcp_need_reset(old_state) ||
+                  (tp->snd_nxt != tp->write_seq &&
+                   (1<<old_state)&(TCPF_CLOSING|TCPF_LAST_ACK))) {
+               /* The last check adjusts for discrepance of Linux wrt. RFC
+                * states
+                */
+               tcp_send_active_reset(sk, gfp_any());
+               sk->err = ECONNRESET;
+       } else if (old_state == TCP_SYN_SENT)
+               sk->err = ECONNRESET;
+
+       tcp_clear_xmit_timers(sk);
+       __skb_queue_purge(&sk->receive_queue);
+       tcp_writequeue_purge(sk);
+       __skb_queue_purge(&tp->out_of_order_queue);
+
+       sk->dport = 0;
+
+       if (!(sk->userlocks&SOCK_BINDADDR_LOCK)) {
+               sk->rcv_saddr = 0;
+               sk->saddr = 0;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               memset(&sk->net_pinfo.af_inet6.saddr, 0, 16);
+               memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16);
+#endif
+       }
+
+       sk->shutdown = 0;
+       sk->done = 0;
+       tp->srtt = 0;
+       if ((tp->write_seq += tp->max_window+2) == 0)
+               tp->write_seq = 1;
+       tp->backoff = 0;
+       tp->snd_cwnd = 2;
+       tp->probes_out = 0;
+       tp->packets_out = 0;
+       tp->snd_ssthresh = 0x7fffffff;
+       tp->snd_cwnd_cnt = 0;
+       tp->ca_state = TCP_CA_Open;
+       tcp_clear_retrans(tp);
+       tcp_delack_init(tp);
+       tp->send_head = NULL;
+       tp->saw_tstamp = 0;
+       tcp_sack_reset(tp);
+       __sk_dst_reset(sk);
+
+       BUG_TRAP(!sk->num || sk->prev);
+
+       sk->error_report(sk);
+       return err;
+#else
+       return 0;
+#endif
+}
+
+/*
+ *     Wait for an incoming connection, avoid race
+ *     conditions. This must be called with the socket locked.
+ */
+static int wait_for_connect(struct sock * sk, long timeo)
+{
+#if 0
+       DECLARE_WAITQUEUE(wait, current);
+       int err;
+
+       /*
+        * True wake-one mechanism for incoming connections: only
+        * one process gets woken up, not the 'whole herd'.
+        * Since we do not 'race & poll' for established sockets
+        * anymore, the common case will execute the loop only once.
+        *
+        * Subtle issue: "add_wait_queue_exclusive()" will be added
+        * after any current non-exclusive waiters, and we know that
+        * it will always _stay_ after any new non-exclusive waiters
+        * because all non-exclusive waiters are added at the
+        * beginning of the wait-queue. As such, it's ok to "drop"
+        * our exclusiveness temporarily when we get woken up without
+        * having to remove and re-insert us on the wait queue.
+        */
+       add_wait_queue_exclusive(sk->sleep, &wait);
+       for (;;) {
+               current->state = TASK_INTERRUPTIBLE;
+               release_sock(sk);
+               if (sk->tp_pinfo.af_tcp.accept_queue == NULL)
+                       timeo = schedule_timeout(timeo);
+               lock_sock(sk);
+               err = 0;
+               if (sk->tp_pinfo.af_tcp.accept_queue)
+                       break;
+               err = -EINVAL;
+               if (sk->state != TCP_LISTEN)
+                       break;
+               err = sock_intr_errno(timeo);
+               if (signal_pending(current))
+                       break;
+               err = -EAGAIN;
+               if (!timeo)
+                       break;
+       }
+       current->state = TASK_RUNNING;
+       remove_wait_queue(sk->sleep, &wait);
+       return err;
+#else
+       return 0;
+#endif
+}
+
+/*
+ *     This will accept the next outstanding connection.
+ */
+
+struct sock *tcp_accept(struct sock *sk, int flags, int *err)
+{
+#if 0
+       struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+       struct open_request *req;
+       struct sock *newsk;
+       int error;
+
+       lock_sock(sk); 
+
+       /* We need to make sure that this socket is listening,
+        * and that it has something pending.
+        */
+       error = -EINVAL;
+       if (sk->state != TCP_LISTEN)
+               goto out;
+
+       /* Find already established connection */
+       if (!tp->accept_queue) {
+               long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+               /* If this is a non blocking socket don't sleep */
+               error = -EAGAIN;
+               if (!timeo)
+                       goto out;
+
+               error = wait_for_connect(sk, timeo);
+               if (error)
+                       goto out;
+       }
+
+       req = tp->accept_queue;
+       if ((tp->accept_queue = req->dl_next) == NULL)
+               tp->accept_queue_tail = NULL;
+
+       newsk = req->sk;
+       tcp_acceptq_removed(sk);
+       tcp_openreq_fastfree(req);
+       BUG_TRAP(newsk->state != TCP_SYN_RECV);
+       release_sock(sk);
+       return newsk;
+
+out:
+       release_sock(sk);
+       *err = error; 
+       return NULL;
+#else
+       return NULL;
+#endif
+}
+
+/*
+ *     Socket option code for TCP. 
+ */
+  
+int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, 
+                  int optlen)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int val;
+       int err = 0;
+
+       if (level != SOL_TCP)
+               return tp->af_specific->setsockopt(sk, level, optname, 
+                                                  optval, optlen);
+
+       if(optlen<sizeof(int))
+               return -EINVAL;
+
+       if (get_user(val, (int *)optval))
+               return -EFAULT;
+
+       lock_sock(sk);
+
+       switch(optname) {
+       case TCP_MAXSEG:
+               /* values greater than interface MTU won't take effect.  however at
+                * the point when this call is done we typically don't yet know
+                * which interface is going to be used
+                */
+               if(val < 8 || val > MAX_TCP_WINDOW) {
+                       err = -EINVAL;
+                       break;
+               }
+               tp->user_mss = val;
+               break;
+
+       case TCP_NODELAY:
+               /* You cannot try to use this and TCP_CORK in
+                * tandem, so let the user know.
+                */
+               if (tp->nonagle == 2) {
+                       err = -EINVAL;
+                       break;
+               }
+               tp->nonagle = (val == 0) ? 0 : 1;
+               if (val)
+                       tcp_push_pending_frames(sk, tp);
+               break;
+
+       case TCP_CORK:
+               /* When set indicates to always queue non-full frames.
+                * Later the user clears this option and we transmit
+                * any pending partial frames in the queue.  This is
+                * meant to be used alongside sendfile() to get properly
+                * filled frames when the user (for example) must write
+                * out headers with a write() call first and then use
+                * sendfile to send out the data parts.
+                *
+                * You cannot try to use TCP_NODELAY and this mechanism
+                * at the same time, so let the user know.
+                */
+               if (tp->nonagle == 1) {
+                       err = -EINVAL;
+                       break;
+               }
+               if (val != 0) {
+                       tp->nonagle = 2;
+               } else {
+                       tp->nonagle = 0;
+
+                       tcp_push_pending_frames(sk, tp);
+               }
+               break;
+               
+       case TCP_KEEPIDLE:
+               if (val < 1 || val > MAX_TCP_KEEPIDLE)
+                       err = -EINVAL;
+               else {
+                       tp->keepalive_time = val * HZ;
+                       if (sk->keepopen && !((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))) {
+                               __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
+                               if (tp->keepalive_time > elapsed)
+                                       elapsed = tp->keepalive_time - elapsed;
+                               else
+                                       elapsed = 0;
+                               tcp_reset_keepalive_timer(sk, elapsed);
+                       }
+               }
+               break;
+       case TCP_KEEPINTVL:
+               if (val < 1 || val > MAX_TCP_KEEPINTVL)
+                       err = -EINVAL;
+               else
+                       tp->keepalive_intvl = val * HZ;
+               break;
+       case TCP_KEEPCNT:
+               if (val < 1 || val > MAX_TCP_KEEPCNT)
+                       err = -EINVAL;
+               else
+                       tp->keepalive_probes = val;
+               break;
+       case TCP_SYNCNT:
+               if (val < 1 || val > MAX_TCP_SYNCNT)
+                       err = -EINVAL;
+               else
+                       tp->syn_retries = val;
+               break;
+
+       case TCP_LINGER2:
+               if (val < 0)
+                       tp->linger2 = -1;
+               else if (val > sysctl_tcp_fin_timeout/HZ)
+                       tp->linger2 = 0;
+               else
+                       tp->linger2 = val*HZ;
+               break;
+
+       case TCP_DEFER_ACCEPT:
+               tp->defer_accept = 0;
+               if (val > 0) {
+                       /* Translate value in seconds to number of retransmits */
+                       while (tp->defer_accept < 32 && val > ((TCP_TIMEOUT_INIT/HZ)<<tp->defer_accept))
+                               tp->defer_accept++;
+                       tp->defer_accept++;
+               }
+               break;
+
+       case TCP_WINDOW_CLAMP:
+               if (val==0) {
+                       if (sk->state != TCP_CLOSE) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       tp->window_clamp = 0;
+               } else {
+                       tp->window_clamp = val<SOCK_MIN_RCVBUF/2 ?
+                               SOCK_MIN_RCVBUF/2 : val;
+               }
+               break;
+
+       case TCP_QUICKACK:
+               if (!val) {
+                       tp->ack.pingpong = 1;
+               } else {
+                       tp->ack.pingpong = 0;
+                       if ((1<<sk->state)&(TCPF_ESTABLISHED|TCPF_CLOSE_WAIT) &&
+                           tcp_ack_scheduled(tp)) {
+                               tp->ack.pending |= TCP_ACK_PUSHED;
+                               cleanup_rbuf(sk, 1);
+                               if (!(val & 1))
+                                       tp->ack.pingpong = 1;
+                       }
+               }
+               break;
+
+       default:
+               err = -ENOPROTOOPT;
+               break;
+       };
+       release_sock(sk);
+       return err;
+#else
+       return 0;
+#endif
+}
+
+int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
+                  int *optlen)
+{
+#if 0
+       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+       int val, len;
+
+       if(level != SOL_TCP)
+               return tp->af_specific->getsockopt(sk, level, optname,
+                                                  optval, optlen);
+
+       if(get_user(len,optlen))
+               return -EFAULT;
+
+       len = min_t(unsigned int, len, sizeof(int));
+       
+       if(len < 0)
+               return -EINVAL;
+
+       switch(optname) {
+       case TCP_MAXSEG:
+               val = tp->mss_cache;
+               if (val == 0 && ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN)))
+                       val = tp->user_mss;
+               break;
+       case TCP_NODELAY:
+               val = (tp->nonagle == 1);
+               break;
+       case TCP_CORK:
+               val = (tp->nonagle == 2);
+               break;
+       case TCP_KEEPIDLE:
+               val = (tp->keepalive_time ? : sysctl_tcp_keepalive_time)/HZ;
+               break;
+       case TCP_KEEPINTVL:
+               val = (tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl)/HZ;
+               break;
+       case TCP_KEEPCNT:
+               val = tp->keepalive_probes ? : sysctl_tcp_keepalive_probes;
+               break;
+       case TCP_SYNCNT:
+               val = tp->syn_retries ? : sysctl_tcp_syn_retries;
+               break;
+       case TCP_LINGER2:
+               val = tp->linger2;
+               if (val >= 0)
+                       val = (val ? : sysctl_tcp_fin_timeout)/HZ;
+               break;
+       case TCP_DEFER_ACCEPT:
+               val = tp->defer_accept == 0 ? 0 : ((TCP_TIMEOUT_INIT/HZ)<<(tp->defer_accept-1));
+               break;
+       case TCP_WINDOW_CLAMP:
+               val = tp->window_clamp;
+               break;
+       case TCP_INFO:
+       {
+               struct tcp_info info;
+               u32 now = tcp_time_stamp;
+
+               if(get_user(len,optlen))
+                       return -EFAULT;
+               info.tcpi_state = sk->state;
+               info.tcpi_ca_state = tp->ca_state;
+               info.tcpi_retransmits = tp->retransmits;
+               info.tcpi_probes = tp->probes_out;
+               info.tcpi_backoff = tp->backoff;
+               info.tcpi_options = 0;
+               if (tp->tstamp_ok)
+                       info.tcpi_options |= TCPI_OPT_TIMESTAMPS;
+               if (tp->sack_ok)
+                       info.tcpi_options |= TCPI_OPT_SACK;
+               if (tp->wscale_ok) {
+                       info.tcpi_options |= TCPI_OPT_WSCALE;
+                       info.tcpi_snd_wscale = tp->snd_wscale;
+                       info.tcpi_rcv_wscale = tp->rcv_wscale;
+               } else {
+                       info.tcpi_snd_wscale = 0;
+                       info.tcpi_rcv_wscale = 0;
+               }
+               if (tp->ecn_flags&TCP_ECN_OK)
+                       info.tcpi_options |= TCPI_OPT_ECN;
+
+               info.tcpi_rto = (1000000*tp->rto)/HZ;
+               info.tcpi_ato = (1000000*tp->ack.ato)/HZ;
+               info.tcpi_snd_mss = tp->mss_cache;
+               info.tcpi_rcv_mss = tp->ack.rcv_mss;
+
+               info.tcpi_unacked = tp->packets_out;
+               info.tcpi_sacked = tp->sacked_out;
+               info.tcpi_lost = tp->lost_out;
+               info.tcpi_retrans = tp->retrans_out;
+               info.tcpi_fackets = tp->fackets_out;
+
+               info.tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ;
+               info.tcpi_last_ack_sent = 0;
+               info.tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ;
+               info.tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ;
+
+               info.tcpi_pmtu = tp->pmtu_cookie;
+               info.tcpi_rcv_ssthresh = tp->rcv_ssthresh;
+               info.tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3;
+               info.tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2;
+               info.tcpi_snd_ssthresh = tp->snd_ssthresh;
+               info.tcpi_snd_cwnd = tp->snd_cwnd;
+               info.tcpi_advmss = tp->advmss;
+               info.tcpi_reordering = tp->reordering;
+
+               len = min_t(unsigned int, len, sizeof(info));
+               if(put_user(len, optlen))
+                       return -EFAULT;
+               if(copy_to_user(optval, &info,len))
+                       return -EFAULT;
+               return 0;
+       }
+       case TCP_QUICKACK:
+               val = !tp->ack.pingpong;
+               break;
+       default:
+               return -ENOPROTOOPT;
+       };
+
+       if(put_user(len, optlen))
+               return -EFAULT;
+       if(copy_to_user(optval, &val,len))
+               return -EFAULT;
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+
+//extern void __skb_cb_too_small_for_tcp(int, int);
+//extern void tcpdiag_init(void);
+
+void /* __init */ tcp_init(void)
+{
+#if 0
+       struct sk_buff *skb = NULL;
+       unsigned long goal;
+       int order, i;
+
+       if(sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
+               __skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
+                                          sizeof(skb->cb));
+
+       tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
+                                                  sizeof(struct open_request),
+                                              0, SLAB_HWCACHE_ALIGN,
+                                              NULL, NULL);
+       if(!tcp_openreq_cachep)
+               panic("tcp_init: Cannot alloc open_request cache.");
+
+       tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
+                                             sizeof(struct tcp_bind_bucket),
+                                             0, SLAB_HWCACHE_ALIGN,
+                                             NULL, NULL);
+       if(!tcp_bucket_cachep)
+               panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
+
+       tcp_timewait_cachep = kmem_cache_create("tcp_tw_bucket",
+                                               sizeof(struct tcp_tw_bucket),
+                                               0, SLAB_HWCACHE_ALIGN,
+                                               NULL, NULL);
+       if(!tcp_timewait_cachep)
+               panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
+
+       /* Size and allocate the main established and bind bucket
+        * hash tables.
+        *
+        * The methodology is similar to that of the buffer cache.
+        */
+       if (num_physpages >= (128 * 1024))
+               goal = num_physpages >> (21 - PAGE_SHIFT);
+       else
+               goal = num_physpages >> (23 - PAGE_SHIFT);
+
+       for(order = 0; (1UL << order) < goal; order++)
+               ;
+       do {
+               tcp_ehash_size = (1UL << order) * PAGE_SIZE /
+                       sizeof(struct tcp_ehash_bucket);
+               tcp_ehash_size >>= 1;
+               while (tcp_ehash_size & (tcp_ehash_size-1))
+                       tcp_ehash_size--;
+               tcp_ehash = (struct tcp_ehash_bucket *)
+                       __get_free_pages(GFP_ATOMIC, order);
+       } while (tcp_ehash == NULL && --order > 0);
+
+       if (!tcp_ehash)
+               panic("Failed to allocate TCP established hash table\n");
+       for (i = 0; i < (tcp_ehash_size<<1); i++) {
+               tcp_ehash[i].lock = RW_LOCK_UNLOCKED;
+               tcp_ehash[i].chain = NULL;
+       }
+
+       do {
+               tcp_bhash_size = (1UL << order) * PAGE_SIZE /
+                       sizeof(struct tcp_bind_hashbucket);
+               if ((tcp_bhash_size > (64 * 1024)) && order > 0)
+                       continue;
+               tcp_bhash = (struct tcp_bind_hashbucket *)
+                       __get_free_pages(GFP_ATOMIC, order);
+       } while (tcp_bhash == NULL && --order >= 0);
+
+       if (!tcp_bhash)
+               panic("Failed to allocate TCP bind hash table\n");
+       for (i = 0; i < tcp_bhash_size; i++) {
+               tcp_bhash[i].lock = SPIN_LOCK_UNLOCKED;
+               tcp_bhash[i].chain = NULL;
+       }
+
+       /* Try to be a bit smarter and adjust defaults depending
+        * on available memory.
+        */
+       if (order > 4) {
+               sysctl_local_port_range[0] = 32768;
+               sysctl_local_port_range[1] = 61000;
+               sysctl_tcp_max_tw_buckets = 180000;
+               sysctl_tcp_max_orphans = 4096<<(order-4);
+               sysctl_max_syn_backlog = 1024;
+       } else if (order < 3) {
+               sysctl_local_port_range[0] = 1024*(3-order);
+               sysctl_tcp_max_tw_buckets >>= (3-order);
+               sysctl_tcp_max_orphans >>= (3-order);
+               sysctl_max_syn_backlog = 128;
+       }
+       tcp_port_rover = sysctl_local_port_range[0] - 1;
+
+       sysctl_tcp_mem[0] = 768<<order;
+       sysctl_tcp_mem[1] = 1024<<order;
+       sysctl_tcp_mem[2] = 1536<<order;
+       if (sysctl_tcp_mem[2] - sysctl_tcp_mem[1] > 512)
+               sysctl_tcp_mem[1] = sysctl_tcp_mem[2] - 512;
+       if (sysctl_tcp_mem[1] - sysctl_tcp_mem[0] > 512)
+               sysctl_tcp_mem[0] = sysctl_tcp_mem[1] - 512;
+
+       if (order < 3) {
+               sysctl_tcp_wmem[2] = 64*1024;
+               sysctl_tcp_rmem[0] = PAGE_SIZE;
+               sysctl_tcp_rmem[1] = 43689;
+               sysctl_tcp_rmem[2] = 2*43689;
+       }
+
+       printk(KERN_INFO "TCP: Hash tables configured (established %d bind %d)\n",
+              tcp_ehash_size<<1, tcp_bhash_size);
+
+       tcpdiag_init();
+#endif
+}
diff --git a/drivers/net/tcpip/transport/udp/.cvsignore b/drivers/net/tcpip/transport/udp/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tdi/.cvsignore b/drivers/net/tdi/.cvsignore
new file mode 100644 (file)
index 0000000..07e60d4
--- /dev/null
@@ -0,0 +1,3 @@
+*.sym
+*.sys
+*.o
diff --git a/drivers/net/tdi/cte/.cvsignore b/drivers/net/tdi/cte/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/drivers/net/tdi/tdi/.cvsignore b/drivers/net/tdi/tdi/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/include/basetsd.h b/include/basetsd.h
new file mode 100644 (file)
index 0000000..d9c375d
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef _BASETSD_H
+#define _BASETSD_H
+#if __GNUC__ >=3
+#pragma GCC system_header
+#endif
+
+#ifdef __GNUC__
+#ifndef __int64
+#define __int64 long long
+#endif
+#endif
+
+#if defined(_WIN64)
+#define __int3264   __int64
+#define ADDRESS_TAG_BIT 0x40000000000UI64
+#else /*  !_WIN64 */
+#define __int3264   __int32
+#define ADDRESS_TAG_BIT 0x80000000UL
+#define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
+#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
+#define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
+#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
+#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
+#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
+#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
+#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
+#define PtrToShort( p ) ((short)(LONG_PTR)(p) )
+#define IntToPtr( i )    ((VOID*)(INT_PTR)((int)i))
+#define UIntToPtr( ui )  ((VOID*)(UINT_PTR)((unsigned int)ui))
+#define LongToPtr( l )   ((VOID*)(LONG_PTR)((long)l))
+#define ULongToPtr( ul )  ((VOID*)(ULONG_PTR)((unsigned long)ul))
+#endif /* !_WIN64 */
+
+#define UlongToPtr(ul) ULongToPtr(ul)
+#define UintToPtr(ui) UIntToPtr(ui)
+#define MAXUINT_PTR  (~((UINT_PTR)0))
+#define MAXINT_PTR   ((INT_PTR)(MAXUINT_PTR >> 1))
+#define MININT_PTR   (~MAXINT_PTR)
+#define MAXULONG_PTR (~((ULONG_PTR)0))
+#define MAXLONG_PTR  ((LONG_PTR)(MAXULONG_PTR >> 1))
+#define MINLONG_PTR  (~MAXLONG_PTR)
+#define MAXUHALF_PTR ((UHALF_PTR)~0)
+#define MAXHALF_PTR  ((HALF_PTR)(MAXUHALF_PTR >> 1))
+#define MINHALF_PTR  (~MAXHALF_PTR)
+
+#ifndef RC_INVOKED
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef int LONG32, *PLONG32;
+#ifndef XFree86Server
+typedef int INT32, *PINT32;
+#endif /* ndef XFree86Server */
+typedef unsigned int ULONG32, *PULONG32;
+typedef unsigned int DWORD32, *PDWORD32;
+typedef unsigned int UINT32, *PUINT32;
+
+#if defined(_WIN64)
+typedef __int64 INT_PTR, *PINT_PTR;
+typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
+typedef __int64 LONG_PTR, *PLONG_PTR;
+typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+typedef unsigned __int64 HANDLE_PTR;
+typedef unsigned int UHALF_PTR, *PUHALF_PTR;
+typedef int HALF_PTR, *PHALF_PTR;
+
+#if 0 /* TODO when WIN64 is here */
+inline unsigned long HandleToUlong(const void* h )
+    { return((unsigned long) h ); }
+inline long HandleToLong( const void* h )
+    { return((long) h ); }
+inline void* LongToHandle( const long h )
+    { return((void*) (INT_PTR) h ); }
+inline unsigned long PtrToUlong( const void* p)
+    { return((unsigned long) p ); }
+inline unsigned int PtrToUint( const void* p )
+    { return((unsigned int) p ); }
+inline unsigned short PtrToUshort( const void* p )
+    { return((unsigned short) p ); }
+inline long PtrToLong( const void* p )
+    { return((long) p ); }
+inline int PtrToInt( const void* p )
+    { return((int) p ); }
+inline short PtrToShort( const void* p )
+    { return((short) p ); }
+inline void* IntToPtr( const int i )
+    { return( (void*)(INT_PTR)i ); }
+inline void* UIntToPtr(const unsigned int ui)
+    { return( (void*)(UINT_PTR)ui ); }
+inline void* LongToPtr( const long l )
+    { return( (void*)(LONG_PTR)l ); }
+inline void* ULongToPtr( const unsigned long ul )
+    { return( (void*)(ULONG_PTR)ul ); }
+#endif /* 0_ */
+
+#else /*  !_WIN64 */
+typedef  int INT_PTR, *PINT_PTR;
+typedef  unsigned int UINT_PTR, *PUINT_PTR;
+typedef  long LONG_PTR, *PLONG_PTR;
+typedef  unsigned long ULONG_PTR, *PULONG_PTR;
+typedef unsigned short UHALF_PTR, *PUHALF_PTR;
+typedef short HALF_PTR, *PHALF_PTR;
+typedef unsigned long HANDLE_PTR;
+#endif /* !_WIN64 */
+
+typedef ULONG_PTR SIZE_T, *PSIZE_T;
+typedef LONG_PTR SSIZE_T, *PSSIZE_T;
+typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
+typedef __int64 LONG64, *PLONG64;
+typedef __int64 INT64,  *PINT64;
+typedef unsigned __int64 ULONG64, *PULONG64;
+typedef unsigned __int64 DWORD64, *PDWORD64;
+typedef unsigned __int64 UINT64,  *PUINT64;
+#ifdef __cplusplus
+}
+#endif
+#endif /* !RC_INVOKED */
+
+#endif /* _BASETSD_H */
diff --git a/include/ddk/af_irda.h b/include/ddk/af_irda.h
new file mode 100644 (file)
index 0000000..0a6433f
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * af_irda.h
+ *
+ * IrDa ports interface
+ *
+ * This file is part of the MinGW package.
+ *
+ * Contributors:
+ *   Created by Robert Dickenson <robd@users.sourceforge.net>
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef __AF_IRDA_H
+#define __AF_IRDA_H
+
+#if __GNUC__ >=3
+#pragma GCC system_header
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push,4)
+
+
+/* GUIDs */
+
+#ifdef DEFINE_GUID
+DEFINE_GUID(GUID_DEVINTERFACE_IRDAPORT,
+  0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x74);
+DEFINE_GUID(GUID_DEVINTERFACE_IRDAENUM_BUS_ENUMERATOR,
+  0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x19);
+#endif // DEFINE_GUID
+
+#define WINDOWS_AF_IRDA 26
+#define WINDOWS_PF_IRDA WINDOWS_AF_IRDA
+
+#ifndef AF_IRDA
+#define AF_IRDA WINDOWS_AF_IRDA
+#endif
+
+#define IRDA_PROTO_SOCK_STREAM 1
+#define PF_IRDA AF_IRDA
+#define SOL_IRLMP 0x00FF
+#define SIO_LAZY_DISCOVERY _IOR('t', 127, ULONG)   
+
+
+#define IAS_MAX_USER_STRING  256
+#define IAS_MAX_OCTET_STRING 1024
+#define IAS_MAX_CLASSNAME    64
+#define IAS_MAX_ATTRIBNAME   256
+
+#define IAS_ATTRIB_NO_CLASS  ((ULONG)0x10)
+#define IAS_ATTRIB_NO_ATTRIB ((ULONG)0x00)
+#define IAS_ATTRIB_INT       ((ULONG)0x01)
+#define IAS_ATTRIB_OCTETSEQ  ((ULONG)0x02)
+#define IAS_ATTRIB_STR       ((ULONG)0x03)
+
+#define IRLMP_ENUMDEVICES    ((ULONG)0x10)
+#define IRLMP_IAS_SET        ((ULONG)0x11)
+#define IRLMP_IAS_QUERY      ((ULONG)0x12)
+#define IRLMP_SEND_PDU_LEN   ((ULONG)0x13)
+#define IRLMP_EXCLUSIVE_MODE ((ULONG)0x14)
+#define IRLMP_IRLPT_MODE     ((ULONG)0x15)
+#define IRLMP_9WIRE_MODE     ((ULONG)0x16)
+
+#if 0
+// Available/Used on Windows 98 only ???
+#define IRLMP_TINYTP_MODE    ((ULONG)0x17)
+#define IRLMP_PARAMETERS     ((ULONG)0x18)
+#define IRLMP_DISCOVERY_MODE ((ULONG)0x19)
+// Available/Used on Windows CE only ???
+#define IRLMP_SHARP_MODE     ((ULONG)0x20)
+#endif
+
+enum {
+// First hint byte
+  LM_HB1_PnP =         0x01,
+  LM_HB1_PDA_Palmtop = 0x02,
+  LM_HB1_Computer =    0x04,
+  LM_HB1_Printer =     0x08,
+  LM_HB1_Modem =       0x10,
+  LM_HB1_Fax =         0x20,
+  LM_HB1_LANAccess =   0x40,
+// Second hint byte
+  LM_HB2_Telephony =   0x01,
+  LM_HB2_FileServer =  0x02,
+// Any hint byte
+  LM_HB_Extension =    0x80,
+};
+
+#define LmCharSetASCII       0x00
+#define LmCharSetISO_8859_1  0x01
+#define LmCharSetISO_8859_2  0x02
+#define LmCharSetISO_8859_3  0x03
+#define LmCharSetISO_8859_4  0x04
+#define LmCharSetISO_8859_5  0x05
+#define LmCharSetISO_8859_6  0x06
+#define LmCharSetISO_8859_7  0x07
+#define LmCharSetISO_8859_8  0x08
+#define LmCharSetISO_8859_9  0x09
+#define LmCharSetUNICODE     0xFF
+
+#define  LM_BAUD_1200   1200
+#define  LM_BAUD_2400   2400
+#define  LM_BAUD_9600   9600
+#define  LM_BAUD_19200  19200
+#define  LM_BAUD_38400  38400
+#define  LM_BAUD_57600  57600
+#define  LM_BAUD_115200 115200
+#define  LM_BAUD_576K   576000
+#define  LM_BAUD_1152K  1152000
+#define  LM_BAUD_4M     4000000
+
+#if 0 // Available/Used on Windows 98 only ???
+typedef ULONG LM_BAUD_RATE;
+typedef struct {
+    ULONG        nTXDataBytes;  // packet transmit receive bytes
+    ULONG        nRXDataBytes;  // packet maximum receive bytes
+    LM_BAUD_RATE nBaudRate;     // link negotiated baud
+    ULONG        thresholdTime; // milliseconds for threshold time
+    ULONG        discTime;      // milliseconds for disconnect time
+    USHORT       nMSLinkTurn;   // milliseconds for link turn around time
+    UCHAR        nTXPackets;    // transmit window packets
+    UCHAR        nRXPackets;    // receive window packets
+} LM_IRPARMS;
+typedef LM_IRPARMS *PLM_IRPARMS;
+#endif
+
+typedef struct _SOCKADDR_IRDA {
+    USHORT irdaAddressFamily;
+    UCHAR  irdaDeviceID[4];
+    char   irdaServiceName[25];
+} SOCKADDR_IRDA;
+
+typedef struct _WINDOWS_IRDA_DEVICE_INFO {
+    UCHAR irdaDeviceID[4];
+    char  irdaDeviceName[22];
+    UCHAR irdaDeviceHints1;
+    UCHAR irdaDeviceHints2;
+    UCHAR irdaCharSet;
+} WINDOWS_IRDA_DEVICE_INFO;
+
+typedef struct _WINDOWS_IAS_SET {
+    char  irdaClassName[IAS_MAX_CLASSNAME];
+    char  irdaAttribName[IAS_MAX_ATTRIBNAME];
+    ULONG irdaAttribType;
+    union {
+        LONG irdaAttribInt;
+        struct {
+            USHORT Len;
+            UCHAR OctetSeq[IAS_MAX_OCTET_STRING];
+        } irdaAttribOctetSeq;
+        struct {
+            UCHAR Len;
+            UCHAR CharSet;
+            UCHAR UsrStr[IAS_MAX_USER_STRING];
+        } irdaAttribUsrStr;
+    } irdaAttribute;
+} WINDOWS_IAS_SET;
+
+typedef struct _WINDOWS_IAS_QUERY {
+    UCHAR irdaDeviceID[4];
+    char  irdaClassName[IAS_MAX_CLASSNAME];
+    char  irdaAttribName[IAS_MAX_ATTRIBNAME];
+    ULONG irdaAttribType;
+    union {
+        LONG irdaAttribInt;
+        struct {
+            ULONG Len;
+            UCHAR OctetSeq[IAS_MAX_OCTET_STRING];
+        } irdaAttribOctetSeq;
+        struct {
+            ULONG Len;
+            ULONG CharSet;
+            UCHAR UsrStr[IAS_MAX_USER_STRING];
+        } irdaAttribUsrStr;
+    } irdaAttribute;
+} WINDOWS_IAS_QUERY;
+
+typedef struct _WINDOWS_DEVICELIST {
+    ULONG numDevice;
+    WINDOWS_IRDA_DEVICE_INFO Device[1];
+} WINDOWS_DEVICELIST;
+
+typedef WINDOWS_DEVICELIST DEVICELIST;
+typedef WINDOWS_DEVICELIST *PDEVICELIST;
+typedef WINDOWS_DEVICELIST *PWINDOWS_DEVICELIST;
+
+typedef WINDOWS_IRDA_DEVICE_INFO IRDA_DEVICE_INFO;
+typedef WINDOWS_IRDA_DEVICE_INFO *PIRDA_DEVICE_INFO;
+typedef WINDOWS_IRDA_DEVICE_INFO *PWINDOWS_IRDA_DEVICE_INFO;
+
+typedef WINDOWS_IAS_SET IAS_SET;
+typedef WINDOWS_IAS_SET *PIAS_SET;
+typedef WINDOWS_IAS_SET *PWINDOWS_IAS_SET;
+
+typedef WINDOWS_IAS_QUERY IAS_QUERY;
+typedef WINDOWS_IAS_QUERY *PIAS_QUERY;
+typedef WINDOWS_IAS_QUERY *PWINDOWS_IAS_QUERY;
+
+typedef SOCKADDR_IRDA *PSOCKADDR_IRDA;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AF_IRDA_H */
diff --git a/include/msvcrt/crttypes.h b/include/msvcrt/crttypes.h
new file mode 100644 (file)
index 0000000..fe15209
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            include/msvcrt/crttypes.h
+ * PURPOSE:         
+ * PROGRAMMER:      
+ * UPDATE HISTORY: 
+ *                
+ */
+
+#ifndef __CRT_TYPES__
+#define __CRT_TYPES__
+
+
+#ifdef  __GNUC__
+
+//typedef long long LONGLONG;
+//typedef unsigned long long ULONGLONG;
+//typedef long long *PLONGLONG;
+//typedef unsigned long long *PULONGLONG;
+#define HAVE_LONGLONG
+#define LONGLONG_DEFINED
+#define LONGLONG    long long
+#define ULONGLONG   unsigned long long
+#define PLONGLONG   long long *
+#define PULONGLONG  unsigned long long *
+
+#else /*__GNUC__*/
+
+#define LONGLONG_DEFINED
+#define LONGLONG    __int64
+#define ULONGLONG   unsigned __int64
+#define PLONGLONG   __int64*
+#define PULONGLONG  unsigned __int64*
+#define __attribute__(a)
+#define __volatile
+
+#define inline __inline
+#define __asm__
+#define __volatile__(a)
+#define __attribute__(a)
+struct _KTHREAD { int foobar; };
+struct _ETHREAD { int foobar; };
+struct _EPROCESS { int foobar; };
+
+#ifndef _DEBUG
+#pragma function(_disable,_enable)
+#pragma function(_inp,_inpw,_outp,_outpw)
+#pragma function(_lrotl,_lrotr,_rotl,_rotr)
+#pragma function(abs,fabs,labs)
+#pragma function(memcpy,memcmp,memset)
+#pragma function(strcat,strcmp,strcpy,strlen,_strset)
+#pragma function(fmod,sqrt)
+#pragma function(log,log10,pow,exp)
+#pragma function(tan,atan,atan2,tanh)
+#pragma function(cos,acos,cosh)
+#pragma function(sin,asin,sinh)
+#endif
+
+#endif /*__GNUC__*/
+
+
+#endif /* __CRT_TYPES__ */
diff --git a/include/ntos/ldrtypes.h b/include/ntos/ldrtypes.h
new file mode 100755 (executable)
index 0000000..74501a3
--- /dev/null
@@ -0,0 +1,18 @@
+/* $Id$ */
+
+#ifndef __INCLUDE_DDK_LDRTYPES_H
+#define __INCLUDE_DDK_LDRTYPES_H
+
+typedef struct _LDR_RESOURCE_INFO
+{
+    ULONG Type;
+    ULONG Name;
+    ULONG Language;
+} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO;
+
+#define RESOURCE_TYPE_LEVEL      0
+#define RESOURCE_NAME_LEVEL      1
+#define RESOURCE_LANGUAGE_LEVEL  2
+#define RESOURCE_DATA_LEVEL      3
+
+#endif /* __INCLUDE_DDK_LDRTYPES_H */
diff --git a/include/ntos/rtl.h b/include/ntos/rtl.h
new file mode 100755 (executable)
index 0000000..a1f0f2e
--- /dev/null
@@ -0,0 +1,2224 @@
+/* $Id$
+ * 
+ */
+
+#ifndef __DDK_RTL_H
+#define __DDK_RTL_H
+
+#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined (__NTAPP__)
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */
+
+#include <pe.h>
+
+
+#ifndef __USE_W32API
+
+/*
+ * PURPOSE: Flags for RtlQueryRegistryValues
+ */
+#define RTL_QUERY_REGISTRY_SUBKEY      (0x00000001)
+#define RTL_QUERY_REGISTRY_TOPKEY      (0x00000002)
+#define RTL_QUERY_REGISTRY_REQUIRED    (0x00000004)
+#define RTL_QUERY_REGISTRY_NOVALUE     (0x00000008)
+#define RTL_QUERY_REGISTRY_NOEXPAND    (0x00000010)
+#define RTL_QUERY_REGISTRY_DIRECT      (0x00000020)
+#define RTL_QUERY_REGISTRY_DELETE      (0x00000040)
+
+/*
+ * VOID
+ * InitializeObjectAttributes (
+ *     POBJECT_ATTRIBUTES      InitializedAttributes,
+ *     PUNICODE_STRING         ObjectName,
+ *     ULONG                   Attributes,
+ *     HANDLE                  RootDirectory,
+ *     PSECURITY_DESCRIPTOR    SecurityDescriptor
+ *     );
+ *
+ * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a 
+ * subsequent call to ZwCreateXXX or ZwOpenXXX
+ * ARGUMENTS:
+ *        InitializedAttributes (OUT) = Caller supplied storage for the
+ *                                      object attributes
+ *        ObjectName = Full path name for object
+ *        Attributes = Attributes for the object
+ *        RootDirectory = Where the object should be placed or NULL
+ *        SecurityDescriptor = Ignored
+ */
+#define InitializeObjectAttributes(p,n,a,r,s) \
+{ \
+       (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
+       (p)->ObjectName = n; \
+       (p)->Attributes = a; \
+       (p)->RootDirectory = r; \
+       (p)->SecurityDescriptor = s; \
+       (p)->SecurityQualityOfService = NULL; \
+}
+
+
+/*
+ * VOID
+ * InitializeListHead (
+ *             PLIST_ENTRY     ListHead
+ *             );
+ *
+ * FUNCTION: Initializes a double linked list
+ * ARGUMENTS:
+ *         ListHead = Caller supplied storage for the head of the list
+ */
+#define InitializeListHead(ListHead) \
+{ \
+       (ListHead)->Flink = (ListHead); \
+       (ListHead)->Blink = (ListHead); \
+}
+
+
+/*
+ * VOID
+ * InsertHeadList (
+ *             PLIST_ENTRY     ListHead,
+ *             PLIST_ENTRY     Entry
+ *             );
+ *
+ * FUNCTION: Inserts an entry in a double linked list
+ * ARGUMENTS:
+ *        ListHead = Head of the list
+ *        Entry = Entry to insert
+ */
+#define InsertHeadList(ListHead, ListEntry) \
+{ \
+       PLIST_ENTRY OldFlink; \
+       OldFlink = (ListHead)->Flink; \
+       (ListEntry)->Flink = OldFlink; \
+       (ListEntry)->Blink = (ListHead); \
+       OldFlink->Blink = (ListEntry); \
+       (ListHead)->Flink = (ListEntry); \
+       assert((ListEntry) != NULL); \
+       assert((ListEntry)->Blink!=NULL); \
+       assert((ListEntry)->Blink->Flink == (ListEntry)); \
+       assert((ListEntry)->Flink != NULL); \
+       assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+
+/*
+ * VOID
+ * InsertTailList (
+ *             PLIST_ENTRY     ListHead,
+ *             PLIST_ENTRY     Entry
+ *             );
+ *
+ * FUNCTION:
+ *     Inserts an entry in a double linked list
+ *
+ * ARGUMENTS:
+ *     ListHead = Head of the list
+ *     Entry = Entry to insert
+ */
+#define InsertTailList(ListHead, ListEntry) \
+{ \
+       PLIST_ENTRY OldBlink; \
+       OldBlink = (ListHead)->Blink; \
+       (ListEntry)->Flink = (ListHead); \
+       (ListEntry)->Blink = OldBlink; \
+       OldBlink->Flink = (ListEntry); \
+       (ListHead)->Blink = (ListEntry); \
+       assert((ListEntry) != NULL); \
+       assert((ListEntry)->Blink != NULL); \
+       assert((ListEntry)->Blink->Flink == (ListEntry)); \
+       assert((ListEntry)->Flink != NULL); \
+       assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+/*
+ * BOOLEAN
+ * IsListEmpty (
+ *     PLIST_ENTRY     ListHead
+ *     );
+ *
+ * FUNCTION:
+ *     Checks if a double linked list is empty
+ *
+ * ARGUMENTS:
+ *     ListHead = Head of the list
+*/
+#define IsListEmpty(ListHead) \
+       ((ListHead)->Flink == (ListHead))
+
+
+/*
+ * PSINGLE_LIST_ENTRY
+ * PopEntryList (
+ *     PSINGLE_LIST_ENTRY      ListHead
+ *     );
+ *
+ * FUNCTION:
+ *     Removes an entry from the head of a single linked list
+ *
+ * ARGUMENTS:
+ *     ListHead = Head of the list
+ *
+ * RETURNS:
+ *     The removed entry
+ */
+/*
+#define PopEntryList(ListHead) \
+       (ListHead)->Next; \
+       { \
+               PSINGLE_LIST_ENTRY FirstEntry; \
+               FirstEntry = (ListHead)->Next; \
+               if (FirstEntry != NULL) \
+               { \
+                       (ListHead)->Next = FirstEntry->Next; \
+               } \
+       }
+*/
+static inline PSINGLE_LIST_ENTRY
+PopEntryList(PSINGLE_LIST_ENTRY ListHead)
+{
+  PSINGLE_LIST_ENTRY ListEntry;
+
+  ListEntry = ListHead->Next;
+  if (ListEntry!=NULL)
+  {
+    ListHead->Next = ListEntry->Next;
+  }
+
+  return(ListEntry);
+}
+
+#define RtlCopyMemory(Destination,Source,Length) \
+       memcpy((Destination),(Source),(Length))
+
+static
+inline
+VOID
+PushEntryList (
+       PSINGLE_LIST_ENTRY      ListHead,
+       PSINGLE_LIST_ENTRY      Entry
+       )
+{
+       Entry->Next = ListHead->Next;
+       ListHead->Next = Entry;
+}
+
+/*
+ *VOID
+ *RemoveEntryList (
+ *     PLIST_ENTRY     Entry
+ *     );
+ *
+ * FUNCTION:
+ *     Removes an entry from a double linked list
+ *
+ * ARGUMENTS:
+ *     ListEntry = Entry to remove
+ */
+#define RemoveEntryList(ListEntry) \
+{ \
+       PLIST_ENTRY OldFlink; \
+       PLIST_ENTRY OldBlink; \
+       assert((ListEntry) != NULL); \
+       assert((ListEntry)->Blink!=NULL); \
+       assert((ListEntry)->Blink->Flink == (ListEntry)); \
+       assert((ListEntry)->Flink != NULL); \
+       assert((ListEntry)->Flink->Blink == (ListEntry)); \
+       OldFlink = (ListEntry)->Flink; \
+       OldBlink = (ListEntry)->Blink; \
+       OldFlink->Blink = OldBlink; \
+       OldBlink->Flink = OldFlink; \
+        (ListEntry)->Flink = NULL; \
+        (ListEntry)->Blink = NULL; \
+}
+
+
+/*
+ * PLIST_ENTRY
+ * RemoveHeadList (
+ *     PLIST_ENTRY     ListHead
+ *     );
+ *
+ * FUNCTION:
+ *     Removes the head entry from a double linked list
+ *
+ * ARGUMENTS:
+ *     ListHead = Head of the list
+ *
+ * RETURNS:
+ *     The removed entry
+ */
+/*
+#define RemoveHeadList(ListHead) \
+       (ListHead)->Flink; \
+       {RemoveEntryList((ListHead)->Flink)}
+*/
+/*
+PLIST_ENTRY
+RemoveHeadList (
+       PLIST_ENTRY     ListHead
+       );
+*/
+
+static
+inline
+PLIST_ENTRY
+RemoveHeadList (
+       PLIST_ENTRY     ListHead
+       )
+{
+       PLIST_ENTRY Old;
+       PLIST_ENTRY OldFlink;
+       PLIST_ENTRY OldBlink;
+
+       Old = ListHead->Flink;
+
+       OldFlink = ListHead->Flink->Flink;
+       OldBlink = ListHead->Flink->Blink;
+       OldFlink->Blink = OldBlink;
+       OldBlink->Flink = OldFlink;
+        if (Old != ListHead)
+     {
+        Old->Flink = NULL;
+        Old->Blink = NULL;
+     }
+   
+       return(Old);
+}
+
+
+/*
+ * PLIST_ENTRY
+ * RemoveTailList (
+ *     PLIST_ENTRY     ListHead
+ *     );
+ *
+ * FUNCTION:
+ *     Removes the tail entry from a double linked list
+ *
+ * ARGUMENTS:
+ *     ListHead = Head of the list
+ *
+ * RETURNS:
+ *     The removed entry
+ */
+/*
+#define RemoveTailList(ListHead) \
+       (ListHead)->Blink; \
+       {RemoveEntryList((ListHead)->Blink)}
+*/
+/*
+PLIST_ENTRY
+RemoveTailList (
+       PLIST_ENTRY     ListHead
+       );
+*/
+
+static
+inline
+PLIST_ENTRY
+RemoveTailList (
+       PLIST_ENTRY ListHead
+       )
+{
+       PLIST_ENTRY Old;
+       PLIST_ENTRY OldFlink;
+       PLIST_ENTRY OldBlink;
+
+       Old = ListHead->Blink;
+
+       OldFlink = ListHead->Blink->Flink;
+       OldBlink = ListHead->Blink->Blink;
+       OldFlink->Blink = OldBlink;
+       OldBlink->Flink = OldFlink;
+   if (Old != ListHead)
+     {
+        Old->Flink = NULL;
+        Old->Blink = NULL;
+     }
+   
+       return(Old);
+}
+
+NTSTATUS
+STDCALL
+RtlAppendUnicodeToString (
+       PUNICODE_STRING Destination,
+       PWSTR           Source
+       );
+
+ULONG
+STDCALL
+RtlCompareMemory (
+       PVOID   Source1,
+       PVOID   Source2,
+       ULONG   Length
+       );
+
+BOOLEAN
+STDCALL
+RtlEqualUnicodeString (
+       PUNICODE_STRING String1,
+       PUNICODE_STRING String2,
+       BOOLEAN         CaseInSensitive
+       );
+
+VOID
+RtlGetCallersAddress (
+       PVOID   * CallersAddress
+       );
+
+NTSTATUS
+STDCALL
+RtlQueryRegistryValues (
+       IN      ULONG                           RelativeTo,
+       IN      PWSTR                           Path,
+       IN      PRTL_QUERY_REGISTRY_TABLE       QueryTable,
+       IN      PVOID                           Context,
+       IN      PVOID                           Environment
+       );
+
+NTSTATUS
+STDCALL
+RtlWriteRegistryValue (
+       ULONG   RelativeTo,
+       PWSTR   Path,
+       PWSTR   ValueName,
+       ULONG   ValueType,
+       PVOID   ValueData,
+       ULONG   ValueLength
+       );
+
+NTSTATUS STDCALL
+RtlDeleteRegistryValue(IN ULONG RelativeTo,
+                      IN PWSTR Path,
+                      IN PWSTR ValueName);
+
+VOID STDCALL
+RtlMoveMemory (PVOID Destination, CONST VOID* Source, ULONG Length);
+
+BOOLEAN STDCALL
+RtlEqualLuid(IN PLUID Luid1,
+            IN PLUID Luid2);
+
+VOID
+STDCALL
+RtlFillMemory (
+       PVOID   Destination,
+       ULONG   Length,
+       UCHAR   Fill
+       );
+
+VOID STDCALL
+RtlZeroMemory (PVOID Destination, ULONG Length);
+
+#else /* __USE_W32API */
+
+#include <ddk/ntifs.h>
+
+#endif /* __USE_W32API */
+
+
+/*
+ * PURPOSE: Used with RtlCheckRegistryKey, RtlCreateRegistryKey, 
+ * RtlDeleteRegistryKey
+ */
+#define RTL_REGISTRY_ABSOLUTE   0
+#define RTL_REGISTRY_SERVICES   1
+#define RTL_REGISTRY_CONTROL    2
+#define RTL_REGISTRY_WINDOWS_NT 3
+#define RTL_REGISTRY_DEVICEMAP  4
+#define RTL_REGISTRY_USER       5
+#define RTL_REGISTRY_ENUM       6   // ReactOS specific: Used internally in kernel only
+#define RTL_REGISTRY_MAXIMUM    7
+
+#define RTL_REGISTRY_HANDLE     0x40000000
+#define RTL_REGISTRY_OPTIONAL   0x80000000
+
+
+#define SHORT_SIZE     (sizeof(USHORT))
+#define SHORT_MASK     (SHORT_SIZE-1)
+#define LONG_SIZE      (sizeof(ULONG))
+#define LONG_MASK      (LONG_SIZE-1)
+#define LOWBYTE_MASK   0x00FF
+
+#define FIRSTBYTE(Value)       ((Value) & LOWBYTE_MASK)
+#define SECONDBYTE(Value)      (((Value) >> 8) & LOWBYTE_MASK)
+#define THIRDBYTE(Value)       (((Value) >> 16) & LOWBYTE_MASK)
+#define FOURTHBYTE(Value)      (((Value) >> 24) & LOWBYTE_MASK)
+
+/* FIXME: reverse byte-order on big-endian machines (e.g. MIPS) */
+#define SHORT_LEAST_SIGNIFICANT_BIT    0
+#define SHORT_MOST_SIGNIFICANT_BIT     1
+
+#define LONG_LEAST_SIGNIFICANT_BIT     0
+#define LONG_3RD_MOST_SIGNIFICANT_BIT  1
+#define LONG_2RD_MOST_SIGNIFICANT_BIT  2
+#define LONG_MOST_SIGNIFICANT_BIT      3
+
+
+
+#if defined(__NTOSKRNL__) || defined(__NTDLL__)
+#define NLS_MB_CODE_PAGE_TAG     NlsMbCodePageTag
+#define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
+#else
+#define NLS_MB_CODE_PAGE_TAG     (*NlsMbCodePageTag)
+#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag)
+#endif /* __NTOSKRNL__ || __NTDLL__ */
+
+extern BOOLEAN NLS_MB_CODE_PAGE_TAG;
+extern BOOLEAN NLS_MB_OEM_CODE_PAGE_TAG;
+
+
+/*
+ * NOTE: ReactOS extensions
+ */
+#define RtlMin(X,Y) (((X) < (Y))? (X) : (Y))
+#define RtlMax(X,Y) (((X) > (Y))? (X) : (Y))
+#define RtlMin3(X,Y,Z) (((X) < (Y)) ? RtlMin(X,Z) : RtlMin(Y,Z))
+#define RtlMax3(X,Y,Z) (((X) > (Y)) ? RtlMax(X,Z) : RtlMax(Y,Z))
+
+
+/*
+ * VOID
+ * InitializeUnicodeString(PUNICODE_STRING DestinationString,
+ *                         USHORT Lenght,
+ *                         USHORT MaximumLength,
+ *                         PCWSTR Buffer);
+ *
+ * Initialize n UNICODE_STRING from its fields. Use when you know the values of
+ * all the fields in advance
+ */
+
+#define InitializeUnicodeString(__PDEST_STRING__,__LENGTH__,__MAXLENGTH__,__BUFFER__) \
+{ \
+  (__PDEST_STRING__)->Length = (__LENGTH__); \
+  (__PDEST_STRING__)->MaximumLength = (__MAXLENGTH__); \
+  (__PDEST_STRING__)->Buffer = (__BUFFER__); \
+}
+
+
+/*
+ * VOID
+ * RtlInitUnicodeStringFromLiteral(PUNICODE_STRING DestinationString,
+ *                                 PCWSTR SourceString);
+ *
+ * Initialize a UNICODE_STRING from a wide string literal. WARNING: use only with
+ * string literals and statically initialized arrays, it will calculate the wrong
+ * length otherwise
+ */
+
+#define RtlInitUnicodeStringFromLiteral(__PDEST_STRING__,__SOURCE_STRING__) \
+ InitializeUnicodeString( \
+  (__PDEST_STRING__), \
+  sizeof(__SOURCE_STRING__) - sizeof(WCHAR), \
+  sizeof(__SOURCE_STRING__), \
+  (__SOURCE_STRING__) \
+)
+
+
+/*
+ * Static initializer for UNICODE_STRING variables.
+ *
+ * Usage:
+ *    UNICODE_STRING wstr = UNICODE_STRING_INITIALIZER(L"string");
+ */
+
+#define UNICODE_STRING_INITIALIZER(__SOURCE_STRING__) \
+{ \
+  sizeof((__SOURCE_STRING__)) - sizeof(WCHAR), \
+  sizeof((__SOURCE_STRING__)), \
+  (__SOURCE_STRING__) \
+}
+
+
+/*
+ * Initializer for empty UNICODE_STRING variables.
+ *
+ * Usage:
+ *    UNICODE_STRING wstr = EMPTY_UNICODE_STRING;
+ */
+
+#define EMPTY_UNICODE_STRING {0, 0, NULL}
+
+
+/*
+VOID
+PushEntryList (
+       PSINGLE_LIST_ENTRY      ListHead,
+       PSINGLE_LIST_ENTRY      Entry
+       );
+*/
+/*
+#define PushEntryList(ListHead,Entry) \
+       (Entry)->Next = (ListHead)->Next; \
+       (ListHead)->Next = (Entry)
+*/
+
+
+#ifndef __USE_W32API
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+PSINGLE_LIST_ENTRY
+ PopEntrySList(
+       PSLIST_HEADER   ListHead
+       )
+{
+       PSINGLE_LIST_ENTRY ListEntry;
+
+       ListEntry = ListHead->s.Next.Next;
+       if (ListEntry!=NULL)
+       {
+               ListHead->s.Next.Next = ListEntry->Next;
+    ListHead->s.Depth++;
+    ListHead->s.Sequence++;
+  }
+       return ListEntry;
+}
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+VOID
+PushEntrySList (
+       PSLIST_HEADER   ListHead,
+       PSINGLE_LIST_ENTRY      Entry
+       )
+{
+       Entry->Next = ListHead->s.Next.Next;
+       ListHead->s.Next.Next = Entry;
+  ListHead->s.Depth++;
+  ListHead->s.Sequence++;
+}
+
+#else /* __USE_W32API */
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+PSINGLE_LIST_ENTRY
+ PopEntrySList(
+       PSLIST_HEADER   ListHead
+       )
+{
+       PSINGLE_LIST_ENTRY ListEntry;
+
+       ListEntry = ListHead->Next.Next;
+       if (ListEntry!=NULL)
+       {
+               ListHead->Next.Next = ListEntry->Next;
+    ListHead->Depth++;
+    ListHead->Sequence++;
+  }
+       return ListEntry;
+}
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+VOID
+PushEntrySList (
+       PSLIST_HEADER   ListHead,
+       PSINGLE_LIST_ENTRY      Entry
+       )
+{
+       Entry->Next = ListHead->Next.Next;
+       ListHead->Next.Next = Entry;
+  ListHead->Depth++;
+  ListHead->Sequence++;
+}
+
+#endif /* __USE_W32API */
+
+
+NTSTATUS
+STDCALL
+RtlAddAtomToAtomTable (
+       IN      PRTL_ATOM_TABLE AtomTable,
+       IN      PWSTR           AtomName,
+       OUT     PRTL_ATOM       Atom
+       );
+
+PVOID STDCALL
+RtlAllocateHeap (
+       HANDLE  Heap,
+       ULONG   Flags,
+       ULONG   Size
+       );
+
+WCHAR
+STDCALL
+RtlAnsiCharToUnicodeChar (
+       CHAR    AnsiChar
+       );
+
+ULONG
+STDCALL
+RtlAnsiStringToUnicodeSize (
+       PANSI_STRING    AnsiString
+       );
+
+NTSTATUS
+STDCALL
+RtlAnsiStringToUnicodeString (
+       PUNICODE_STRING DestinationString,
+       PANSI_STRING    SourceString,
+       BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlAppendAsciizToString(
+       PSTRING Destination,
+       PCSZ    Source
+       );
+
+NTSTATUS
+STDCALL
+RtlAppendStringToString (
+       PSTRING Destination,
+       PSTRING Source
+       );
+
+NTSTATUS
+STDCALL
+RtlAppendUnicodeStringToString (
+       PUNICODE_STRING Destination,
+       PUNICODE_STRING Source
+       );
+
+BOOLEAN
+STDCALL
+RtlAreBitsClear (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           StartingIndex,
+       ULONG           Length
+       );
+
+BOOLEAN
+STDCALL
+RtlAreBitsSet (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           StartingIndex,
+       ULONG           Length
+       );
+
+VOID
+STDCALL
+RtlAssert (
+       PVOID FailedAssertion,
+       PVOID FileName,
+       ULONG LineNumber,
+       PCHAR Message
+       );
+
+NTSTATUS
+STDCALL
+RtlCharToInteger (
+       PCSZ    String,
+       ULONG   Base,
+       PULONG  Value
+       );
+
+NTSTATUS
+STDCALL
+RtlCheckRegistryKey (
+       ULONG   RelativeTo,
+       PWSTR   Path
+       );
+
+VOID
+STDCALL
+RtlClearAllBits (
+       IN      PRTL_BITMAP     BitMapHeader
+       );
+
+VOID
+STDCALL
+RtlClearBits (
+       IN      PRTL_BITMAP     BitMapHeader,
+       IN      ULONG           StartingIndex,
+       IN      ULONG           NumberToClear
+       );
+
+DWORD
+STDCALL
+RtlCompactHeap (
+       HANDLE  hheap,
+       DWORD   flags
+       );
+
+LONG
+STDCALL
+RtlCompareString (
+       PSTRING String1,
+       PSTRING String2,
+       BOOLEAN CaseInsensitive
+       );
+
+LONG
+STDCALL
+RtlCompareUnicodeString (
+       PUNICODE_STRING String1,
+       PUNICODE_STRING String2,
+       BOOLEAN         CaseInsensitive
+       );
+
+NTSTATUS STDCALL
+RtlCompressBuffer(IN USHORT CompressionFormatAndEngine,
+                 IN PUCHAR UncompressedBuffer,
+                 IN ULONG UncompressedBufferSize,
+                 OUT PUCHAR CompressedBuffer,
+                 IN ULONG CompressedBufferSize,
+                 IN ULONG UncompressedChunkSize,
+                 OUT PULONG FinalCompressedSize,
+                 IN PVOID WorkSpace);
+
+NTSTATUS STDCALL
+RtlCompressChunks(IN PUCHAR UncompressedBuffer,
+                 IN ULONG UncompressedBufferSize,
+                 OUT PUCHAR CompressedBuffer,
+                 IN ULONG CompressedBufferSize,
+                 IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo,
+                 IN ULONG CompressedDataInfoLength,
+                 IN PVOID WorkSpace);
+
+LARGE_INTEGER STDCALL
+RtlConvertLongToLargeInteger(IN LONG SignedInteger);
+
+NTSTATUS STDCALL
+RtlConvertSidToUnicodeString(IN OUT PUNICODE_STRING String,
+                            IN PSID Sid,
+                            IN BOOLEAN AllocateString);
+
+LARGE_INTEGER STDCALL
+RtlConvertUlongToLargeInteger(IN ULONG UnsignedInteger);
+
+#if 0
+VOID
+RtlCopyBytes (
+       PVOID           Destination,
+       CONST VOID      * Source,
+       ULONG           Length
+       );
+
+VOID
+RtlCopyMemory (
+       VOID            * Destination,
+       CONST VOID      * Source,
+       ULONG           Length
+       );
+#endif
+
+#define RtlCopyBytes RtlCopyMemory
+
+VOID STDCALL
+RtlCopyLuid(IN PLUID LuidDest,
+           IN PLUID LuidSrc);
+
+VOID STDCALL
+RtlCopyLuidAndAttributesArray(ULONG Count,
+                             PLUID_AND_ATTRIBUTES Src,
+                             PLUID_AND_ATTRIBUTES Dest);
+
+NTSTATUS STDCALL
+RtlCopySid(ULONG BufferLength,
+          PSID Dest,
+          PSID Src);
+
+NTSTATUS STDCALL
+RtlCopySidAndAttributesArray(ULONG Count,
+                            PSID_AND_ATTRIBUTES Src,
+                            ULONG SidAreaSize,
+                            PSID_AND_ATTRIBUTES Dest,
+                            PVOID SidArea,
+                            PVOID* RemainingSidArea,
+                            PULONG RemainingSidAreaSize);
+
+VOID STDCALL
+RtlCopyString(PSTRING DestinationString,
+             PSTRING SourceString);
+
+VOID STDCALL
+RtlCopyUnicodeString(PUNICODE_STRING DestinationString,
+                    PUNICODE_STRING SourceString);
+
+NTSTATUS STDCALL
+RtlCreateAtomTable(IN ULONG TableSize,
+                  IN OUT PRTL_ATOM_TABLE *AtomTable);
+
+HANDLE
+STDCALL
+RtlCreateHeap (
+       ULONG                   Flags,
+       PVOID                   BaseAddress,
+       ULONG                   SizeToReserve,     // dwMaximumSize
+       ULONG                   SizeToCommit,      // dwInitialSize
+       PVOID                   Unknown,
+       PRTL_HEAP_DEFINITION    Definition
+       );
+
+NTSTATUS
+STDCALL
+RtlCreateRegistryKey (
+       ULONG   RelativeTo,
+       PWSTR   Path
+       );
+
+NTSTATUS
+STDCALL
+RtlCreateSecurityDescriptor (
+       PSECURITY_DESCRIPTOR    SecurityDescriptor,
+       ULONG                   Revision
+       );
+
+BOOLEAN
+STDCALL
+RtlCreateUnicodeString (
+       OUT     PUNICODE_STRING Destination,
+       IN      PWSTR           Source
+       );
+
+BOOLEAN STDCALL
+RtlCreateUnicodeStringFromAsciiz (OUT  PUNICODE_STRING Destination,
+                                 IN    PCSZ            Source);
+
+NTSTATUS
+STDCALL
+RtlCustomCPToUnicodeN (
+       PRTL_NLS_DATA   NlsData,
+       PWCHAR          UnicodeString,
+       ULONG           UnicodeSize,
+       PULONG          ResultSize,
+       PCHAR           CustomString,
+       ULONG           CustomSize
+       );
+
+NTSTATUS STDCALL
+RtlDecompressBuffer(IN USHORT CompressionFormat,
+                   OUT PUCHAR UncompressedBuffer,
+                   IN ULONG UncompressedBufferSize,
+                   IN PUCHAR CompressedBuffer,
+                   IN ULONG CompressedBufferSize,
+                   OUT PULONG FinalUncompressedSize);
+
+NTSTATUS STDCALL
+RtlDecompressChunks(OUT PUCHAR UncompressedBuffer,
+                   IN ULONG UncompressedBufferSize,
+                   IN PUCHAR CompressedBuffer,
+                   IN ULONG CompressedBufferSize,
+                   IN PUCHAR CompressedTail,
+                   IN ULONG CompressedTailSize,
+                   IN PCOMPRESSED_DATA_INFO CompressedDataInfo);
+
+NTSTATUS STDCALL
+RtlDecompressFragment(IN USHORT CompressionFormat,
+                     OUT PUCHAR UncompressedFragment,
+                     IN ULONG UncompressedFragmentSize,
+                     IN PUCHAR CompressedBuffer,
+                     IN ULONG CompressedBufferSize,
+                     IN ULONG FragmentOffset,
+                     OUT PULONG FinalUncompressedSize,
+                     IN PVOID WorkSpace);
+
+NTSTATUS STDCALL
+RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
+                          IN RTL_ATOM Atom);
+
+NTSTATUS STDCALL
+RtlDescribeChunk(IN USHORT CompressionFormat,
+                IN OUT PUCHAR *CompressedBuffer,
+                IN PUCHAR EndOfCompressedBufferPlus1,
+                OUT PUCHAR *ChunkBuffer,
+                OUT PULONG ChunkSize);
+
+NTSTATUS STDCALL
+RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable);
+
+BOOL STDCALL
+RtlDestroyHeap(HANDLE hheap);
+
+NTSTATUS
+STDCALL
+RtlDowncaseUnicodeString (
+       IN OUT PUNICODE_STRING  DestinationString,
+       IN PUNICODE_STRING      SourceString,
+       IN BOOLEAN              AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlEmptyAtomTable (
+       IN      PRTL_ATOM_TABLE AtomTable,
+       IN      BOOLEAN         DeletePinned
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedIntegerMultiply (
+       LONG    Multiplicand,
+       LONG    Multiplier
+       );
+
+ULONG
+STDCALL
+RtlEnlargedUnsignedDivide (
+       ULARGE_INTEGER  Dividend,
+       ULONG           Divisor,
+       PULONG          Remainder
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedUnsignedMultiply (
+       ULONG   Multiplicand,
+       ULONG   Multiplier
+       );
+
+BOOLEAN
+STDCALL
+RtlEqualString (
+       PSTRING String1,
+       PSTRING String2,
+       BOOLEAN CaseInSensitive
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedIntegerMultiply (
+       LARGE_INTEGER   Multiplicand,
+       LONG            Multiplier
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedLargeIntegerDivide (
+       LARGE_INTEGER   Dividend,
+       ULONG           Divisor,
+       PULONG          Remainder
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedMagicDivide (
+       LARGE_INTEGER   Dividend,
+       LARGE_INTEGER   MagicDivisor,
+       CCHAR           ShiftCount
+       );
+
+VOID
+STDCALL
+RtlFillMemoryUlong (
+       PVOID   Destination,
+       ULONG   Length,
+       ULONG   Fill
+       );
+
+ULONG
+STDCALL
+RtlFindClearBits (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           NumberToFind,
+       ULONG           HintIndex
+       );
+
+ULONG
+STDCALL
+RtlFindClearBitsAndSet (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           NumberToFind,
+       ULONG           HintIndex
+       );
+
+ULONG
+STDCALL
+RtlFindFirstRunClear (
+       PRTL_BITMAP     BitMapHeader,
+       PULONG          StartingIndex
+       );
+
+ULONG
+STDCALL
+RtlFindFirstRunSet (
+       PRTL_BITMAP     BitMapHeader,
+       PULONG          StartingIndex
+       );
+
+ULONG
+STDCALL
+RtlFindLongestRunClear (
+       PRTL_BITMAP     BitMapHeader,
+       PULONG          StartingIndex
+       );
+
+ULONG
+STDCALL
+RtlFindLongestRunSet (
+       PRTL_BITMAP     BitMapHeader,
+       PULONG          StartingIndex
+       );
+
+NTSTATUS
+STDCALL
+RtlFindMessage (
+       IN      PVOID                           BaseAddress,
+       IN      ULONG                           Type,
+       IN      ULONG                           Language,
+       IN      ULONG                           MessageId,
+       OUT     PRTL_MESSAGE_RESOURCE_ENTRY     *MessageResourceEntry
+       );
+
+ULONG
+STDCALL
+RtlFindSetBits (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           NumberToFind,
+       ULONG           HintIndex
+       );
+
+ULONG
+STDCALL
+RtlFindSetBitsAndClear (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           NumberToFind,
+       ULONG           HintIndex
+       );
+
+NTSTATUS
+STDCALL
+RtlFormatCurrentUserKeyPath (
+       IN OUT  PUNICODE_STRING KeyPath
+       );
+
+VOID
+STDCALL
+RtlFreeAnsiString (
+       PANSI_STRING    AnsiString
+       );
+
+BOOLEAN
+STDCALL
+RtlFreeHeap (
+       HANDLE  Heap,
+       ULONG   Flags,
+       PVOID   Address
+       );
+
+VOID
+STDCALL
+RtlFreeOemString (
+       POEM_STRING     OemString
+       );
+
+VOID
+STDCALL
+RtlFreeUnicodeString (
+       PUNICODE_STRING UnicodeString
+       );
+
+VOID STDCALL
+RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
+                    IN BOOLEAN AllowExtendedCharacters,
+                    IN OUT PGENERATE_NAME_CONTEXT Context,
+                    OUT PUNICODE_STRING Name8dot3);
+
+NTSTATUS STDCALL
+RtlGetCompressionWorkSpaceSize(IN USHORT CompressionFormatAndEngine,
+                              OUT PULONG CompressBufferAndWorkSpaceSize,
+                              OUT PULONG CompressFragmentWorkSpaceSize);
+
+VOID
+STDCALL
+RtlGetDefaultCodePage (
+       PUSHORT AnsiCodePage,
+       PUSHORT OemCodePage
+       );
+
+PVOID
+STDCALL
+RtlImageDirectoryEntryToData (
+       PVOID   BaseAddress,
+       BOOLEAN bFlag,
+       ULONG   Directory,
+       PULONG  Size
+       );
+
+PIMAGE_NT_HEADERS
+STDCALL
+RtlImageNtHeader (
+       PVOID   BaseAddress
+       );
+
+PIMAGE_SECTION_HEADER
+STDCALL
+RtlImageRvaToSection (
+       PIMAGE_NT_HEADERS       NtHeader,
+       PVOID                   BaseAddress,
+       ULONG                   Rva
+       );
+
+ULONG
+STDCALL
+RtlImageRvaToVa (
+       PIMAGE_NT_HEADERS       NtHeader,
+       PVOID                   BaseAddress,
+       ULONG                   Rva,
+       PIMAGE_SECTION_HEADER   *SectionHeader
+       );
+
+VOID
+STDCALL
+RtlInitAnsiString (
+       PANSI_STRING    DestinationString,
+       PCSZ            SourceString
+       );
+
+VOID
+STDCALL
+RtlInitString (
+       PSTRING DestinationString,
+       PCSZ    SourceString
+       );
+
+VOID
+STDCALL
+RtlInitUnicodeString (
+       PUNICODE_STRING DestinationString,
+       PCWSTR          SourceString
+       );
+
+VOID
+STDCALL
+RtlInitializeBitMap (
+       IN OUT  PRTL_BITMAP     BitMapHeader,
+       IN      PULONG          BitMapBuffer,
+       IN      ULONG           SizeOfBitMap
+       );
+
+NTSTATUS
+STDCALL
+RtlInitializeContext (
+       IN      HANDLE                  ProcessHandle,
+       IN      PCONTEXT                Context,
+       IN      PVOID                   Parameter,
+       IN      PTHREAD_START_ROUTINE   StartAddress,
+       IN OUT  PINITIAL_TEB            InitialTeb
+       );
+
+VOID
+STDCALL
+RtlInitializeGenericTable (
+       IN OUT  PRTL_GENERIC_TABLE      Table,
+       IN      PVOID                   CompareRoutine,
+       IN      PVOID                   AllocateRoutine,
+       IN      PVOID                   FreeRoutine,
+       IN      ULONG                   UserParameter
+       );
+
+PVOID
+STDCALL
+RtlInsertElementGenericTable (
+       IN OUT  PRTL_GENERIC_TABLE      Table,
+       IN      PVOID                   Element,
+       IN      ULONG                   ElementSize,
+       IN      ULONG                   Unknown4
+       );
+
+NTSTATUS
+STDCALL
+RtlIntegerToChar (
+       IN      ULONG   Value,
+       IN      ULONG   Base,
+       IN      ULONG   Length,
+       IN OUT  PCHAR   String
+       );
+
+NTSTATUS
+STDCALL
+RtlIntegerToUnicodeString (
+       IN      ULONG           Value,
+       IN      ULONG           Base,
+       IN OUT  PUNICODE_STRING String
+       );
+
+BOOLEAN
+STDCALL
+RtlIsGenericTableEmpty (
+       IN      PRTL_GENERIC_TABLE      Table
+       );
+
+BOOLEAN STDCALL
+RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName,
+                      IN PANSI_STRING AnsiName,
+                      OUT PBOOLEAN SpacesFound);
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerAdd (
+       LARGE_INTEGER   Addend1,
+       LARGE_INTEGER   Addend2
+       );
+
+/*
+ * VOID
+ * RtlLargeIntegerAnd (
+ *     PLARGE_INTEGER  Result,
+ *     LARGE_INTEGER   Source,
+ *     LARGE_INTEGER   Mask
+ *     );
+ */
+#define RtlLargeIntegerAnd(Result, Source, Mask) \
+{ \
+       Result.HighPart = Source.HighPart & Mask.HighPart; \
+       Result.LowPart = Source.LowPart & Mask.LowPart; \
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerArithmeticShift (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR   ShiftCount
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerDivide (
+       LARGE_INTEGER   Dividend,
+       LARGE_INTEGER   Divisor,
+       PLARGE_INTEGER  Remainder
+       );
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerEqualTo (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerEqualTo(X,Y) \
+       (!(((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart)))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerEqualToZero (
+ *     LARGE_INTEGER   Operand
+ *     );
+ */
+#define RtlLargeIntegerEqualToZero(X) \
+       (!((X).LowPart | (X).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThan (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerGreaterThan(X,Y) \
+       ((((X).HighPart == (Y).HighPart) && ((X).LowPart > (Y).LowPart)) || \
+         ((X).HighPart > (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanOrEqualTo (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerGreaterThanOrEqualTo(X,Y) \
+       ((((X).HighPart == (Y).HighPart) && ((X).LowPart >= (Y).LowPart)) || \
+         ((X).HighPart > (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanOrEqualToZero (
+ *     LARGE_INTEGER   Operand1
+ *     );
+ */
+#define RtlLargeIntegerGreaterOrEqualToZero(X) \
+       ((X).HighPart >= 0)
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanZero (
+ *     LARGE_INTEGER   Operand1
+ *     );
+ */
+#define RtlLargeIntegerGreaterThanZero(X) \
+       ((((X).HighPart == 0) && ((X).LowPart > 0)) || \
+         ((X).HighPart > 0 ))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThan (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerLessThan(X,Y) \
+       ((((X).HighPart == (Y).HighPart) && ((X).LowPart < (Y).LowPart)) || \
+         ((X).HighPart < (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanOrEqualTo (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerLessThanOrEqualTo(X,Y) \
+       ((((X).HighPart == (Y).HighPart) && ((X).LowPart <= (Y).LowPart)) || \
+         ((X).HighPart < (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanOrEqualToZero (
+ *     LARGE_INTEGER   Operand
+ *     );
+ */
+#define RtlLargeIntegerLessOrEqualToZero(X) \
+       (((X).HighPart < 0) || !((X).LowPart | (X).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanZero (
+ *     LARGE_INTEGER   Operand
+ *     );
+ */
+#define RtlLargeIntegerLessThanZero(X) \
+       (((X).HighPart < 0))
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerNegate (
+       LARGE_INTEGER   Subtrahend
+       );
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerNotEqualTo (
+ *     LARGE_INTEGER   Operand1,
+ *     LARGE_INTEGER   Operand2
+ *     );
+ */
+#define RtlLargeIntegerNotEqualTo(X,Y) \
+       ((((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart)))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerNotEqualToZero (
+ *     LARGE_INTEGER   Operand
+ *     );
+ */
+#define RtlLargeIntegerNotEqualToZero(X) \
+       (((X).LowPart | (X).HighPart))
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftLeft (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR           ShiftCount
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftRight (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR           ShiftCount
+       );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerSubtract (
+       LARGE_INTEGER   Minuend,
+       LARGE_INTEGER   Subtrahend
+       );
+
+ULONG
+STDCALL
+RtlLengthSecurityDescriptor (
+       PSECURITY_DESCRIPTOR    SecurityDescriptor
+       );
+
+BOOL
+STDCALL
+RtlLockHeap (
+       HANDLE  hheap
+       );
+
+NTSTATUS
+STDCALL
+RtlLookupAtomInAtomTable (
+       IN      PRTL_ATOM_TABLE AtomTable,
+       IN      PWSTR           AtomName,
+       OUT     PRTL_ATOM       Atom
+       );
+
+NTSTATUS
+STDCALL
+RtlMultiByteToUnicodeN (
+       PWCHAR UnicodeString,
+       ULONG  UnicodeSize,
+       PULONG ResultSize,
+       PCHAR  MbString,
+       ULONG  MbSize
+       );
+
+NTSTATUS
+STDCALL
+RtlMultiByteToUnicodeSize (
+       PULONG UnicodeSize,
+       PCHAR  MbString,
+       ULONG  MbSize
+       );
+
+DWORD
+STDCALL
+RtlNtStatusToDosError (
+       NTSTATUS        StatusCode
+       );
+
+DWORD
+STDCALL
+RtlNtStatusToDosErrorNoTeb (
+       NTSTATUS        StatusCode
+       );
+
+int
+STDCALL
+RtlNtStatusToPsxErrno (
+       NTSTATUS        StatusCode
+       );
+
+ULONG
+STDCALL
+RtlNumberGenericTableElements (
+       IN      PRTL_GENERIC_TABLE      Table
+       );
+
+ULONG
+STDCALL
+RtlNumberOfClearBits (
+       PRTL_BITMAP     BitMapHeader
+       );
+
+ULONG
+STDCALL
+RtlNumberOfSetBits (
+       PRTL_BITMAP     BitMapHeader
+       );
+
+ULONG
+STDCALL
+RtlOemStringToUnicodeSize (
+       POEM_STRING     AnsiString
+       );
+
+NTSTATUS
+STDCALL
+RtlOemStringToUnicodeString (
+       PUNICODE_STRING DestinationString,
+       POEM_STRING     SourceString,
+       BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlOemToUnicodeN (
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize,
+       PULONG  ResultSize,
+       PCHAR   OemString,
+       ULONG   OemSize
+       );
+
+NTSTATUS STDCALL
+RtlPinAtomInAtomTable (
+       IN      PRTL_ATOM_TABLE AtomTable,
+       IN      RTL_ATOM        Atom
+       );
+
+BOOLEAN
+STDCALL
+RtlPrefixString (
+       PANSI_STRING    String1,
+       PANSI_STRING    String2,
+       BOOLEAN         CaseInsensitive
+       );
+
+BOOLEAN
+STDCALL
+RtlPrefixUnicodeString (
+       PUNICODE_STRING String1,
+       PUNICODE_STRING String2,
+       BOOLEAN         CaseInsensitive
+       );
+
+NTSTATUS
+STDCALL
+RtlQueryAtomInAtomTable (
+       IN      PRTL_ATOM_TABLE AtomTable,
+       IN      RTL_ATOM        Atom,
+       IN OUT  PULONG          RefCount OPTIONAL,
+       IN OUT  PULONG          PinCount OPTIONAL,
+       IN OUT  PWSTR           AtomName OPTIONAL,
+       IN OUT  PULONG          NameLength OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+RtlQueryTimeZoneInformation (
+       IN OUT  PTIME_ZONE_INFORMATION  TimeZoneInformation
+       );
+
+VOID
+STDCALL
+RtlRaiseException (
+       IN      PEXCEPTION_RECORD       ExceptionRecord
+       );
+
+LPVOID
+STDCALL
+RtlReAllocateHeap (
+       HANDLE  hheap,
+       DWORD   flags,
+       LPVOID  ptr,
+       DWORD   size
+       );
+
+NTSTATUS STDCALL
+RtlReserveChunk(IN USHORT CompressionFormat,
+               IN OUT PUCHAR *CompressedBuffer,
+               IN PUCHAR EndOfCompressedBufferPlus1,
+               OUT PUCHAR *ChunkBuffer,
+               IN ULONG ChunkSize);
+
+/*
+ * VOID
+ * RtlRetrieveUlong (
+ *     PULONG  DestinationAddress,
+ *     PULONG  SourceAddress
+ *     );
+ */
+#define RtlRetrieveUlong(DestAddress,SrcAddress) \
+       if ((ULONG)(SrcAddress) & LONG_MASK) \
+       { \
+               ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \
+               ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \
+               ((PUCHAR)(DestAddress))[2]=((PUCHAR)(SrcAddress))[2]; \
+               ((PUCHAR)(DestAddress))[3]=((PUCHAR)(SrcAddress))[3]; \
+       } \
+       else \
+       { \
+               *((PULONG)(DestAddress))=*((PULONG)(SrcAddress)); \
+       }
+
+/*
+ * VOID
+ * RtlRetrieveUshort (
+ *     PUSHORT DestinationAddress,
+ *     PUSHORT SourceAddress
+ *     );
+ */
+#define RtlRetrieveUshort(DestAddress,SrcAddress) \
+       if ((ULONG)(SrcAddress) & SHORT_MASK) \
+       { \
+               ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \
+               ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \
+       } \
+       else \
+       { \
+               *((PUSHORT)(DestAddress))=*((PUSHORT)(SrcAddress)); \
+       }
+
+VOID
+STDCALL
+RtlSecondsSince1970ToTime (
+       ULONG SecondsSince1970,
+       PLARGE_INTEGER Time
+       );
+
+VOID
+STDCALL
+RtlSecondsSince1980ToTime (
+       ULONG SecondsSince1980,
+       PLARGE_INTEGER Time
+       );
+
+VOID
+STDCALL
+RtlSetAllBits (
+       IN      PRTL_BITMAP     BitMapHeader
+       );
+
+VOID
+STDCALL
+RtlSetBits (
+       PRTL_BITMAP     BitMapHeader,
+       ULONG           StartingIndex,
+       ULONG           NumberToSet
+       );
+
+NTSTATUS
+STDCALL
+RtlSetDaclSecurityDescriptor (
+       PSECURITY_DESCRIPTOR    SecurityDescriptor,
+       BOOLEAN                 DaclPresent,
+       PACL                    Dacl,
+       BOOLEAN                 DaclDefaulted
+       );
+
+NTSTATUS
+STDCALL
+RtlSetTimeZoneInformation (
+       IN OUT  PTIME_ZONE_INFORMATION  TimeZoneInformation
+       );
+
+DWORD
+STDCALL
+RtlSizeHeap (
+       HANDLE  hheap,
+       DWORD   flags,
+       PVOID   pmem
+       );
+
+/*
+ * VOID
+ * RtlStoreUlong (
+ *     PULONG  Address,
+ *     ULONG   Value
+ *     );
+ */
+#define RtlStoreUlong(Address,Value) \
+       if ((ULONG)(Address) & LONG_MASK) \
+       { \
+               ((PUCHAR)(Address))[LONG_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+               ((PUCHAR)(Address))[LONG_3RD_MOST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+               ((PUCHAR)(Address))[LONG_2ND_MOST_SIGNIFICANT_BIT]=(UCHAR)(THIRDBYTE(Value)); \
+               ((PUCHAR)(Address))[LONG_MOST_SIGNIFICANT_BIT]=(UCHAR)(FOURTHBYTE(Value)); \
+       } \
+       else \
+       { \
+               *((PULONG)(Address))=(ULONG)(Value); \
+       }
+
+/*
+ * VOID
+ * RtlStoreUshort (
+ *     PUSHORT Address,
+ *     USHORT  Value
+ *     );
+ */
+#define RtlStoreUshort(Address,Value) \
+       if ((ULONG)(Address) & SHORT_MASK) \
+       { \
+               ((PUCHAR)(Address))[SHORT_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+               ((PUCHAR)(Address))[SHORT_MOST_SIGNIFICANT_BIT]=(UCHAR)(SECONDBYTE(Value)); \
+       } \
+       else \
+       { \
+               *((PUSHORT)(Address))=(USHORT)(Value); \
+       }
+
+BOOLEAN
+STDCALL
+RtlTimeFieldsToTime (
+       PTIME_FIELDS    TimeFields,
+       PLARGE_INTEGER  Time
+       );
+
+BOOLEAN
+STDCALL
+RtlTimeToSecondsSince1970 (
+       PLARGE_INTEGER Time,
+       PULONG SecondsSince1970
+       );
+
+BOOLEAN
+STDCALL
+RtlTimeToSecondsSince1980 (
+       PLARGE_INTEGER Time,
+       PULONG SecondsSince1980
+       );
+
+VOID
+STDCALL
+RtlTimeToTimeFields (
+       PLARGE_INTEGER  Time,
+       PTIME_FIELDS    TimeFields
+       );
+
+ULONG
+STDCALL
+RtlUnicodeStringToAnsiSize (
+       IN      PUNICODE_STRING UnicodeString
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToAnsiString (
+       IN OUT  PANSI_STRING    DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToInteger (
+       IN      PUNICODE_STRING String,
+       IN      ULONG           Base,
+       OUT     PULONG          Value
+       );
+
+ULONG
+STDCALL
+RtlUnicodeStringToOemSize (
+       IN      PUNICODE_STRING UnicodeString
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToCountedOemString (
+       IN OUT  POEM_STRING     DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToOemString (
+       IN OUT  POEM_STRING     DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToCustomCPN (
+       PRTL_NLS_DATA   NlsData,
+       PCHAR           MbString,
+       ULONG           MbSize,
+       PULONG          ResultSize,
+       PWCHAR          UnicodeString,
+       ULONG           UnicodeSize
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToMultiByteN (
+       PCHAR   MbString,
+       ULONG   MbSize,
+       PULONG  ResultSize,
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToMultiByteSize (
+       PULONG  MbSize,
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize
+       );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToOemN (
+       PCHAR   OemString,
+       ULONG   OemSize,
+       PULONG  ResultSize,
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize
+       );
+
+BOOL
+STDCALL
+RtlUnlockHeap (
+       HANDLE  hheap
+       );
+
+VOID
+STDCALL
+RtlUnwind (
+  PEXCEPTION_REGISTRATION RegistrationFrame,
+  PVOID ReturnAddress,
+  PEXCEPTION_RECORD ExceptionRecord,
+  DWORD EaxValue
+       );
+
+WCHAR
+STDCALL
+RtlUpcaseUnicodeChar (
+       WCHAR Source
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeString (
+       IN OUT  PUNICODE_STRING DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToAnsiString (
+       IN OUT  PANSI_STRING    DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToCountedOemString (
+       IN OUT  POEM_STRING     DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToOemString (
+       IN OUT  POEM_STRING     DestinationString,
+       IN      PUNICODE_STRING SourceString,
+       IN      BOOLEAN         AllocateDestinationString
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToCustomCPN (
+       PRTL_NLS_DATA   NlsData,
+       PCHAR           MbString,
+       ULONG           MbSize,
+       PULONG          ResultSize,
+       PWCHAR          UnicodeString,
+       ULONG           UnicodeSize
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToMultiByteN (
+       PCHAR   MbString,
+       ULONG   MbSize,
+       PULONG  ResultSize,
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize
+       );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToOemN (
+       PCHAR   OemString,
+       ULONG   OemSize,
+       PULONG  ResultSize,
+       PWCHAR  UnicodeString,
+       ULONG   UnicodeSize
+       );
+
+CHAR
+STDCALL
+RtlUpperChar (
+       CHAR    Source
+       );
+
+VOID
+STDCALL
+RtlUpperString (
+       PSTRING DestinationString,
+       PSTRING SourceString
+       );
+
+BOOL
+STDCALL
+RtlValidateHeap (
+       HANDLE  hheap,
+       DWORD   flags,
+       PVOID   pmem
+       );
+
+BOOLEAN
+STDCALL
+RtlValidSecurityDescriptor (
+       PSECURITY_DESCRIPTOR    SecurityDescriptor
+       );
+
+BOOLEAN STDCALL
+RtlValidSid(IN PSID Sid);
+
+ULONG
+STDCALL
+RtlxAnsiStringToUnicodeSize (
+       IN      PANSI_STRING    AnsiString
+       );
+
+ULONG
+STDCALL
+RtlxOemStringToUnicodeSize (
+       IN      POEM_STRING     OemString
+       );
+
+ULONG
+STDCALL
+RtlxUnicodeStringToAnsiSize (
+       IN      PUNICODE_STRING UnicodeString
+       );
+
+ULONG
+STDCALL
+RtlxUnicodeStringToOemSize (
+       IN      PUNICODE_STRING UnicodeString
+       );
+
+
+/* Register io functions */
+
+UCHAR
+STDCALL
+READ_REGISTER_UCHAR (
+       PUCHAR  Register
+       );
+
+USHORT
+STDCALL
+READ_REGISTER_USHORT (
+       PUSHORT Register
+       );
+
+ULONG
+STDCALL
+READ_REGISTER_ULONG (
+       PULONG  Register
+       );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_UCHAR (
+       PUCHAR  Register,
+       PUCHAR  Buffer,
+       ULONG   Count
+       );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_USHORT (
+       PUSHORT Register,
+       PUSHORT Buffer,
+       ULONG   Count
+       );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_ULONG (
+       PULONG  Register,
+       PULONG  Buffer,
+       ULONG   Count
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_UCHAR (
+       PUCHAR  Register,
+       UCHAR   Value
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_USHORT (
+       PUSHORT Register,
+       USHORT  Value
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_ULONG (
+       PULONG  Register,
+       ULONG   Value
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_UCHAR (
+       PUCHAR  Register,
+       PUCHAR  Buffer,
+       ULONG   Count
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_USHORT (
+       PUSHORT Register,
+       PUSHORT Buffer,
+       ULONG   Count
+       );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_ULONG (
+       PULONG  Register,
+       PULONG  Buffer,
+       ULONG   Count
+       );
+
+
+NTSTATUS STDCALL RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision);
+NTSTATUS STDCALL RtlQueryInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass);
+NTSTATUS STDCALL RtlSetInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass);
+BOOLEAN STDCALL RtlValidAcl (PACL Acl);
+
+NTSTATUS STDCALL RtlAddAccessAllowedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid);
+NTSTATUS STDCALL RtlAddAccessDeniedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid);
+NTSTATUS STDCALL RtlAddAce(PACL Acl, ULONG Revision, ULONG StartingIndex, PACE AceList, ULONG AceListLength);
+NTSTATUS STDCALL RtlAddAuditAccessAce (PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid, BOOLEAN Success, BOOLEAN Failure);
+NTSTATUS STDCALL RtlDeleteAce(PACL Acl, ULONG AceIndex);
+BOOLEAN STDCALL RtlFirstFreeAce(PACL Acl, PACE* Ace);
+NTSTATUS STDCALL RtlGetAce(PACL Acl, ULONG AceIndex, PACE *Ace);
+
+NTSTATUS STDCALL RtlAbsoluteToSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength);
+NTSTATUS STDCALL RtlMakeSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength);
+NTSTATUS STDCALL RtlCreateSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Revision);
+BOOLEAN STDCALL RtlValidSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor);
+ULONG STDCALL RtlLengthSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor);
+NTSTATUS STDCALL RtlSetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN DaclPresent, PACL Dacl, BOOLEAN DaclDefaulted);
+NTSTATUS STDCALL RtlGetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN DaclPresent, PACL* Dacl, PBOOLEAN DaclDefauted);
+NTSTATUS STDCALL RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Owner, BOOLEAN OwnerDefaulted);
+NTSTATUS STDCALL RtlGetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Owner, PBOOLEAN OwnerDefaulted);
+NTSTATUS STDCALL RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Group, BOOLEAN GroupDefaulted);
+NTSTATUS STDCALL RtlGetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Group, PBOOLEAN GroupDefaulted);
+NTSTATUS STDCALL RtlGetControlSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL Control, PULONG Revision);
+NTSTATUS STDCALL RtlSetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN SaclPresent, PACL Sacl, BOOLEAN SaclDefaulted);
+NTSTATUS STDCALL RtlGetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN SaclPresent, PACL* Sacl, PBOOLEAN SaclDefauted);
+NTSTATUS STDCALL RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR RelSD,
+                                             PSECURITY_DESCRIPTOR AbsSD,
+                                             PDWORD AbsSDSize,
+                                             PACL Dacl,
+                                             PDWORD DaclSize,
+                                             PACL Sacl,
+                                             PDWORD SaclSize,
+                                             PSID Owner,
+                                             PDWORD OwnerSize,
+                                             PSID Group,
+                                             PDWORD GroupSize);
+
+NTSTATUS STDCALL RtlAllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
+                                             UCHAR SubAuthorityCount,
+                                             ULONG SubAuthority0,
+                                             ULONG SubAuthority1,
+                                             ULONG SubAuthority2,
+                                             ULONG SubAuthority3,
+                                             ULONG SubAuthority4,
+                                             ULONG SubAuthority5,
+                                             ULONG SubAuthority6,
+                                             ULONG SubAuthority7,
+                                             PSID *Sid);
+ULONG STDCALL RtlLengthRequiredSid (UCHAR SubAuthorityCount);
+PSID_IDENTIFIER_AUTHORITY STDCALL RtlIdentifierAuthoritySid (PSID Sid);
+NTSTATUS STDCALL RtlInitializeSid (PSID Sid, PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, UCHAR SubAuthorityCount);
+PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority);
+BOOLEAN STDCALL RtlEqualPrefixSid (PSID Sid1, PSID Sid2);
+BOOLEAN STDCALL RtlEqualSid(PSID Sid1, PSID Sid2);
+PSID STDCALL RtlFreeSid (PSID Sid);
+ULONG STDCALL RtlLengthSid (PSID Sid);
+PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority);
+PUCHAR STDCALL RtlSubAuthorityCountSid (PSID Sid);
+BOOLEAN STDCALL RtlValidSid (PSID Sid);
+NTSTATUS STDCALL RtlConvertSidToUnicodeString (PUNICODE_STRING String, PSID Sid, BOOLEAN AllocateBuffer);
+
+BOOLEAN STDCALL RtlAreAllAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess);
+BOOLEAN STDCALL RtlAreAnyAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess);
+VOID STDCALL RtlMapGenericMask (PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping);
+
+
+/*  functions exported from NTOSKRNL.EXE which are considered RTL  */
+
+#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined(__NTAPP__)
+
+char *_itoa (int value, char *string, int radix);
+int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
+int _snwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, ...);
+int _stricmp(const char *s1, const char *s2);
+char * _strlwr(char *x);
+int _strnicmp(const char *s1, const char *s2, size_t n);
+char * _strnset(char* szToFill, int szFill, size_t sizeMaxFill);
+char * _strrev(char *s);
+char * _strset(char* szToFill, int szFill);
+char * _strupr(char *x);
+int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args);
+int _wcsicmp (const wchar_t* cs, const wchar_t* ct);
+wchar_t * _wcslwr (wchar_t *x);
+int _wcsnicmp (const wchar_t * cs,const wchar_t * ct,size_t count);
+wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill);
+wchar_t * _wcsrev(wchar_t *s);
+wchar_t *_wcsupr(wchar_t *x);
+
+int atoi(const char *str);
+long atol(const char *str);
+int isdigit(int c);
+int islower(int c);
+int isprint(int c);
+int isspace(int c);
+int isupper(int c);
+int isxdigit(int c);
+size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count);
+int mbtowc (wchar_t *wchar, const char *mbchar, size_t count);
+void * memchr(const void *s, int c, size_t n);
+void * memcpy(void *to, const void *from, size_t count);
+void * memmove(void *dest,const void *src, size_t count);
+void * memset(void *src, int val, size_t count);
+
+#if 0
+qsort
+#endif
+
+int rand(void);
+int sprintf(char * buf, const char *fmt, ...);
+void srand(unsigned seed);
+char * strcat(char *s, const char *append);
+char * strchr(const char *s, int c);
+int strcmp(const char *s1, const char *s2);
+char * strcpy(char *to, const char *from);
+size_t strlen(const char *str);
+char * strncat(char *dst, const char *src, size_t n);
+int strncmp(const char *s1, const char *s2, size_t n);
+char *strncpy(char *dst, const char *src, size_t n);
+char *strrchr(const char *s, int c);
+size_t strspn(const char *s1, const char *s2);
+char *strstr(const char *s, const char *find);
+int swprintf(wchar_t *buf, const wchar_t *fmt, ...);
+int tolower(int c);
+int toupper(int c);
+wchar_t towlower(wchar_t c);
+wchar_t towupper(wchar_t c);
+int vsprintf(char *buf, const char *fmt, va_list args);
+wchar_t * wcscat(wchar_t *dest, const wchar_t *src);
+wchar_t * wcschr(const wchar_t *str, wchar_t ch);
+int wcscmp(const wchar_t *cs, const wchar_t *ct);
+wchar_t* wcscpy(wchar_t* str1, const wchar_t* str2);
+size_t wcscspn(const wchar_t *str,const wchar_t *reject);
+size_t wcslen(const wchar_t *s);
+wchar_t * wcsncat(wchar_t *dest, const wchar_t *src, size_t count);
+int wcsncmp(const wchar_t *cs, const wchar_t *ct, size_t count);
+wchar_t * wcsncpy(wchar_t *dest, const wchar_t *src, size_t count);
+wchar_t * wcsrchr(const wchar_t *str, wchar_t ch);
+size_t wcsspn(const wchar_t *str,const wchar_t *accept);
+wchar_t *wcsstr(const wchar_t *s,const wchar_t *b);
+size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count);
+int wctomb (char *mbchar, wchar_t wchar);
+
+#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */
+
+#endif /* __DDK_RTL_H */
diff --git a/include/ntos/rtltypes.h b/include/ntos/rtltypes.h
new file mode 100755 (executable)
index 0000000..7532839
--- /dev/null
@@ -0,0 +1,223 @@
+/* $Id$
+ * 
+ */
+
+#ifndef __DDK_RTLTYPES_H
+#define __DDK_RTLTYPES_H
+
+#ifndef __USE_W32API
+
+#define COMPRESSION_FORMAT_NONE                0x0000
+#define COMPRESSION_FORMAT_DEFAULT     0x0001
+#define COMPRESSION_FORMAT_LZNT1       0x0002
+
+#define COMPRESSION_ENGINE_STANDARD    0x0000
+#define COMPRESSION_ENGINE_MAXIMUM     0x0100
+#define COMPRESSION_ENGINE_HIBER       0x0200
+
+typedef struct _CONTROLLER_OBJECT
+{
+  CSHORT Type;
+  CSHORT Size;
+  PVOID ControllerExtension;
+  KDEVICE_QUEUE DeviceWaitQueue;
+  ULONG Spare1;
+  LARGE_INTEGER Spare2;
+} CONTROLLER_OBJECT, *PCONTROLLER_OBJECT;
+
+typedef struct _STRING
+{
+  /*
+   * Length in bytes of the string stored in buffer
+   */
+  USHORT Length;
+
+  /*
+   * Maximum length of the string 
+   */
+  USHORT MaximumLength;
+
+  /*
+   * String
+   */
+  PCHAR Buffer;
+} STRING, *PSTRING;
+
+typedef STRING ANSI_STRING;
+typedef PSTRING PANSI_STRING;
+
+typedef STRING OEM_STRING;
+typedef PSTRING POEM_STRING;
+
+typedef struct _TIME_FIELDS
+{
+  CSHORT Year;
+  CSHORT Month;
+  CSHORT Day;
+  CSHORT Hour;
+  CSHORT Minute;
+  CSHORT Second;
+  CSHORT Milliseconds;
+  CSHORT Weekday;
+} TIME_FIELDS, *PTIME_FIELDS;
+
+typedef struct _RTL_BITMAP
+{
+  ULONG  SizeOfBitMap;
+  PULONG Buffer;
+} RTL_BITMAP, *PRTL_BITMAP;
+
+
+#ifdef __GNUC__
+#define STDCALL_FUNC STDCALL
+#else
+#define STDCALL_FUNC(a) (__stdcall a )
+#endif /*__GNUC__*/
+
+
+typedef NTSTATUS STDCALL_FUNC
+(*PRTL_QUERY_REGISTRY_ROUTINE) (PWSTR ValueName,
+                              ULONG ValueType,
+                              PVOID ValueData,
+                              ULONG ValueLength,
+                              PVOID Context,
+                              PVOID EntryContext);
+
+typedef struct _RTL_QUERY_REGISTRY_TABLE
+{
+  PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
+  ULONG Flags;
+  PWSTR Name;
+  PVOID EntryContext;
+  ULONG DefaultType;
+  PVOID DefaultData;
+  ULONG DefaultLength;
+} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
+
+typedef struct _COMPRESSED_DATA_INFO
+{
+  USHORT CompressionFormatAndEngine;
+  UCHAR CompressionUnitShift;
+  UCHAR ChunkShift;
+  UCHAR ClusterShift;
+  UCHAR Reserved;
+  USHORT NumberOfChunks;
+  ULONG CompressedChunkSizes[1];
+} COMPRESSED_DATA_INFO, *PCOMPRESSED_DATA_INFO;
+
+typedef struct _GENERATE_NAME_CONTEXT
+{
+  USHORT Checksum;
+  BOOLEAN CheckSumInserted;
+  UCHAR NameLength;
+  WCHAR NameBuffer[8];
+  ULONG ExtensionLength;
+  WCHAR ExtensionBuffer[4];
+  ULONG LastIndexValue;
+} GENERATE_NAME_CONTEXT, *PGENERATE_NAME_CONTEXT;
+
+typedef struct _RTL_SPLAY_LINKS
+{
+  struct _RTL_SPLAY_LINKS *Parent;
+  struct _RTL_SPLAY_LINKS *LeftChild;
+  struct _RTL_SPLAY_LINKS *RightChild;
+} RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS;
+
+#else /* __USE_W32API */
+
+#include <ddk/ntifs.h>
+
+#endif /* __USE_W32API */
+
+typedef struct _INITIAL_TEB
+{
+  ULONG StackCommit;
+  ULONG StackReserve;
+  PVOID StackBase;
+  PVOID StackLimit;
+  PVOID StackAllocate;
+} INITIAL_TEB, *PINITIAL_TEB;
+
+typedef struct _RTL_HEAP_DEFINITION
+{
+  ULONG Length;
+  ULONG Unknown[11];
+} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
+
+typedef struct _RTL_ATOM_TABLE
+{
+  ULONG TableSize;
+  ULONG NumberOfAtoms;
+  PVOID Lock;          /* fast mutex (kernel mode)/ critical section (user mode) */
+  PVOID HandleTable;
+  LIST_ENTRY Slot[0];
+} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;
+
+typedef struct _LB_RANGE
+{
+  UCHAR upper;
+  UCHAR lower;
+} LB_RANGE;
+
+typedef struct _RTL_NLS_DATA
+{
+  USHORT   CodePage;
+  USHORT   MaxCharacterSize;  // SBCS = 1, DBCS = 2
+  WCHAR    DefaultCharacter;
+  WCHAR    char1;
+  WCHAR    char2;
+  WCHAR    char3;
+  USHORT   DbcsFlag;
+  LB_RANGE LeadByteRange[6];
+  USHORT   reserved;
+  PWCHAR   MultiByteToUnicode;
+  PCHAR    UnicodeToMultiByte;
+  PWCHAR   DosMultiByteToUnicode;
+  PCHAR    DbcsTags;
+} RTL_NLS_DATA, *PRTL_NLS_DATA;
+
+typedef struct _RTL_NLS_TABLE
+{
+  RTL_NLS_DATA OemInfo;
+  RTL_NLS_DATA AnsiInfo;
+  PWCHAR UpcaseTable;
+  PWCHAR DowncaseTable;
+} RTL_NLS_TABLE, *PRTL_NLS_TABLE;
+
+
+typedef struct _RTL_GENERIC_TABLE
+{
+  PVOID RootElement;
+  ULONG Unknown2;
+  ULONG Unknown3;
+  ULONG Unknown4;
+  ULONG Unknown5;
+  ULONG ElementCount;
+  PVOID CompareRoutine;
+  PVOID AllocateRoutine;
+  PVOID FreeRoutine;
+  ULONG UserParameter;
+} RTL_GENERIC_TABLE, *PRTL_GENERIC_TABLE;
+
+
+typedef struct _RTL_MESSAGE_RESOURCE_ENTRY
+{
+  USHORT Length;
+  USHORT Flags;
+  UCHAR Text[1];
+} RTL_MESSAGE_RESOURCE_ENTRY, *PRTL_MESSAGE_RESOURCE_ENTRY;
+
+typedef struct _RTL_MESSAGE_RESOURCE_BLOCK
+{
+  ULONG LowId;
+  ULONG HighId;
+  ULONG OffsetToEntries;
+} RTL_MESSAGE_RESOURCE_BLOCK, *PRTL_MESSAGE_RESOURCE_BLOCK;
+
+typedef struct _RTL_MESSAGE_RESOURCE_DATA
+{
+  ULONG NumberOfBlocks;
+  RTL_MESSAGE_RESOURCE_BLOCK Blocks[1];
+} RTL_MESSAGE_RESOURCE_DATA, *PRTL_MESSAGE_RESOURCE_DATA;
+
+#endif /* __DDK_RTLTYPES_H */
diff --git a/include/ntos/zw.h b/include/ntos/zw.h
new file mode 100755 (executable)
index 0000000..0799a2b
--- /dev/null
@@ -0,0 +1,5420 @@
+
+/* $Id$
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          System call definitions
+ * FILE:             include/ddk/zw.h
+ * REVISION HISTORY: 
+ *              ??/??/??: First few functions (David Welch)
+ *              ??/??/??: Complete implementation by Ariadne
+ *              13/07/98: Reorganised things a bit (David Welch)
+ *              04/08/98: Added some documentation (Ariadne)
+ *             14/08/98: Added type TIME and change variable type from [1] to [0]
+ *              14/09/98: Added for each Nt call a corresponding Zw Call
+ */
+
+#ifndef __DDK_ZW_H
+#define __DDK_ZW_H
+
+#include <ntos/security.h>
+#include <ntos/zwtypes.h>
+#include <napi/npipe.h>
+
+#ifndef _RTLGETPROCESSHEAP_DEFINED_
+#define _RTLGETPROCESSHEAP_DEFINED_
+#define RtlGetProcessHeap() (NtCurrentPeb()->ProcessHeap)
+#endif
+
+// semaphore information
+
+typedef enum _SEMAPHORE_INFORMATION_CLASS
+{
+       SemaphoreBasicInformation               = 0
+} SEMAPHORE_INFORMATION_CLASS;
+
+typedef struct _SEMAPHORE_BASIC_INFORMATION
+{
+       LONG CurrentCount;
+       LONG MaximumCount;
+} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION;
+
+// event information
+
+typedef enum _EVENT_INFORMATION_CLASS
+{
+       EventBasicInformation                   = 0
+} EVENT_INFORMATION_CLASS;
+
+typedef struct _EVENT_BASIC_INFORMATION
+{
+       EVENT_TYPE EventType;
+       LONG EventState;
+} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
+
+//#define LCID ULONG
+//#define SECURITY_INFORMATION ULONG
+//typedef ULONG SECURITY_INFORMATION;
+
+/*
+ * FUNCTION: Adjusts the groups in an access token
+ * ARGUMENTS: 
+ *       TokenHandle = Specifies the access token
+ *       ResetToDefault = If true the NewState parameter is ignored and the groups are set to
+ *                     their default state, if false the groups specified in
+ *                     NewState are set.
+ *       NewState = 
+ *       BufferLength = Specifies the size of the buffer for the PreviousState.
+ *       PreviousState = 
+ *       ReturnLength = Bytes written in PreviousState buffer.
+ * REMARKS: The arguments map to the win32 AdjustTokenGroups
+ * RETURNS: Status
+ */
+
+NTSTATUS 
+STDCALL 
+NtAdjustGroupsToken(
+       IN HANDLE TokenHandle,
+       IN BOOLEAN  ResetToDefault,
+       IN PTOKEN_GROUPS  NewState,
+       IN ULONG  BufferLength,
+       OUT PTOKEN_GROUPS  PreviousState OPTIONAL,
+       OUT PULONG  ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwAdjustGroupsToken(
+       IN HANDLE TokenHandle,
+       IN BOOLEAN  ResetToDefault,
+       IN PTOKEN_GROUPS  NewState,
+       IN ULONG  BufferLength,
+       OUT PTOKEN_GROUPS  PreviousState,
+       OUT PULONG  ReturnLength
+       );
+
+
+/*
+ * FUNCTION:
+ *
+ * ARGUMENTS:
+ *        TokenHandle = Handle to the access token
+ *        DisableAllPrivileges =  The resulting suspend count.
+         NewState = 
+         BufferLength =
+         PreviousState =
+         ReturnLength =
+ * REMARK:
+ *       The arguments map to the win32 AdjustTokenPrivileges
+ * RETURNS: Status
+ */
+
+NTSTATUS 
+STDCALL 
+NtAdjustPrivilegesToken(
+       IN HANDLE  TokenHandle,
+       IN BOOLEAN  DisableAllPrivileges,
+       IN PTOKEN_PRIVILEGES  NewState,
+       IN ULONG  BufferLength,
+       OUT PTOKEN_PRIVILEGES  PreviousState,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS 
+STDCALL 
+ZwAdjustPrivilegesToken(
+       IN HANDLE  TokenHandle,
+       IN BOOLEAN  DisableAllPrivileges,
+       IN PTOKEN_PRIVILEGES  NewState,
+       IN ULONG  BufferLength,
+       OUT PTOKEN_PRIVILEGES  PreviousState,
+       OUT PULONG ReturnLength
+       );
+
+
+/*
+ * FUNCTION: Decrements a thread's suspend count and places it in an alerted 
+ *           state.
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread that should be resumed
+ *        SuspendCount =  The resulting suspend count.
+ * REMARK:
+ *       A thread is resumed if its suspend count is 0
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAlertResumeThread(
+       IN HANDLE ThreadHandle,
+       OUT PULONG SuspendCount
+       );
+
+NTSTATUS
+STDCALL
+ZwAlertResumeThread(
+       IN HANDLE ThreadHandle,
+       OUT PULONG SuspendCount
+       );
+
+/*
+ * FUNCTION: Puts the thread in a alerted state
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread that should be alerted
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAlertThread(
+       IN HANDLE ThreadHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwAlertThread(
+       IN HANDLE ThreadHandle
+       );
+
+
+/*
+ * FUNCTION: Allocates a locally unique id
+ * ARGUMENTS: 
+ *        LocallyUniqueId = Locally unique number
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAllocateLocallyUniqueId(
+       OUT LUID *LocallyUniqueId
+       );
+
+NTSTATUS
+STDCALL
+ZwAllocateLocallyUniqueId(
+       OUT PLUID Luid
+       );
+
+/*
+ * FUNCTION: Allocates a block of virtual memory in the process address space
+ * ARGUMENTS:
+ *      ProcessHandle = The handle of the process which owns the virtual memory
+ *      BaseAddress   = A pointer to the virtual memory allocated. If you supply a non zero
+ *                     value the system will try to allocate the memory at the address supplied. It rounds
+ *                     it down to a multiple if the page size.
+ *      ZeroBits  = (OPTIONAL) You can specify the number of high order bits that must be zero, ensuring that 
+ *                     the memory will be allocated at a address below a certain value.
+ *      RegionSize = The number of bytes to allocate
+ *      AllocationType = Indicates the type of virtual memory you like to allocated,
+ *                       can be one of the values : MEM_COMMIT, MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN
+ *      Protect = Indicates the protection type of the pages allocated, can be a combination of
+ *                      PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ,
+ *                      PAGE_EXECUTE_READWRITE, PAGE_GUARD, PAGE_NOACCESS, PAGE_NOACCESS
+ * REMARKS:
+ *       This function maps to the win32 VirtualAllocEx. Virtual memory is process based so the 
+ *       protocol starts with a ProcessHandle. I splitted the functionality of obtaining the actual address and specifying
+ *       the start address in two parameters ( BaseAddress and StartAddress ) The NumberOfBytesAllocated specify the range
+ *       and the AllocationType and ProctectionType map to the other two parameters.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAllocateVirtualMemory (
+       IN HANDLE ProcessHandle,
+       IN OUT PVOID *BaseAddress,
+       IN ULONG  ZeroBits,
+       IN OUT PULONG  RegionSize,
+       IN ULONG  AllocationType,
+       IN ULONG  Protect
+       );
+
+NTSTATUS
+STDCALL
+ZwAllocateVirtualMemory (
+       IN HANDLE ProcessHandle,
+       IN OUT PVOID *BaseAddress,
+       IN ULONG  ZeroBits,
+       IN OUT PULONG  RegionSize,
+       IN ULONG  AllocationType,
+       IN ULONG  Protect);
+
+/*
+ * FUNCTION: Returns from a callback into user mode
+ * ARGUMENTS:
+ * RETURN Status
+ */
+//FIXME: this function might need 3 parameters
+NTSTATUS STDCALL NtCallbackReturn(PVOID Result,
+                                 ULONG ResultLength,
+                                 NTSTATUS Status);
+
+NTSTATUS STDCALL ZwCallbackReturn(PVOID Result,
+                                 ULONG ResultLength,
+                                 NTSTATUS Status);
+
+/*
+ * FUNCTION: Cancels a IO request
+ * ARGUMENTS: 
+ *        FileHandle = Handle to the file
+ *        IoStatusBlock  = 
+ *
+ * REMARKS:
+ *        This function maps to the win32 CancelIo.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCancelIoFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock
+       );
+
+NTSTATUS
+STDCALL
+ZwCancelIoFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock
+       );
+
+/*
+ * FUNCTION: Sets the status of the event back to non-signaled
+ * ARGUMENTS: 
+ *        EventHandle = Handle to the event
+ * REMARKS:
+ *       This function maps to win32 function ResetEvent.
+ * RETURcNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtClearEvent(
+       IN HANDLE  EventHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwClearEvent(
+       IN HANDLE  EventHandle
+       );
+
+/*
+ * FUNCTION: Closes an object handle
+ * ARGUMENTS:
+ *         Handle = Handle to the object
+ * REMARKS:
+ *       This function maps to the win32 function CloseHandle. 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtClose(
+       IN HANDLE Handle
+       );
+
+NTSTATUS
+STDCALL
+ZwClose(
+       IN HANDLE Handle
+       );
+
+/*
+ * FUNCTION: Generates an audit message when a handle to an object is dereferenced
+ * ARGUMENTS:
+ *         SubsystemName   = 
+          HandleId        = Handle to the object
+          GenerateOnClose =
+ * REMARKS:
+ *       This function maps to the win32 function ObjectCloseAuditAlarm. 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCloseObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PVOID HandleId,
+       IN BOOLEAN GenerateOnClose
+       );
+
+NTSTATUS
+STDCALL
+ZwCloseObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PVOID HandleId,
+       IN BOOLEAN GenerateOnClose
+       );
+
+/*
+ * FUNCTION: Creates a directory object
+ * ARGUMENTS:
+ *        DirectoryHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies access to the directory
+ *        ObjectAttribute = Initialized attributes for the object
+ * REMARKS: This function maps to the win32 CreateDirectory. A directory is like a file so it needs a
+ *          handle, a access mask and a OBJECT_ATTRIBUTES structure to map the path name and the SECURITY_ATTRIBUTES.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateDirectoryObject(
+       OUT PHANDLE DirectoryHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateDirectoryObject(
+       OUT PHANDLE DirectoryHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Creates an event object
+ * ARGUMENTS:
+ *        EventHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies access to the event
+ *        ObjectAttribute = Initialized attributes for the object
+ *        ManualReset = manual-reset or auto-reset if true you have to reset the state of the event manually
+ *                       using NtResetEvent/NtClearEvent. if false the system will reset the event to a non-signalled state
+ *                       automatically after the system has rescheduled a thread waiting on the event.
+ *        InitialState = specifies the initial state of the event to be signaled ( TRUE ) or non-signalled (FALSE).
+ * REMARKS: This function maps to the win32 CreateEvent. Demanding a out variable  of type HANDLE,
+ *          a access mask and a OBJECT_ATTRIBUTES structure mapping to the SECURITY_ATTRIBUTES. ManualReset and InitialState are
+ *          both parameters aswell ( possibly the order is reversed ).
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateEvent(
+       OUT PHANDLE EventHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN BOOLEAN ManualReset,
+       IN BOOLEAN InitialState
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateEvent(
+       OUT PHANDLE EventHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN BOOLEAN ManualReset,
+       IN BOOLEAN InitialState
+       );
+
+/*
+ * FUNCTION: Creates an eventpair object
+ * ARGUMENTS:
+ *        EventPairHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies access to the event
+ *        ObjectAttribute = Initialized attributes for the object
+ */
+
+NTSTATUS
+STDCALL
+NtCreateEventPair(
+       OUT PHANDLE EventPairHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateEventPair(
+       OUT PHANDLE EventPairHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+
+/*
+ * FUNCTION: Creates or opens a file, directory or device object.
+ * ARGUMENTS:
+ *        FileHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the file can
+ *                        be a combination of DELETE | FILE_READ_DATA ..  
+ *        ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ *        IoStatusBlock (OUT) = Caller supplied storage for the resulting status information, indicating if the
+ *                              the file is created and opened or allready existed and is just opened.
+ *        FileAttributes = file attributes can be a combination of FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN ...
+ *        ShareAccess = can be a combination of the following: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE 
+ *        CreateDisposition = specifies what the behavior of the system if the file allready exists.
+ *        CreateOptions = specifies the behavior of the system on file creation.
+ *        EaBuffer (OPTIONAL) = Extended Attributes buffer, applies only to files and directories.
+ *        EaLength = Extended Attributes buffer size,  applies only to files and directories.
+ * REMARKS: This function maps to the win32 CreateFile. 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateFile(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PLARGE_INTEGER AllocationSize OPTIONAL,
+       IN ULONG FileAttributes,
+       IN ULONG ShareAccess,
+       IN ULONG CreateDisposition,
+       IN ULONG CreateOptions,
+       IN PVOID EaBuffer OPTIONAL,
+       IN ULONG EaLength
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateFile(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PLARGE_INTEGER AllocationSize OPTIONAL,
+       IN ULONG FileAttributes,
+       IN ULONG ShareAccess,
+       IN ULONG CreateDisposition,
+       IN ULONG CreateOptions,
+       IN PVOID EaBuffer OPTIONAL,
+       IN ULONG EaLength
+       );
+
+/*
+ * FUNCTION: Creates or opens a file, directory or device object.
+ * ARGUMENTS:
+ *        CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the port
+ *        IoStatusBlock =
+ *        NumberOfConcurrentThreads =
+ * REMARKS: This function maps to the win32 CreateIoCompletionPort
+ * RETURNS:
+ *     Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateIoCompletion(
+       OUT PHANDLE CompletionPort,
+       IN ACCESS_MASK DesiredAccess,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG NumberOfConcurrentThreads
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateIoCompletion(
+       OUT PHANDLE CompletionPort,
+       IN ACCESS_MASK DesiredAccess,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG NumberOfConcurrentThreads
+       );
+
+
+/*
+ * FUNCTION: Creates a registry key
+ * ARGUMENTS:
+ *        KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the key
+ *          It can have a combination of the following values:
+ *          KEY_READ | KEY_WRITE | KEY_EXECUTE | KEY_ALL_ACCESS
+ *          or
+ *          KEY_QUERY_VALUE The values of the key can be queried.
+ *          KEY_SET_VALUE The values of the key can be modified.
+ *          KEY_CREATE_SUB_KEYS The key may contain subkeys.
+ *          KEY_ENUMERATE_SUB_KEYS Subkeys can be queried.
+ *          KEY_NOTIFY
+ *          KEY_CREATE_LINK A symbolic link to the key can be created. 
+ *        ObjectAttributes = The name of the key may be specified directly in the name field 
+ *          of object attributes or relative to a key in rootdirectory.
+ *        TitleIndex = Might specify the position in the sequential order of subkeys. 
+ *        Class = Specifies the kind of data, for example REG_SZ for string data. [ ??? ]
+ *        CreateOptions = Specifies additional options with which the key is created
+ *          REG_OPTION_VOLATILE  The key is not preserved across boots.
+ *          REG_OPTION_NON_VOLATILE  The key is preserved accross boots.
+ *          REG_OPTION_CREATE_LINK  The key is a symbolic link to another key. 
+ *          REG_OPTION_BACKUP_RESTORE  Key is being opened or created for backup/restore operations. 
+ *        Disposition = Indicates if the call to NtCreateKey resulted in the creation of a key it 
+ *          can have the following values: REG_CREATED_NEW_KEY | REG_OPENED_EXISTING_KEY
+ * RETURNS:
+ *  Status
+ */
+
+NTSTATUS STDCALL
+NtCreateKey(OUT PHANDLE KeyHandle,
+            IN ACCESS_MASK DesiredAccess,
+            IN POBJECT_ATTRIBUTES ObjectAttributes,
+            IN ULONG TitleIndex,
+            IN PUNICODE_STRING Class OPTIONAL,
+            IN ULONG CreateOptions,
+            IN PULONG Disposition OPTIONAL);
+
+NTSTATUS STDCALL
+ZwCreateKey(OUT PHANDLE KeyHandle,
+            IN ACCESS_MASK DesiredAccess,
+            IN POBJECT_ATTRIBUTES ObjectAttributes,
+            IN ULONG TitleIndex,
+            IN PUNICODE_STRING Class OPTIONAL,
+            IN ULONG CreateOptions,
+            IN PULONG Disposition OPTIONAL);
+
+/*
+ * FUNCTION: Creates a mail slot file
+ * ARGUMENTS:
+ *        MailSlotFileHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the file
+ *        ObjectAttributes = Contains the name of the mailslotfile.
+ *        IoStatusBlock = 
+ *        FileAttributes =
+ *        ShareAccess =
+ *        MaxMessageSize =
+ *        TimeOut =
+ *       
+ * REMARKS: This funciton maps to the win32 function CreateMailSlot
+ * RETURNS:
+ *     Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateMailslotFile(
+       OUT PHANDLE MailSlotFileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG FileAttributes,
+       IN ULONG ShareAccess,
+       IN ULONG MaxMessageSize,
+       IN PLARGE_INTEGER TimeOut
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateMailslotFile(
+       OUT PHANDLE MailSlotFileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG FileAttributes,
+       IN ULONG ShareAccess,
+       IN ULONG MaxMessageSize,
+       IN PLARGE_INTEGER TimeOut
+       );
+
+/*
+ * FUNCTION: Creates or opens a mutex
+ * ARGUMENTS:
+ *        MutantHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the port
+ *        ObjectAttributes = Contains the name of the mutex.
+ *        InitialOwner = If true the calling thread acquires ownership 
+ *                     of the mutex.
+ * REMARKS: This funciton maps to the win32 function CreateMutex
+ * RETURNS:
+ *     Status
+ */
+NTSTATUS
+STDCALL
+NtCreateMutant(
+       OUT PHANDLE MutantHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN BOOLEAN InitialOwner
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateMutant(
+       OUT PHANDLE MutantHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN BOOLEAN InitialOwner
+       );
+
+/*
+ * FUNCTION: Creates a process.
+ * ARGUMENTS:
+ *        ProcessHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the process can
+ *                        be a combinate of STANDARD_RIGHTS_REQUIRED| ..  
+ *        ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ *        ParentProcess = Handle to the parent process.
+ *        InheritObjectTable = Specifies to inherit the objects of the parent process if true.
+ *        SectionHandle = Handle to a section object to back the image file
+ *        DebugPort = Handle to a DebugPort if NULL the system default debug port will be used.
+ *        ExceptionPort = Handle to a exception port.
+ * REMARKS:
+ *        This function maps to the win32 CreateProcess.
+ * RETURNS: Status
+ */
+NTSTATUS 
+STDCALL 
+NtCreateProcess(
+       OUT PHANDLE ProcessHandle,
+        IN ACCESS_MASK DesiredAccess,
+        IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+        IN HANDLE ParentProcess,
+        IN BOOLEAN InheritObjectTable,
+        IN HANDLE SectionHandle OPTIONAL,
+        IN HANDLE DebugPort OPTIONAL,
+        IN HANDLE ExceptionPort OPTIONAL
+       );
+
+NTSTATUS 
+STDCALL 
+ZwCreateProcess(
+       OUT PHANDLE ProcessHandle,
+        IN ACCESS_MASK DesiredAccess,
+        IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+        IN HANDLE ParentProcess,
+        IN BOOLEAN InheritObjectTable,
+        IN HANDLE SectionHandle OPTIONAL,
+        IN HANDLE DebugPort OPTIONAL,
+        IN HANDLE ExceptionPort OPTIONAL
+       );
+
+/*
+ * FUNCTION: Creates a section object.
+ * ARGUMENTS:
+ *        SectionHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the desired access to the section can be a combination of STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE |  
+ *                        SECTION_MAP_READ | SECTION_MAP_EXECUTE.
+ *        ObjectAttribute = Initialized attributes for the object can be used to create a named section
+ *        MaxiumSize = Maximizes the size of the memory section. Must be non-NULL for a page-file backed section. 
+ *                     If value specified for a mapped file and the file is not large enough, file will be extended. 
+ *        SectionPageProtection = Can be a combination of PAGE_READONLY | PAGE_READWRITE | PAGE_WRITEONLY | PAGE_WRITECOPY.
+ *        AllocationAttributes = can be a combination of SEC_IMAGE | SEC_RESERVE
+ *        FileHanlde = Handle to a file to create a section mapped to a file instead of a memory backed section.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateSection( 
+       OUT PHANDLE SectionHandle, 
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,  
+       IN PLARGE_INTEGER MaximumSize OPTIONAL,  
+       IN ULONG SectionPageProtection OPTIONAL,
+       IN ULONG AllocationAttributes,
+       IN HANDLE FileHandle OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateSection( 
+       OUT PHANDLE SectionHandle, 
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,  
+       IN PLARGE_INTEGER MaximumSize OPTIONAL,  
+       IN ULONG SectionPageProtection OPTIONAL,
+       IN ULONG AllocationAttributes,
+       IN HANDLE FileHandle OPTIONAL
+       );
+
+/*
+ * FUNCTION: Creates a semaphore object for interprocess synchronization.
+ * ARGUMENTS:
+ *        SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the semaphore. 
+ *        ObjectAttribute = Initialized attributes for the object.
+ *        InitialCount = Not necessary zero, might be smaller than zero.
+ *        MaximumCount = Maxiumum count the semaphore can reach.
+ * RETURNS: Status
+ * REMARKS: 
+ *        The semaphore is set to signaled when its count is greater than zero, and non-signaled when its count is zero.
+ */
+
+//FIXME: should a semaphore's initial count allowed to be smaller than zero ??
+NTSTATUS
+STDCALL
+NtCreateSemaphore(
+       OUT PHANDLE SemaphoreHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+       IN LONG InitialCount,
+       IN LONG MaximumCount
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateSemaphore(
+       OUT PHANDLE SemaphoreHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+       IN LONG InitialCount,
+       IN LONG MaximumCount
+       );
+
+/*
+ * FUNCTION: Creates a symbolic link object
+ * ARGUMENTS:
+ *        SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the thread. 
+ *        ObjectAttributes = Initialized attributes for the object.
+ *        Name = Target name of the symbolic link  
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateSymbolicLinkObject(
+       OUT PHANDLE SymbolicLinkHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PUNICODE_STRING Name
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateSymbolicLinkObject(
+       OUT PHANDLE SymbolicLinkHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PUNICODE_STRING Name
+       );
+
+/*
+ * FUNCTION: Creates a waitable timer.
+ * ARGUMENTS:
+ *        TimerHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the timer. 
+ *        ObjectAttributes = Initialized attributes for the object.
+ *        TimerType = Specifies if the timer should be reset manually.
+ * REMARKS:
+ *       This function maps to the win32  CreateWaitableTimer. lpTimerAttributes and lpTimerName map to
+ *       corresponding fields in OBJECT_ATTRIBUTES structure. 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateTimer(
+       OUT PHANDLE TimerHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+       IN TIMER_TYPE TimerType
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateTimer(
+       OUT PHANDLE TimerHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+       IN TIMER_TYPE TimerType
+       );
+
+/*
+ * FUNCTION: Creates a token.
+ * ARGUMENTS:
+ *        TokenHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the process can
+ *                        be a combinate of STANDARD_RIGHTS_REQUIRED| ..  
+ *        ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ *        TokenType = 
+ *        AuthenticationId = 
+ *        ExpirationTime = 
+ *        TokenUser = 
+ *        TokenGroups =
+ *        TokenPrivileges = 
+ *        TokenOwner = 
+ *        TokenPrimaryGroup = 
+ *        TokenDefaultDacl =
+ *        TokenSource =
+ * REMARKS:
+ *        This function does not map to a win32 function
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateToken(
+       OUT PHANDLE TokenHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN TOKEN_TYPE TokenType,
+       IN PLUID AuthenticationId,
+       IN PLARGE_INTEGER ExpirationTime,
+       IN PTOKEN_USER TokenUser,
+       IN PTOKEN_GROUPS TokenGroups,
+       IN PTOKEN_PRIVILEGES TokenPrivileges,
+       IN PTOKEN_OWNER TokenOwner,
+       IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
+       IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
+       IN PTOKEN_SOURCE TokenSource
+       );
+
+NTSTATUS
+STDCALL
+ZwCreateToken(
+       OUT PHANDLE TokenHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN TOKEN_TYPE TokenType,
+       IN PLUID AuthenticationId,
+       IN PLARGE_INTEGER ExpirationTime,
+       IN PTOKEN_USER TokenUser,
+       IN PTOKEN_GROUPS TokenGroups,
+       IN PTOKEN_PRIVILEGES TokenPrivileges,
+       IN PTOKEN_OWNER TokenOwner,
+       IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
+       IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
+       IN PTOKEN_SOURCE TokenSource
+       );
+
+/*
+ * FUNCTION: Returns the callers thread TEB.
+ * RETURNS: The resulting teb.
+ */
+#if 0
+ NT_TEB *
+STDCALL 
+NtCurrentTeb(VOID
+       );
+#endif
+
+/*
+ * FUNCTION: Deletes an atom from the global atom table
+ * ARGUMENTS:
+ *        Atom = Identifies the atom to delete
+ * REMARKS:
+ *      The function maps to the win32 GlobalDeleteAtom
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteAtom(
+       IN RTL_ATOM Atom
+       );
+
+NTSTATUS
+STDCALL
+ZwDeleteAtom(
+       IN RTL_ATOM Atom
+       );
+
+/*
+ * FUNCTION: Deletes a file or a directory
+ * ARGUMENTS:
+ *        ObjectAttributes = Name of the file which should be deleted
+ * REMARKS:
+ *      This system call is functionally equivalent to NtSetInformationFile
+ *      setting the disposition information.
+ *      The function maps to the win32 DeleteFile. 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteFile(
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwDeleteFile(
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Deletes a registry key
+ * ARGUMENTS:
+ *         KeyHandle = Handle of the key
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteKey(
+       IN HANDLE KeyHandle
+       );
+NTSTATUS
+STDCALL
+ZwDeleteKey(
+       IN HANDLE KeyHandle
+       );
+
+/*
+ * FUNCTION: Generates a audit message when an object is deleted
+ * ARGUMENTS:
+ *         SubsystemName = Spefies the name of the subsystem can be 'WIN32' or 'DEBUG'
+ *         HandleId= Handle to an audit object
+ *        GenerateOnClose = Value returned by NtAccessCheckAndAuditAlarm
+ * REMARKS: This function maps to the win32 ObjectCloseAuditAlarm
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDeleteObjectAuditAlarm ( 
+       IN PUNICODE_STRING SubsystemName, 
+       IN PVOID HandleId, 
+       IN BOOLEAN GenerateOnClose 
+       );
+
+NTSTATUS
+STDCALL
+ZwDeleteObjectAuditAlarm ( 
+       IN PUNICODE_STRING SubsystemName, 
+       IN PVOID HandleId, 
+       IN BOOLEAN GenerateOnClose 
+       );  
+
+
+/*
+ * FUNCTION: Deletes a value from a registry key
+ * ARGUMENTS:
+ *         KeyHandle = Handle of the key
+ *         ValueName = Name of the value to delete
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDeleteValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName
+       );
+
+NTSTATUS
+STDCALL
+ZwDeleteValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName
+       );
+/*
+ * FUNCTION: Sends IOCTL to the io sub system
+ * ARGUMENTS:
+ *        DeviceHandle = Points to the handle that is created by NtCreateFile
+ *        Event = Event to synchronize on STATUS_PENDING
+ *        ApcRoutine = Asynchroneous procedure callback
+ *       ApcContext = Callback context.
+ *       IoStatusBlock = Caller should supply storage for extra information.. 
+ *        IoControlCode = Contains the IO Control command. This is an 
+ *                     index to the structures in InputBuffer and OutputBuffer.
+ *       InputBuffer = Caller should supply storage for input buffer if IOTL expects one.
+ *       InputBufferSize = Size of the input bufffer
+ *        OutputBuffer = Caller should supply storage for output buffer if IOTL expects one.
+ *        OutputBufferSize  = Size of the input bufffer
+ * RETURNS: Status 
+ */
+
+NTSTATUS
+STDCALL
+NtDeviceIoControlFile(
+       IN HANDLE DeviceHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 
+       IN PVOID UserApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock, 
+       IN ULONG IoControlCode,
+       IN PVOID InputBuffer, 
+       IN ULONG InputBufferSize,
+       OUT PVOID OutputBuffer,
+       IN ULONG OutputBufferSize
+       );
+
+NTSTATUS
+STDCALL
+ZwDeviceIoControlFile(
+       IN HANDLE DeviceHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 
+       IN PVOID UserApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock, 
+       IN ULONG IoControlCode,
+       IN PVOID InputBuffer, 
+       IN ULONG InputBufferSize,
+       OUT PVOID OutputBuffer,
+       IN ULONG OutputBufferSize
+       );
+/*
+ * FUNCTION: Displays a string on the blue screen
+ * ARGUMENTS:
+ *         DisplayString = The string to display
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDisplayString(
+       IN PUNICODE_STRING DisplayString
+       );
+
+NTSTATUS
+STDCALL
+ZwDisplayString(
+       IN PUNICODE_STRING DisplayString
+       );
+
+/*
+ * FUNCTION: Returns information about the subkeys of an open key
+ * ARGUMENTS:
+ *         KeyHandle = Handle of the key whose subkeys are to enumerated
+ *         Index = zero based index of the subkey for which information is
+ *                 request
+ *         KeyInformationClass = Type of information returned
+ *         KeyInformation (OUT) = Caller allocated buffer for the information
+ *                                about the key
+ *         Length = Length in bytes of the KeyInformation buffer
+ *         ResultLength (OUT) = Caller allocated storage which holds
+ *                              the number of bytes of information retrieved
+ *                              on return
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtEnumerateKey(
+       IN HANDLE KeyHandle,
+       IN ULONG Index,
+       IN KEY_INFORMATION_CLASS KeyInformationClass,
+       OUT PVOID KeyInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwEnumerateKey(
+       IN HANDLE KeyHandle,
+       IN ULONG Index,
+       IN KEY_INFORMATION_CLASS KeyInformationClass,
+       OUT PVOID KeyInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+/*
+ * FUNCTION: Returns information about the value entries of an open key
+ * ARGUMENTS:
+ *         KeyHandle = Handle of the key whose value entries are to enumerated
+ *         Index = zero based index of the subkey for which information is
+ *                 request
+ *         KeyInformationClass = Type of information returned
+ *         KeyInformation (OUT) = Caller allocated buffer for the information
+ *                                about the key
+ *         Length = Length in bytes of the KeyInformation buffer
+ *         ResultLength (OUT) = Caller allocated storage which holds
+ *                              the number of bytes of information retrieved
+ *                              on return
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtEnumerateValueKey(
+       IN HANDLE KeyHandle,
+       IN ULONG Index,
+       IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+       OUT PVOID KeyValueInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwEnumerateValueKey(
+       IN HANDLE KeyHandle,
+       IN ULONG Index,
+       IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+       OUT PVOID KeyValueInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+/*
+ * FUNCTION: Flushes chached file data to disk
+ * ARGUMENTS:
+ *       FileHandle = Points to the file
+ *      IoStatusBlock = Caller must supply storage to receive the result of the flush
+ *             buffers operation. The information field is set to number of bytes
+ *             flushed to disk.
+ * RETURNS: Status 
+ * REMARKS:
+ *     This funciton maps to the win32 FlushFileBuffers
+ */
+NTSTATUS
+STDCALL
+NtFlushBuffersFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock
+       );
+
+NTSTATUS
+STDCALL
+ZwFlushBuffersFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock
+       );
+
+/*
+ * FUNCTION: Flushes a registry key to disk
+ * ARGUMENTS:
+ *       KeyHandle = Points to the registry key handle
+ * RETURNS: Status 
+ * REMARKS:
+ *     This funciton maps to the win32 RegFlushKey.
+ */
+NTSTATUS
+STDCALL
+NtFlushKey(
+       IN HANDLE KeyHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwFlushKey(
+       IN HANDLE KeyHandle
+       );
+/*
+ * FUNCTION: Flushes the dirty pages to file
+ * RETURNS: Status
+ * FIXME: Not sure this does (how is the file specified)
+ */
+NTSTATUS STDCALL NtFlushWriteBuffer(VOID);
+NTSTATUS STDCALL ZwFlushWriteBuffer(VOID);                      
+
+ /*
+ * FUNCTION: Frees a range of virtual memory
+ * ARGUMENTS:
+ *        ProcessHandle = Points to the process that allocated the virtual 
+ *                        memory
+ *        BaseAddress = Points to the memory address, rounded down to a 
+ *                      multiple of the pagesize
+ *        RegionSize = Limits the range to free, rounded up to a multiple of 
+ *                     the paging size
+ *        FreeType = Can be one of the values:  MEM_DECOMMIT, or MEM_RELEASE
+ * RETURNS: Status 
+ */
+NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle,
+                                    IN PVOID  *BaseAddress,    
+                                    IN PULONG  RegionSize,     
+                                    IN ULONG  FreeType);
+NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle,
+                                    IN PVOID  *BaseAddress,    
+                                    IN PULONG  RegionSize,     
+                                    IN ULONG  FreeType);  
+
+/*
+ * FUNCTION: Sends FSCTL to the filesystem
+ * ARGUMENTS:
+ *        DeviceHandle = Points to the handle that is created by NtCreateFile
+ *        Event = Event to synchronize on STATUS_PENDING
+ *        ApcRoutine = 
+ *       ApcContext =
+ *       IoStatusBlock = Caller should supply storage for 
+ *        IoControlCode = Contains the File System Control command. This is an 
+ *                     index to the structures in InputBuffer and OutputBuffer.
+ *             FSCTL_GET_RETRIEVAL_POINTERS    MAPPING_PAIR
+ *             FSCTL_GET_RETRIEVAL_POINTERS    GET_RETRIEVAL_DESCRIPTOR
+ *             FSCTL_GET_VOLUME_BITMAP         BITMAP_DESCRIPTOR
+ *             FSCTL_MOVE_FILE                 MOVEFILE_DESCRIPTOR
+ *
+ *       InputBuffer = Caller should supply storage for input buffer if FCTL expects one.
+ *       InputBufferSize = Size of the input bufffer
+ *        OutputBuffer = Caller should supply storage for output buffer if FCTL expects one.
+ *        OutputBufferSize  = Size of the input bufffer
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+ *             STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST ]
+ */
+NTSTATUS
+STDCALL
+NtFsControlFile(
+       IN HANDLE DeviceHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock, 
+       IN ULONG IoControlCode,
+       IN PVOID InputBuffer, 
+       IN ULONG InputBufferSize,
+       OUT PVOID OutputBuffer,
+       IN ULONG OutputBufferSize
+       );
+
+NTSTATUS
+STDCALL
+ZwFsControlFile(
+       IN HANDLE DeviceHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock, 
+       IN ULONG IoControlCode,
+       IN PVOID InputBuffer, 
+       IN ULONG InputBufferSize,
+       OUT PVOID OutputBuffer,
+       IN ULONG OutputBufferSize
+       );
+
+/*
+ * FUNCTION: Retrieves the processor context of a thread
+ * ARGUMENTS:
+ *        ThreadHandle = Handle to a thread
+ *        Context (OUT) = Caller allocated storage for the processor context
+ * RETURNS: Status 
+ */
+
+NTSTATUS
+STDCALL 
+NtGetContextThread(
+       IN HANDLE ThreadHandle, 
+       OUT PCONTEXT Context
+       );
+
+NTSTATUS
+STDCALL 
+ZwGetContextThread(
+       IN HANDLE ThreadHandle, 
+       OUT PCONTEXT Context
+       );
+
+/*
+ * FUNCTION: Sets a thread to impersonate another 
+ * ARGUMENTS:
+ *        ThreadHandle = Server thread that will impersonate a client.
+         ThreadToImpersonate = Client thread that will be impersonated
+         SecurityQualityOfService = Specifies the impersonation level.
+ * RETURNS: Status 
+ */
+
+NTSTATUS
+STDCALL 
+NtImpersonateThread(
+       IN HANDLE ThreadHandle,
+       IN HANDLE ThreadToImpersonate,
+       IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
+       );
+
+NTSTATUS
+STDCALL 
+ZwImpersonateThread(
+       IN HANDLE ThreadHandle,
+       IN HANDLE ThreadToImpersonate,
+       IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
+       );
+
+/*
+ * FUNCTION: Initializes the registry.
+ * ARGUMENTS:
+ *        SetUpBoot = This parameter is true for a setup boot.
+ * RETURNS: Status 
+ */
+NTSTATUS
+STDCALL 
+NtInitializeRegistry(
+       BOOLEAN SetUpBoot
+       );
+NTSTATUS
+STDCALL 
+ZwInitializeRegistry(
+       BOOLEAN SetUpBoot
+       );
+
+/*
+ * FUNCTION: Loads a driver. 
+ * ARGUMENTS: 
+ *      DriverServiceName = Name of the driver to load
+ * RETURNS: Status
+ */    
+NTSTATUS
+STDCALL 
+NtLoadDriver(
+       IN PUNICODE_STRING DriverServiceName
+       );
+
+NTSTATUS
+STDCALL 
+ZwLoadDriver(
+       IN PUNICODE_STRING DriverServiceName
+       );
+
+/*
+ * FUNCTION: Locks a range of bytes in a file. 
+ * ARGUMENTS: 
+ *       FileHandle = Handle to the file
+ *       Event = Should be null if apc is specified.
+ *       ApcRoutine = Asynchroneous Procedure Callback
+ *       ApcContext = Argument to the callback
+ *       IoStatusBlock (OUT) = Caller should supply storage for a structure containing
+ *                      the completion status and information about the requested lock operation.
+ *       ByteOffset = Offset 
+ *       Length = Number of bytes to lock.
+ *       Key  = Special value to give other threads the possibility to unlock the file
+               by supplying the key in a call to NtUnlockFile.
+ *       FailImmediatedly = If false the request will block untill the lock is obtained. 
+ *       ExclusiveLock = Specifies whether a exclusive or a shared lock is obtained.
+ * REMARK:
+       This procedure maps to the win32 procedure LockFileEx. STATUS_PENDING is returned if the lock could
+       not be obtained immediately, the device queue is busy and the IRP is queued.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+               STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_LOCK_NOT_GRANTED ]
+
+ */    
+NTSTATUS 
+STDCALL
+NtLockFile(
+       IN  HANDLE FileHandle,
+       IN  HANDLE Event OPTIONAL,
+       IN  PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN  PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN  PLARGE_INTEGER ByteOffset,
+       IN  PLARGE_INTEGER Length,
+       IN  PULONG Key,
+       IN  BOOLEAN FailImmediatedly,
+       IN  BOOLEAN ExclusiveLock
+       );
+
+NTSTATUS 
+STDCALL
+ZwLockFile(
+       IN  HANDLE FileHandle,
+       IN  HANDLE Event OPTIONAL,
+       IN  PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN  PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN  PLARGE_INTEGER ByteOffset,
+       IN  PLARGE_INTEGER Length,
+       IN  PULONG Key,
+       IN  BOOLEAN FailImmediatedly,
+       IN  BOOLEAN ExclusiveLock
+       );
+
+/*
+ * FUNCTION: Makes temporary object that will be removed at next boot.
+ * ARGUMENTS: 
+ *       Handle = Handle to object
+ * RETURNS: Status
+ */    
+
+NTSTATUS
+STDCALL
+NtMakeTemporaryObject(
+       IN HANDLE Handle 
+       );
+
+NTSTATUS
+STDCALL
+ZwMakeTemporaryObject(
+       IN HANDLE Handle 
+       );
+/*
+ * FUNCTION: Maps a view of a section into the virtual address space of a 
+ *           process
+ * ARGUMENTS:
+ *        SectionHandle = Handle of the section
+ *        ProcessHandle = Handle of the process
+ *        BaseAddress = Desired base address (or NULL) on entry
+ *                      Actual base address of the view on exit
+ *        ZeroBits = Number of high order address bits that must be zero
+ *        CommitSize = Size in bytes of the initially committed section of 
+ *                     the view 
+ *        SectionOffset = Offset in bytes from the beginning of the section
+ *                        to the beginning of the view
+ *        ViewSize = Desired length of map (or zero to map all) on entry
+ *                   Actual length mapped on exit
+ *        InheritDisposition = Specified how the view is to be shared with
+ *                            child processes
+ *        AllocateType = Type of allocation for the pages
+ *        Protect = Protection for the committed region of the view
+ * RETURNS: Status
+ */
+NTSTATUS 
+STDCALL
+NtMapViewOfSection(
+       IN HANDLE SectionHandle,
+       IN HANDLE ProcessHandle,
+       IN OUT PVOID *BaseAddress,
+       IN ULONG ZeroBits,
+       IN ULONG CommitSize,
+       IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+       IN OUT PULONG ViewSize,
+       IN SECTION_INHERIT InheritDisposition,
+       IN ULONG AllocationType,
+       IN ULONG AccessProtection
+       );
+
+NTSTATUS
+STDCALL
+ZwMapViewOfSection(
+       IN HANDLE SectionHandle,
+       IN HANDLE ProcessHandle,
+       IN OUT PVOID *BaseAddress,
+       IN ULONG ZeroBits,
+       IN ULONG CommitSize,
+       IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+       IN OUT PULONG ViewSize,
+       IN SECTION_INHERIT InheritDisposition,
+       IN ULONG AllocationType,
+       IN ULONG AccessProtection
+       );
+
+/*
+ * FUNCTION: Installs a notify for the change of a directory's contents
+ * ARGUMENTS:
+ *        FileHandle = Handle to the directory
+         Event = 
+ *        ApcRoutine   = Start address
+ *        ApcContext = Delimits the range of virtual memory
+ *                             for which the new access protection holds
+ *        IoStatusBlock = The new access proctection for the pages
+ *        Buffer = Caller supplies storage for resulting information --> FILE_NOTIFY_INFORMATION
+ *       BufferSize =  Size of the buffer
+         CompletionFilter = Can be one of the following values:
+                       FILE_NOTIFY_CHANGE_FILE_NAME
+                       FILE_NOTIFY_CHANGE_DIR_NAME
+                       FILE_NOTIFY_CHANGE_NAME ( FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME ) 
+                       FILE_NOTIFY_CHANGE_ATTRIBUTES
+                       FILE_NOTIFY_CHANGE_SIZE
+                       FILE_NOTIFY_CHANGE_LAST_WRITE
+                       FILE_NOTIFY_CHANGE_LAST_ACCESS
+                       FILE_NOTIFY_CHANGE_CREATION ( change of creation timestamp )
+                       FILE_NOTIFY_CHANGE_EA
+                       FILE_NOTIFY_CHANGE_SECURITY
+                       FILE_NOTIFY_CHANGE_STREAM_NAME
+                       FILE_NOTIFY_CHANGE_STREAM_SIZE
+                       FILE_NOTIFY_CHANGE_STREAM_WRITE
+         WatchTree = If true the notify will be installed recursively on the targetdirectory and all subdirectories.
+ *
+ * REMARKS:
+ *      The function maps to the win32 FindFirstChangeNotification, FindNextChangeNotification 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtNotifyChangeDirectoryFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG BufferSize,
+       IN ULONG CompletionFilter,
+       IN BOOLEAN WatchTree
+       );
+
+NTSTATUS
+STDCALL
+ZwNotifyChangeDirectoryFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG BufferSize,
+       IN ULONG CompletionFilter,
+       IN BOOLEAN WatchTree
+       );
+
+/*
+ * FUNCTION: Installs a notfication callback on registry changes
+ * ARGUMENTS:
+       KeyHandle = Handle to the registry key
+       Event = Event that should be signalled on modification of the key
+       ApcRoutine = Routine that should be called on modification of the key
+       ApcContext = Argument to the ApcRoutine
+       IoStatusBlock = ???
+       CompletionFilter = Specifies the kind of notification the caller likes to receive.
+                       Can be a combination of the following values:
+
+                       REG_NOTIFY_CHANGE_NAME
+                       REG_NOTIFY_CHANGE_ATTRIBUTES
+                       REG_NOTIFY_CHANGE_LAST_SET
+                       REG_NOTIFY_CHANGE_SECURITY
+                               
+                               
+       Asynchroneous = If TRUE the changes are reported by signalling an event if false
+                       the function will not return before a change occurs.
+       ChangeBuffer =  Will return the old value
+       Length = Size of the change buffer
+       WatchSubtree =  Indicates if the caller likes to receive a notification of changes in
+                       sub keys or not.
+ * REMARKS: If the key is closed the event is signalled aswell.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtNotifyChangeKey(
+       IN HANDLE KeyHandle,
+       IN HANDLE Event,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG CompletionFilter,
+       IN BOOLEAN Asynchroneous, 
+       OUT PVOID ChangeBuffer,
+       IN ULONG Length,
+       IN BOOLEAN WatchSubtree
+       );
+
+NTSTATUS
+STDCALL
+ZwNotifyChangeKey(
+       IN HANDLE KeyHandle,
+       IN HANDLE Event,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG CompletionFilter,
+       IN BOOLEAN Asynchroneous, 
+       OUT PVOID ChangeBuffer,
+       IN ULONG Length,
+       IN BOOLEAN WatchSubtree
+       );
+
+/*
+ * FUNCTION: Opens an existing directory object
+ * ARGUMENTS:
+ *        FileHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the directory
+ *        ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenDirectoryObject(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenDirectoryObject(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Opens an existing event
+ * ARGUMENTS:
+ *        EventHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the event
+ *        ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenEvent(
+       OUT PHANDLE EventHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenEvent(
+       OUT PHANDLE EventHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Opens an existing event pair
+ * ARGUMENTS:
+ *        EventHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the event
+ *        ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenEventPair(
+       OUT PHANDLE EventPairHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenEventPair(
+       OUT PHANDLE EventPairHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+/*
+ * FUNCTION: Opens an existing file
+ * ARGUMENTS:
+ *        FileHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the file
+ *        ObjectAttributes = Initialized attributes for the object
+ *        IoStatusBlock =
+ *        ShareAccess =
+ *        OpenOptions =
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenFile(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG ShareAccess,
+       IN ULONG OpenOptions
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenFile(
+       OUT PHANDLE FileHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG ShareAccess,
+       IN ULONG OpenOptions
+       );
+
+/*
+ * FUNCTION: Opens an existing io completion object
+ * ARGUMENTS:
+ *        CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the io completion object
+ *        ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenIoCompletion(
+       OUT PHANDLE CompetionPort,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenIoCompletion(
+       OUT PHANDLE CompetionPort,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+       
+/*
+ * FUNCTION: Opens an existing key in the registry
+ * ARGUMENTS:
+ *        KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the key
+ *        ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenKey(
+       OUT PHANDLE KeyHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenKey(
+       OUT PHANDLE KeyHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+/*
+ * FUNCTION: Opens an existing key in the registry
+ * ARGUMENTS:
+ *        MutantHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the mutant
+ *        ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenMutant(
+       OUT PHANDLE MutantHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenMutant(
+       OUT PHANDLE MutantHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Opens an existing process
+ * ARGUMENTS:
+ *        ProcessHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the process
+ *        ObjectAttribute = Initialized attributes for the object
+ *        ClientId = Identifies the process id to open
+ * RETURNS: Status
+ */
+NTSTATUS 
+STDCALL
+NtOpenProcess (
+       OUT PHANDLE ProcessHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PCLIENT_ID ClientId
+       ); 
+NTSTATUS 
+STDCALL
+ZwOpenProcess (
+       OUT PHANDLE ProcessHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PCLIENT_ID ClientId
+       ); 
+/*
+ * FUNCTION: Opens an existing process
+ * ARGUMENTS:
+ *        ProcessHandle  = Handle of the process of which owns the token
+ *        DesiredAccess = Requested access to the token
+ *       TokenHandle (OUT) = Caller supplies storage for the resulting token.
+ * REMARKS:
+       This function maps to the win32 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenProcessToken(
+       IN HANDLE ProcessHandle,
+       IN ACCESS_MASK DesiredAccess,
+       OUT PHANDLE TokenHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenProcessToken(
+       IN HANDLE ProcessHandle,
+       IN ACCESS_MASK DesiredAccess,
+       OUT PHANDLE TokenHandle
+       );
+
+/*
+ * FUNCTION: Opens an existing section object
+ * ARGUMENTS:
+ *        KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the key
+ *        ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenSection(
+       OUT PHANDLE SectionHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenSection(
+       OUT PHANDLE SectionHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+/*
+ * FUNCTION: Opens an existing semaphore
+ * ARGUMENTS:
+ *        SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the semaphore
+ *        ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenSemaphore(
+       IN HANDLE SemaphoreHandle,
+       IN ACCESS_MASK DesiredAcces,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenSemaphore(
+       IN HANDLE SemaphoreHandle,
+       IN ACCESS_MASK DesiredAcces,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+/*
+ * FUNCTION: Opens an existing symbolic link
+ * ARGUMENTS:
+ *        SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the symbolic link
+ *        ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenSymbolicLinkObject(
+       OUT PHANDLE SymbolicLinkHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenSymbolicLinkObject(
+       OUT PHANDLE SymbolicLinkHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+/*
+ * FUNCTION: Opens an existing thread
+ * ARGUMENTS:
+ *        ThreadHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the thread
+ *        ObjectAttribute = Initialized attributes for the object
+ *       ClientId = Identifies the thread to open.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenThread(
+       OUT PHANDLE ThreadHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PCLIENT_ID ClientId
+       );
+NTSTATUS
+STDCALL
+ZwOpenThread(
+       OUT PHANDLE ThreadHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN PCLIENT_ID ClientId
+       );
+
+NTSTATUS
+STDCALL
+NtOpenThreadToken(
+       IN HANDLE ThreadHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN BOOLEAN OpenAsSelf,
+       OUT PHANDLE TokenHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenThreadToken(
+       IN HANDLE ThreadHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN BOOLEAN OpenAsSelf,
+       OUT PHANDLE TokenHandle
+       );
+/*
+ * FUNCTION: Opens an existing timer
+ * ARGUMENTS:
+ *        TimerHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Requested access to the timer
+ *        ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenTimer(
+       OUT PHANDLE TimerHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+NTSTATUS
+STDCALL
+ZwOpenTimer(
+       OUT PHANDLE TimerHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Checks an access token for specific privileges
+ * ARGUMENTS:
+ *        ClientToken = Handle to a access token structure
+ *        RequiredPrivileges = Specifies the requested privileges.
+ *        Result = Caller supplies storage for the result. If PRIVILEGE_SET_ALL_NECESSARY is
+                  set in the Control member of PRIVILEGES_SET Result
+                  will only be TRUE if all privileges are present in the access token. 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtPrivilegeCheck(
+       IN HANDLE ClientToken,
+       IN PPRIVILEGE_SET RequiredPrivileges,
+       IN PBOOLEAN Result
+       );
+
+NTSTATUS
+STDCALL
+ZwPrivilegeCheck(
+       IN HANDLE ClientToken,
+       IN PPRIVILEGE_SET RequiredPrivileges,
+       IN PBOOLEAN Result
+       );
+
+NTSTATUS
+STDCALL
+NtPrivilegedServiceAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PUNICODE_STRING ServiceName,
+       IN HANDLE ClientToken,
+       IN PPRIVILEGE_SET Privileges,
+       IN BOOLEAN AccessGranted
+       );
+
+NTSTATUS
+STDCALL
+ZwPrivilegedServiceAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,       
+       IN PUNICODE_STRING ServiceName, 
+       IN HANDLE ClientToken,
+       IN PPRIVILEGE_SET Privileges,   
+       IN BOOLEAN AccessGranted        
+       );      
+
+NTSTATUS
+STDCALL
+NtPrivilegeObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PVOID HandleId,
+       IN HANDLE ClientToken,
+       IN ULONG DesiredAccess,
+       IN PPRIVILEGE_SET Privileges,
+       IN BOOLEAN AccessGranted
+       );
+
+NTSTATUS
+STDCALL
+ZwPrivilegeObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PVOID HandleId,
+       IN HANDLE ClientToken,
+       IN ULONG DesiredAccess,
+       IN PPRIVILEGE_SET Privileges,
+       IN BOOLEAN AccessGranted
+       );
+
+/*
+ * FUNCTION: Entry point for native applications
+ * ARGUMENTS:
+ *     Peb = Pointes to the Process Environment Block (PEB)
+ * REMARKS:
+ *     Native applications should use this function instead of a main.
+ *     Calling proces should terminate itself.
+ * RETURNS: Status
+ */    
+VOID STDCALL
+NtProcessStartup(
+       IN      PPEB    Peb
+       );
+
+
+/*
+ * FUNCTION: Signals an event and resets it afterwards.
+ * ARGUMENTS:
+ *        EventHandle  = Handle to the event
+ *        PulseCount = Number of times the action is repeated
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtPulseEvent(
+       IN HANDLE EventHandle,
+       IN PULONG PulseCount OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwPulseEvent(
+       IN HANDLE EventHandle,
+       IN PULONG PulseCount OPTIONAL
+       );
+
+/*
+ * FUNCTION: Queries the attributes of a file
+ * ARGUMENTS:
+ *        ObjectAttributes = Initialized attributes for the object
+ *        Buffer = Caller supplies storage for the attributes
+ * RETURNS: Status
+ */
+
+NTSTATUS STDCALL
+NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                     OUT PFILE_BASIC_INFORMATION FileInformation);
+
+NTSTATUS STDCALL
+ZwQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                     OUT PFILE_BASIC_INFORMATION FileInformation);
+
+/*
+ * FUNCTION: Queries the default locale id
+ * ARGUMENTS:
+ *        UserProfile = Type of locale id
+ *              TRUE: thread locale id
+ *              FALSE: system locale id
+ *        DefaultLocaleId = Caller supplies storage for the locale id
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtQueryDefaultLocale(
+       IN BOOLEAN UserProfile,
+       OUT PLCID DefaultLocaleId
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryDefaultLocale(
+       IN BOOLEAN UserProfile,
+       OUT PLCID DefaultLocaleId
+       );
+
+/*
+ * FUNCTION: Queries a directory file.
+ * ARGUMENTS:
+ *       FileHandle = Handle to a directory file
+ *        EventHandle  = Handle to the event signaled on completion
+ *       ApcRoutine = Asynchroneous procedure callback, called on completion
+ *       ApcContext = Argument to the apc.
+ *       IoStatusBlock = Caller supplies storage for extended status information.
+ *       FileInformation = Caller supplies storage for the resulting information.
+ *
+ *             FileNameInformation             FILE_NAMES_INFORMATION
+ *             FileDirectoryInformation        FILE_DIRECTORY_INFORMATION
+ *             FileFullDirectoryInformation    FILE_FULL_DIRECTORY_INFORMATION
+ *             FileBothDirectoryInformation    FILE_BOTH_DIR_INFORMATION
+ *
+ *       Length = Size of the storage supplied
+ *       FileInformationClass = Indicates the type of information requested.  
+ *       ReturnSingleEntry = Specify true if caller only requests the first directory found.
+ *       FileName = Initial directory name to query, that may contain wild cards.
+ *        RestartScan = Number of times the action should be repeated
+ * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
+ *                  STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
+ *                  STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
+ */
+
+NTSTATUS
+STDCALL
+NtQueryDirectoryFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID FileInformation,
+       IN ULONG Length,
+       IN FILE_INFORMATION_CLASS FileInformationClass,
+       IN BOOLEAN ReturnSingleEntry,
+       IN PUNICODE_STRING FileName OPTIONAL,
+       IN BOOLEAN RestartScan
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryDirectoryFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID FileInformation,
+       IN ULONG Length,
+       IN FILE_INFORMATION_CLASS FileInformationClass,
+       IN BOOLEAN ReturnSingleEntry,
+       IN PUNICODE_STRING FileName OPTIONAL,
+       IN BOOLEAN RestartScan
+       );
+
+/*
+ * FUNCTION: Queries the extended attributes of a file
+ * ARGUMENTS:
+ *        FileHandle  = Handle to the event
+ *        IoStatusBlock = Number of times the action is repeated
+ *        Buffer
+ *        Length
+ *        ReturnSingleEntry
+ *        EaList
+ *        EaListLength
+ *        EaIndex
+ *        RestartScan
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtQueryEaFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG Length,
+       IN BOOLEAN ReturnSingleEntry,
+       IN PVOID EaList OPTIONAL,
+       IN ULONG EaListLength,
+       IN PULONG EaIndex OPTIONAL,
+       IN BOOLEAN RestartScan
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryEaFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG Length,
+       IN BOOLEAN ReturnSingleEntry,
+       IN PVOID EaList OPTIONAL,
+       IN ULONG EaListLength,
+       IN PULONG EaIndex OPTIONAL,
+       IN BOOLEAN RestartScan
+       );
+
+/*
+ * FUNCTION: Queries an event
+ * ARGUMENTS:
+ *        EventHandle  = Handle to the event
+ *        EventInformationClass = Index of the information structure
+       
+         EventBasicInformation         EVENT_BASIC_INFORMATION
+
+ *       EventInformation = Caller supplies storage for the information structure
+ *       EventInformationLength =  Size of the information structure
+ *       ReturnLength = Data written
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryEvent(
+       IN HANDLE EventHandle,
+       IN EVENT_INFORMATION_CLASS EventInformationClass,
+       OUT PVOID EventInformation,
+       IN ULONG EventInformationLength,
+       OUT PULONG ReturnLength
+       );
+NTSTATUS
+STDCALL
+ZwQueryEvent(
+       IN HANDLE EventHandle,
+       IN EVENT_INFORMATION_CLASS EventInformationClass,
+       OUT PVOID EventInformation,
+       IN ULONG EventInformationLength,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS STDCALL
+NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                         OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation);
+
+NTSTATUS STDCALL
+ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                         OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation);
+
+/*
+ * FUNCTION: Queries the information of a file object.
+ * ARGUMENTS: 
+ *        FileHandle = Handle to the file object
+ *       IoStatusBlock = Caller supplies storage for extended information 
+ *                        on the current operation.
+ *        FileInformation = Storage for the new file information
+ *        Lenght = Size of the storage for the file information.
+ *        FileInformationClass = Indicates which file information is queried
+
+         FileDirectoryInformation              FILE_DIRECTORY_INFORMATION
+         FileFullDirectoryInformation          FILE_FULL_DIRECTORY_INFORMATION
+         FileBothDirectoryInformation          FILE_BOTH_DIRECTORY_INFORMATION
+         FileBasicInformation                  FILE_BASIC_INFORMATION
+         FileStandardInformation               FILE_STANDARD_INFORMATION
+         FileInternalInformation               FILE_INTERNAL_INFORMATION
+         FileEaInformation                     FILE_EA_INFORMATION
+         FileAccessInformation                 FILE_ACCESS_INFORMATION
+         FileNameInformation                   FILE_NAME_INFORMATION
+         FileRenameInformation                 FILE_RENAME_INFORMATION
+         FileLinkInformation                   
+         FileNamesInformation                  FILE_NAMES_INFORMATION
+         FileDispositionInformation            FILE_DISPOSITION_INFORMATION
+         FilePositionInformation               FILE_POSITION_INFORMATION
+         FileFullEaInformation                 FILE_FULL_EA_INFORMATION                
+         FileModeInformation                   FILE_MODE_INFORMATION
+         FileAlignmentInformation              FILE_ALIGNMENT_INFORMATION
+         FileAllInformation                    FILE_ALL_INFORMATION
+
+         FileEndOfFileInformation              FILE_END_OF_FILE_INFORMATION
+         FileAlternateNameInformation          
+         FileStreamInformation                 FILE_STREAM_INFORMATION
+         FilePipeInformation                   
+         FilePipeLocalInformation              
+         FilePipeRemoteInformation             
+         FileMailslotQueryInformation          
+         FileMailslotSetInformation            
+         FileCompressionInformation            FILE_COMPRESSION_INFORMATION            
+         FileCopyOnWriteInformation            
+         FileCompletionInformation             IO_COMPLETION_CONTEXT
+         FileMoveClusterInformation            
+         FileOleClassIdInformation             
+         FileOleStateBitsInformation           
+         FileNetworkOpenInformation            FILE_NETWORK_OPEN_INFORMATION
+         FileObjectIdInformation               
+         FileOleAllInformation                 
+         FileOleDirectoryInformation           
+         FileContentIndexInformation           
+         FileInheritContentIndexInformation    
+         FileOleInformation                    
+         FileMaximumInformation                        
+
+ * REMARK:
+ *       This procedure maps to the win32 GetShortPathName, GetLongPathName,
+          GetFullPathName, GetFileType, GetFileSize, GetFileTime  functions. 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryInformationFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID FileInformation,
+       IN ULONG Length,
+       IN FILE_INFORMATION_CLASS FileInformationClass
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationFile(
+       HANDLE FileHandle,
+       PIO_STATUS_BLOCK IoStatusBlock,
+       PVOID FileInformation,
+       ULONG Length,
+       FILE_INFORMATION_CLASS FileInformationClass
+       );
+
+
+/*
+ * FUNCTION: Queries the information of a thread object.
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread object
+ *        ThreadInformationClass = Index to a certain information structure
+
+               ThreadBasicInformation                  THREAD_BASIC_INFORMATION        
+               ThreadTimes                             KERNEL_USER_TIMES
+               ThreadPriority                          KPRIORITY       
+               ThreadBasePriority                      KPRIORITY       
+               ThreadAffinityMask                      KAFFINITY       
+               ThreadImpersonationToken                
+               ThreadDescriptorTableEntry              
+               ThreadEnableAlignmentFaultFixup         
+               ThreadEventPair                         
+               ThreadQuerySetWin32StartAddress         
+               ThreadZeroTlsCell                       
+               ThreadPerformanceCount                  
+               ThreadAmILastThread                     BOOLEAN
+               ThreadIdealProcessor                    ULONG
+               ThreadPriorityBoost                     ULONG   
+               MaxThreadInfoClass                      
+               
+
+ *        ThreadInformation = Caller supplies torage for the thread information
+ *       ThreadInformationLength = Size of the thread information structure
+ *        ReturnLength  = Actual number of bytes written
+               
+ * REMARK:
+ *       This procedure maps to the win32 GetThreadTimes, GetThreadPriority,
+          GetThreadPriorityBoost   functions. 
+ * RETURNS: Status
+*/
+
+
+NTSTATUS
+STDCALL
+NtQueryInformationThread(
+       IN HANDLE ThreadHandle,
+       IN THREADINFOCLASS ThreadInformationClass,
+       OUT PVOID ThreadInformation,
+       IN ULONG ThreadInformationLength,
+       OUT PULONG ReturnLength 
+       );
+
+
+NTSTATUS
+STDCALL
+NtQueryInformationToken(
+       IN HANDLE TokenHandle,
+       IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+       OUT PVOID TokenInformation,
+       IN ULONG TokenInformationLength,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationToken(
+       IN HANDLE TokenHandle,
+       IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+       OUT PVOID TokenInformation,
+       IN ULONG TokenInformationLength,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+NtQueryIoCompletion(
+       IN HANDLE CompletionPort,
+       IN ULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PULONG NumberOfBytesTransferred
+       );
+NTSTATUS
+STDCALL
+ZwQueryIoCompletion(
+       IN HANDLE CompletionPort,
+       IN ULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PULONG NumberOfBytesTransferred
+       );
+
+
+/*
+ * FUNCTION: Queries the information of a registry key object.
+ * ARGUMENTS: 
+       KeyHandle = Handle to a registry key
+       KeyInformationClass = Index to a certain information structure
+       KeyInformation = Caller supplies storage for resulting information
+       Length = Size of the supplied storage 
+       ResultLength = Bytes written
+ */
+NTSTATUS
+STDCALL
+NtQueryKey(
+       IN HANDLE KeyHandle,
+       IN KEY_INFORMATION_CLASS KeyInformationClass,
+       OUT PVOID KeyInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryKey(
+       IN HANDLE KeyHandle,
+       IN KEY_INFORMATION_CLASS KeyInformationClass,
+       OUT PVOID KeyInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+
+// draft
+
+NTSTATUS
+STDCALL
+NtQueryMultipleValueKey(
+       IN HANDLE KeyHandle,
+       IN OUT PKEY_VALUE_ENTRY ValueList,
+       IN ULONG NumberOfValues,
+       OUT PVOID Buffer,
+       IN OUT PULONG Length,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryMultipleValueKey(
+       IN HANDLE KeyHandle,
+       IN OUT PKEY_VALUE_ENTRY ValueList,
+       IN ULONG NumberOfValues,
+       OUT PVOID Buffer,
+       IN OUT PULONG Length,
+       OUT PULONG ReturnLength
+       );
+
+/*
+ * FUNCTION: Queries the information of a mutant object.
+ * ARGUMENTS: 
+       MutantHandle = Handle to a mutant
+       MutantInformationClass = Index to a certain information structure
+       MutantInformation = Caller supplies storage for resulting information
+       Length = Size of the supplied storage 
+       ResultLength = Bytes written
+ */
+NTSTATUS
+STDCALL
+NtQueryMutant(
+       IN HANDLE MutantHandle,
+       IN CINT MutantInformationClass,
+       OUT PVOID MutantInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryMutant(
+       IN HANDLE MutantHandle,
+       IN CINT MutantInformationClass,
+       OUT PVOID MutantInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+/*
+ * FUNCTION: Queries the system ( high-resolution ) performance counter.
+ * ARGUMENTS: 
+ *        Counter = Performance counter
+ *       Frequency = Performance frequency
+ * REMARKS:
+       This procedure queries a tick count faster than 10ms ( The resolution for  Intel®-based CPUs is about 0.8 microseconds.)
+       This procedure maps to the win32 QueryPerformanceCounter, QueryPerformanceFrequency 
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryPerformanceCounter(
+       IN PLARGE_INTEGER Counter,
+       IN PLARGE_INTEGER Frequency
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryPerformanceCounter(
+       IN PLARGE_INTEGER Counter,
+       IN PLARGE_INTEGER Frequency
+       );
+
+/*
+ * FUNCTION: Queries the information of a semaphore.
+ * ARGUMENTS: 
+ *        SemaphoreHandle = Handle to the semaphore object
+ *        SemaphoreInformationClass = Index to a certain information structure
+
+         SemaphoreBasicInformation     SEMAPHORE_BASIC_INFORMATION
+
+ *       SemaphoreInformation = Caller supplies storage for the semaphore information structure
+ *       Length = Size of the infomation structure
+ */
+NTSTATUS
+STDCALL
+NtQuerySemaphore(
+       IN      HANDLE                          SemaphoreHandle,
+       IN      SEMAPHORE_INFORMATION_CLASS     SemaphoreInformationClass,
+       OUT     PVOID                           SemaphoreInformation,
+       IN      ULONG                           Length,
+       OUT     PULONG                          ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySemaphore(
+       IN      HANDLE                          SemaphoreHandle,
+       IN      SEMAPHORE_INFORMATION_CLASS     SemaphoreInformationClass,
+       OUT     PVOID                           SemaphoreInformation,
+       IN      ULONG                           Length,
+       OUT     PULONG                          ReturnLength
+       );
+
+
+/*
+ * FUNCTION: Queries the information of a symbolic link object.
+ * ARGUMENTS: 
+ *        SymbolicLinkHandle = Handle to the symbolic link object
+ *       LinkTarget = resolved name of link
+ *        DataWritten = size of the LinkName.
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySymbolicLinkObject(
+       IN HANDLE               SymLinkObjHandle,
+       OUT PUNICODE_STRING     LinkTarget,
+       OUT PULONG              DataWritten OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySymbolicLinkObject(
+       IN HANDLE               SymLinkObjHandle,
+       OUT PUNICODE_STRING     LinkName,
+       OUT PULONG              DataWritten OPTIONAL
+       ); 
+
+
+/*
+ * FUNCTION: Queries a system environment variable.
+ * ARGUMENTS: 
+ *        Name = Name of the variable
+ *       Value (OUT) = value of the variable
+ *        Length = size of the buffer
+ *        ReturnLength = data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySystemEnvironmentValue(
+       IN PUNICODE_STRING Name,
+       OUT PVOID Value,
+       ULONG Length,
+       PULONG ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemEnvironmentValue(
+       IN PUNICODE_STRING Name,
+       OUT PVOID Value,
+       ULONG Length,
+       PULONG ReturnLength
+       );
+
+
+/*
+ * FUNCTION: Queries the system information.
+ * ARGUMENTS: 
+ *        SystemInformationClass = Index to a certain information structure
+
+         SystemTimeAdjustmentInformation       SYSTEM_TIME_ADJUSTMENT
+         SystemCacheInformation                SYSTEM_CACHE_INFORMATION
+         SystemConfigurationInformation        CONFIGURATION_INFORMATION
+
+ *       SystemInformation = caller supplies storage for the information structure
+ *        Length = size of the structure
+         ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySystemInformation(
+       IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
+       OUT     PVOID                           SystemInformation,
+       IN      ULONG                           Length,
+       OUT     PULONG                          ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemInformation(
+       IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
+       OUT     PVOID                           SystemInformation,
+       IN      ULONG                           Length,
+       OUT     PULONG                          ResultLength
+       );
+
+/*
+ * FUNCTION: Queries information about a timer
+ * ARGUMENTS: 
+ *        TimerHandle  = Handle to the timer
+         TimerValueInformationClass = Index to a certain information structure
+         TimerValueInformation = Caller supplies storage for the information structure
+         Length = Size of the information structure
+         ResultLength = Data written
+ * RETURNS: Status
+ *
+*/       
+NTSTATUS
+STDCALL
+NtQueryTimer(
+       IN HANDLE TimerHandle,
+       IN CINT TimerInformationClass,
+       OUT PVOID TimerInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+NTSTATUS
+STDCALL
+ZwQueryTimer(
+       IN HANDLE TimerHandle,
+       IN CINT TimerInformationClass,
+       OUT PVOID TimerInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+/*
+ * FUNCTION: Queries the timer resolution
+ * ARGUMENTS: 
+ *        MinimumResolution (OUT) = Caller should supply storage for the resulting time.
+         Maximum Resolution (OUT) = Caller should supply storage for the resulting time.
+         ActualResolution (OUT) = Caller should supply storage for the resulting time.
+ * RETURNS: Status
+ *
+*/        
+
+
+NTSTATUS
+STDCALL 
+NtQueryTimerResolution ( 
+       OUT PULONG MinimumResolution,
+       OUT PULONG MaximumResolution, 
+       OUT PULONG ActualResolution 
+       ); 
+
+NTSTATUS
+STDCALL 
+ZwQueryTimerResolution ( 
+       OUT PULONG MinimumResolution,
+       OUT PULONG MaximumResolution, 
+       OUT PULONG ActualResolution 
+       ); 
+
+/*
+ * FUNCTION: Queries a registry key value
+ * ARGUMENTS: 
+ *        KeyHandle  = Handle to the registry key
+         ValueName = Name of the value in the registry key
+         KeyValueInformationClass = Index to a certain information structure
+
+               KeyValueBasicInformation = KEY_VALUE_BASIC_INFORMATION
+               KeyValueFullInformation = KEY_FULL_INFORMATION
+               KeyValuePartialInformation = KEY_VALUE_PARTIAL_INFORMATION
+
+         KeyValueInformation = Caller supplies storage for the information structure
+         Length = Size of the information structure
+         ResultLength = Data written
+ * RETURNS: Status
+ *
+*/       
+NTSTATUS
+STDCALL
+NtQueryValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName,
+       IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+       OUT PVOID KeyValueInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName,
+       IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+       OUT PVOID KeyValueInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+/*
+ * FUNCTION: Queries the volume information
+ * ARGUMENTS: 
+ *       FileHandle  = Handle to a file object on the target volume
+ *       IoStatusBlock = Caller should supply storage for additional status information
+ *       ReturnLength = DataWritten
+ *       FsInformation = Caller should supply storage for the information structure.
+ *       Length = Size of the information structure
+ *       FsInformationClass = Index to a information structure
+
+               FileFsVolumeInformation         FILE_FS_VOLUME_INFORMATION
+               FileFsLabelInformation          FILE_FS_LABEL_INFORMATION       
+               FileFsSizeInformation           FILE_FS_SIZE_INFORMATION
+               FileFsDeviceInformation         FILE_FS_DEVICE_INFORMATION
+               FileFsAttributeInformation      FILE_FS_ATTRIBUTE_INFORMATION
+               FileFsControlInformation        
+               FileFsQuotaQueryInformation     --
+               FileFsQuotaSetInformation       --
+               FileFsMaximumInformation        
+
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_INSUFFICIENT_RESOURCES | STATUS_INVALID_PARAMETER |
+                STATUS_INVALID_DEVICE_REQUEST | STATUS_BUFFER_OVERFLOW ]
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryVolumeInformationFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID FsInformation,
+       IN ULONG Length,
+       IN FS_INFORMATION_CLASS FsInformationClass 
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryVolumeInformationFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID FsInformation,
+       IN ULONG Length,
+       IN FS_INFORMATION_CLASS FsInformationClass
+       );
+// draft
+// FIXME: Should I specify if the apc is user or kernel mode somewhere ??
+/*
+ * FUNCTION: Queues a (user) apc to a thread.
+ * ARGUMENTS: 
+         ThreadHandle = Thread to which the apc is queued.
+         ApcRoutine = Points to the apc routine
+         NormalContext = Argument to Apc Routine
+ *        SystemArgument1 = Argument of the Apc Routine
+         SystemArgument2 = Argument of the Apc Routine
+ * REMARK: If the apc is queued against a thread of a different process than the calling thread
+               the apc routine should be specified in the address space of the queued thread's process.
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtQueueApcThread(
+       HANDLE ThreadHandle,
+       PKNORMAL_ROUTINE ApcRoutine,
+       PVOID NormalContext,
+       PVOID SystemArgument1,
+       PVOID SystemArgument2);
+
+NTSTATUS
+STDCALL
+ZwQueueApcThread(
+       HANDLE ThreadHandle,
+       PKNORMAL_ROUTINE ApcRoutine,
+       PVOID NormalContext,
+       PVOID SystemArgument1,
+       PVOID SystemArgument2);
+
+
+/*
+ * FUNCTION: Raises an exception
+ * ARGUMENTS:
+ *       ExceptionRecord = Structure specifying the exception
+ *       Context = Context in which the excpetion is raised 
+ *       IsDebugger = 
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtRaiseException(
+       IN PEXCEPTION_RECORD ExceptionRecord,
+       IN PCONTEXT Context,
+       IN BOOLEAN SearchFrames
+       );
+
+NTSTATUS
+STDCALL
+ZwRaiseException(
+       IN PEXCEPTION_RECORD ExceptionRecord,
+       IN PCONTEXT Context,
+       IN BOOLEAN SearchFrames
+       );
+
+/*
+ * FUNCTION: Read a file
+ * ARGUMENTS:
+ *       FileHandle = Handle of a file to read
+ *       Event = This event is signalled when the read operation completes
+ *       UserApcRoutine = Call back , if supplied Event should be NULL
+ *       UserApcContext = Argument to the callback
+ *       IoStatusBlock = Caller should supply storage for additional status information
+ *       Buffer = Caller should supply storage to receive the information
+ *       BufferLength = Size of the buffer
+ *       ByteOffset = Offset to start reading the file
+ *       Key = If a range is lock a matching key will allow the read to continue.
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS
+STDCALL
+NtReadFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+       IN PVOID UserApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG BufferLength,
+       IN PLARGE_INTEGER ByteOffset OPTIONAL,
+       IN PULONG Key OPTIONAL  
+       );
+
+NTSTATUS
+STDCALL
+ZwReadFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+       IN PVOID UserApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PVOID Buffer,
+       IN ULONG BufferLength,
+       IN PLARGE_INTEGER ByteOffset OPTIONAL,
+       IN PULONG Key OPTIONAL  
+       );
+/*
+ * FUNCTION: Read a file using scattered io
+ * ARGUMENTS: 
+         FileHandle = Handle of a file to read
+         Event = This event is signalled when the read operation completes
+ *        UserApcRoutine = Call back , if supplied Event should be NULL
+         UserApcContext = Argument to the callback
+         IoStatusBlock = Caller should supply storage for additional status information
+         BufferDescription = Caller should supply storage to receive the information
+         BufferLength = Size of the buffer
+         ByteOffset = Offset to start reading the file
+         Key =  Key = If a range is lock a matching key will allow the read to continue.
+ * RETURNS: Status
+ *
+*/       
+NTSTATUS
+STDCALL
+NtReadFileScatter( 
+       IN HANDLE FileHandle, 
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 
+       IN  PVOID UserApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK UserIoStatusBlock, 
+       IN FILE_SEGMENT_ELEMENT BufferDescription[], 
+       IN ULONG BufferLength, 
+       IN PLARGE_INTEGER ByteOffset, 
+       IN PULONG Key OPTIONAL  
+       ); 
+
+NTSTATUS
+STDCALL
+ZwReadFileScatter( 
+       IN HANDLE FileHandle, 
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 
+       IN  PVOID UserApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK UserIoStatusBlock, 
+       IN FILE_SEGMENT_ELEMENT BufferDescription[], 
+       IN ULONG BufferLength, 
+       IN PLARGE_INTEGER ByteOffset, 
+       IN PULONG Key OPTIONAL  
+       ); 
+/*
+ * FUNCTION: Copies a range of virtual memory to a buffer
+ * ARGUMENTS: 
+ *       ProcessHandle = Specifies the process owning the virtual address space
+ *       BaseAddress =  Points to the address of virtual memory to start the read
+ *       Buffer = Caller supplies storage to copy the virtual memory to.
+ *       NumberOfBytesToRead = Limits the range to read
+ *       NumberOfBytesRead = The actual number of bytes read.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtReadVirtualMemory( 
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       OUT PVOID Buffer,
+       IN ULONG  NumberOfBytesToRead,
+       OUT PULONG NumberOfBytesRead
+       ); 
+NTSTATUS
+STDCALL
+ZwReadVirtualMemory( 
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       OUT PVOID Buffer,
+       IN ULONG  NumberOfBytesToRead,
+       OUT PULONG NumberOfBytesRead
+       );      
+       
+
+/*
+ * FUNCTION: Debugger can register for thread termination
+ * ARGUMENTS: 
+ *       TerminationPort = Port on which the debugger likes to be notified.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL        
+NtRegisterThreadTerminatePort(
+       HANDLE TerminationPort
+       );
+NTSTATUS
+STDCALL        
+ZwRegisterThreadTerminatePort(
+       HANDLE TerminationPort
+       );
+
+/*
+ * FUNCTION: Releases a mutant
+ * ARGUMENTS: 
+ *       MutantHandle = Handle to the mutant
+ *       ReleaseCount = 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL        
+NtReleaseMutant(
+       IN HANDLE MutantHandle,
+       IN PULONG ReleaseCount OPTIONAL
+       );
+
+NTSTATUS
+STDCALL        
+ZwReleaseMutant(
+       IN HANDLE MutantHandle,
+       IN PULONG ReleaseCount OPTIONAL
+       );
+
+/*
+ * FUNCTION: Releases a semaphore
+ * ARGUMENTS: 
+ *       SemaphoreHandle = Handle to the semaphore object
+ *       ReleaseCount = Number to decrease the semaphore count
+ *       PreviousCount = Previous semaphore count
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtReleaseSemaphore(
+       IN      HANDLE  SemaphoreHandle,
+       IN      LONG    ReleaseCount,
+       OUT     PLONG   PreviousCount
+       );
+
+NTSTATUS
+STDCALL
+ZwReleaseSemaphore(
+       IN      HANDLE  SemaphoreHandle,
+       IN      LONG    ReleaseCount,
+       OUT     PLONG   PreviousCount
+       );
+
+/*
+ * FUNCTION: Removes an io completion
+ * ARGUMENTS:
+ *        CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ *        CompletionKey = Requested access to the key
+ *        IoStatusBlock = Caller provides storage for extended status information
+ *        CompletionStatus = Current status of the io operation.
+ *        WaitTime = Time to wait if ..
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtRemoveIoCompletion(
+       IN HANDLE CompletionPort,
+       OUT PULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PULONG CompletionStatus,
+       IN PLARGE_INTEGER WaitTime 
+       );
+
+NTSTATUS
+STDCALL
+ZwRemoveIoCompletion(
+       IN HANDLE CompletionPort,
+       OUT PULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       OUT PULONG CompletionStatus,
+       IN PLARGE_INTEGER WaitTime 
+       );
+/*
+ * FUNCTION: Replaces one registry key with another
+ * ARGUMENTS: 
+ *       ObjectAttributes = Specifies the attributes of the key
+ *       Key =  Handle to the key
+ *       ReplacedObjectAttributes = The function returns the old object attributes
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtReplaceKey(
+       IN POBJECT_ATTRIBUTES ObjectAttributes, 
+       IN HANDLE Key,
+       IN POBJECT_ATTRIBUTES ReplacedObjectAttributes 
+       );
+NTSTATUS
+STDCALL
+ZwReplaceKey(
+       IN POBJECT_ATTRIBUTES ObjectAttributes, 
+       IN HANDLE Key,
+       IN POBJECT_ATTRIBUTES ReplacedObjectAttributes 
+       );
+
+/*
+ * FUNCTION: Resets a event to a non signaled state 
+ * ARGUMENTS: 
+ *       EventHandle = Handle to the event that should be reset
+ *       NumberOfWaitingThreads =  The number of threads released.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtResetEvent(
+       HANDLE EventHandle,
+       PULONG NumberOfWaitingThreads OPTIONAL
+       );
+NTSTATUS
+STDCALL
+ZwResetEvent(
+       HANDLE EventHandle,
+       PULONG NumberOfWaitingThreads OPTIONAL
+       );
+//draft
+NTSTATUS
+STDCALL
+NtRestoreKey(
+       HANDLE KeyHandle,
+       HANDLE FileHandle,
+       ULONG RestoreFlags
+       );
+
+NTSTATUS
+STDCALL
+ZwRestoreKey(
+       HANDLE KeyHandle,
+       HANDLE FileHandle,
+       ULONG RestoreFlags
+       );
+/*
+ * FUNCTION: Decrements a thread's resume count
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread that should be resumed
+ *        ResumeCount =  The resulting resume count.
+ * REMARK:
+ *       A thread is resumed if its suspend count is 0. This procedure maps to
+ *        the win32 ResumeThread function. ( documentation about the the suspend count can be found here aswell )
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtResumeThread(
+       IN HANDLE ThreadHandle,
+       OUT PULONG SuspendCount
+       );
+NTSTATUS
+STDCALL
+ZwResumeThread(
+       IN HANDLE ThreadHandle,
+       OUT PULONG SuspendCount
+       );
+/*
+ * FUNCTION: Writes the content of a registry key to ascii file
+ * ARGUMENTS: 
+ *        KeyHandle = Handle to the key
+ *        FileHandle =  Handle of the file
+ * REMARKS:
+         This function maps to the Win32 RegSaveKey.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSaveKey(
+       IN HANDLE KeyHandle,
+       IN HANDLE FileHandle
+       );
+NTSTATUS
+STDCALL
+ZwSaveKey(
+       IN HANDLE KeyHandle,
+       IN HANDLE FileHandle
+       );
+
+/*
+ * FUNCTION: Sets the context of a specified thread.
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread
+ *        Context =  The processor context.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetContextThread(
+       IN HANDLE ThreadHandle,
+       IN PCONTEXT Context
+       );
+NTSTATUS
+STDCALL
+ZwSetContextThread(
+       IN HANDLE ThreadHandle,
+       IN PCONTEXT Context
+       );
+
+/*
+ * FUNCTION: Sets the default locale id
+ * ARGUMENTS:
+ *        UserProfile = Type of locale id
+ *              TRUE: thread locale id
+ *              FALSE: system locale id
+ *        DefaultLocaleId = Locale id
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetDefaultLocale(
+       IN BOOLEAN UserProfile,
+       IN LCID DefaultLocaleId
+       );
+
+NTSTATUS
+STDCALL
+ZwSetDefaultLocale(
+       IN BOOLEAN UserProfile,
+       IN LCID DefaultLocaleId
+       );
+
+/*
+ * FUNCTION: Sets the default hard error port
+ * ARGUMENTS:
+ *        PortHandle = Handle to the port
+ * NOTE: The hard error port is used for first change exception handling
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetDefaultHardErrorPort(
+       IN HANDLE PortHandle
+       );
+NTSTATUS
+STDCALL
+ZwSetDefaultHardErrorPort(
+       IN HANDLE PortHandle
+       );
+
+/*
+ * FUNCTION: Sets the extended attributes of a file.
+ * ARGUMENTS:
+ *        FileHandle = Handle to the file
+ *        IoStatusBlock = Storage for a resulting status and information
+ *                        on the current operation.
+ *        EaBuffer = Extended Attributes buffer.
+ *        EaBufferSize = Size of the extended attributes buffer
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetEaFile(
+       IN HANDLE FileHandle,
+       IN PIO_STATUS_BLOCK IoStatusBlock,
+       PVOID EaBuffer,
+       ULONG EaBufferSize
+       );
+NTSTATUS
+STDCALL
+ZwSetEaFile(
+       IN HANDLE FileHandle,
+       IN PIO_STATUS_BLOCK IoStatusBlock,
+       PVOID EaBuffer,
+       ULONG EaBufferSize
+       );
+
+//FIXME: should I return the event state ?
+
+/*
+ * FUNCTION: Sets the  event to a signalled state.
+ * ARGUMENTS: 
+ *        EventHandle = Handle to the event
+ *        NumberOfThreadsReleased =  The number of threads released
+ * REMARK:
+ *       This procedure maps to the win32 SetEvent function. 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetEvent(
+       IN HANDLE EventHandle,
+       PULONG NumberOfThreadsReleased
+       );
+
+NTSTATUS
+STDCALL
+ZwSetEvent(
+       IN HANDLE EventHandle,
+       PULONG NumberOfThreadsReleased
+       );
+
+/*
+ * FUNCTION: Sets the high part of an event pair
+ * ARGUMENTS: 
+       EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetHighEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwSetHighEventPair(
+       IN HANDLE EventPairHandle
+       );
+/*
+ * FUNCTION: Sets the high part of an event pair and wait for the low part
+ * ARGUMENTS: 
+       EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetHighWaitLowEventPair(
+       IN HANDLE EventPairHandle
+       );
+NTSTATUS
+STDCALL
+ZwSetHighWaitLowEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+/*
+ * FUNCTION: Sets the information of a file object.
+ * ARGUMENTS: 
+ *        FileHandle = Handle to the file object
+ *       IoStatusBlock = Caller supplies storage for extended information 
+ *                        on the current operation.
+ *        FileInformation = Storage for the new file information
+ *        Lenght = Size of the new file information.
+ *        FileInformationClass = Indicates to a certain information structure
+        
+         FileNameInformation                   FILE_NAME_INFORMATION
+         FileRenameInformation                 FILE_RENAME_INFORMATION
+         FileStreamInformation                 FILE_STREAM_INFORMATION
+ *       FileCompletionInformation             IO_COMPLETION_CONTEXT
+
+ * REMARK:
+ *       This procedure maps to the win32 SetEndOfFile, SetFileAttributes, 
+ *       SetNamedPipeHandleState, SetMailslotInfo functions. 
+ * RETURNS: Status
+ */
+
+
+NTSTATUS
+STDCALL
+NtSetInformationFile(
+       IN      HANDLE                  FileHandle,
+       IN      PIO_STATUS_BLOCK        IoStatusBlock,
+       IN      PVOID                   FileInformation,
+       IN      ULONG                   Length,
+       IN      FILE_INFORMATION_CLASS  FileInformationClass
+       );
+NTSTATUS
+STDCALL
+ZwSetInformationFile(
+       IN      HANDLE                  FileHandle,
+       IN      PIO_STATUS_BLOCK        IoStatusBlock,
+       IN      PVOID                   FileInformation,
+       IN      ULONG                   Length,
+       IN      FILE_INFORMATION_CLASS  FileInformationClass
+       );
+
+/*
+ * FUNCTION: Changes a set of thread specific parameters
+ * ARGUMENTS: 
+ *      ThreadHandle = Handle to the thread
+ *     ThreadInformationClass = Index to the set of parameters to change. 
+ *     Can be one of the following values:
+ *
+ *     ThreadBasicInformation                  THREAD_BASIC_INFORMATION
+ *     ThreadPriority                          KPRIORITY //???
+ *     ThreadBasePriority                      KPRIORITY
+ *     ThreadAffinityMask                      KAFFINITY //??
+ *      ThreadImpersonationToken               ACCESS_TOKEN
+ *     ThreadIdealProcessor                    ULONG
+ *     ThreadPriorityBoost                     ULONG
+ *
+ *      ThreadInformation = Caller supplies storage for parameters to set.
+ *      ThreadInformationLength = Size of the storage supplied
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationThread(
+       IN HANDLE ThreadHandle,
+       IN THREADINFOCLASS ThreadInformationClass,
+       IN PVOID ThreadInformation,
+       IN ULONG ThreadInformationLength
+       );
+NTSTATUS
+STDCALL
+ZwSetInformationThread(
+       IN HANDLE ThreadHandle,
+       IN THREADINFOCLASS ThreadInformationClass,
+       IN PVOID ThreadInformation,
+       IN ULONG ThreadInformationLength
+       );
+
+/*
+ * FUNCTION: Changes a set of token specific parameters
+ * ARGUMENTS: 
+ *      TokenHandle = Handle to the token
+ *     TokenInformationClass = Index to a certain information structure. 
+ *     Can be one of the following values:
+ *
+               TokenUser               TOKEN_USER 
+               TokenGroups             TOKEN_GROUPS
+               TokenPrivileges         TOKEN_PRIVILEGES
+               TokenOwner              TOKEN_OWNER
+               TokenPrimaryGroup       TOKEN_PRIMARY_GROUP
+               TokenDefaultDacl        TOKEN_DEFAULT_DACL
+               TokenSource             TOKEN_SOURCE
+               TokenType               TOKEN_TYPE
+               TokenImpersonationLevel TOKEN_IMPERSONATION_LEVEL
+               TokenStatistics         TOKEN_STATISTICS
+ *
+ *      TokenInformation = Caller supplies storage for information structure.
+ *      TokenInformationLength = Size of the information structure
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetInformationToken(
+       IN HANDLE TokenHandle,            
+       IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+       OUT PVOID TokenInformation,       
+       IN ULONG TokenInformationLength   
+       );
+
+NTSTATUS
+STDCALL
+ZwSetInformationToken(
+       IN HANDLE TokenHandle,            
+       IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+       OUT PVOID TokenInformation,       
+       IN ULONG TokenInformationLength   
+       );
+
+
+/*
+ * FUNCTION: Sets an io completion
+ * ARGUMENTS: 
+ *      CompletionPort = 
+ *     CompletionKey = 
+ *      IoStatusBlock =
+ *      NumberOfBytesToTransfer =
+ *      NumberOfBytesTransferred =
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetIoCompletion(
+       IN HANDLE CompletionPort,
+       IN ULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG NumberOfBytesToTransfer, 
+       OUT PULONG NumberOfBytesTransferred
+       );
+NTSTATUS
+STDCALL
+ZwSetIoCompletion(
+       IN HANDLE CompletionPort,
+       IN ULONG CompletionKey,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN ULONG NumberOfBytesToTransfer, 
+       OUT PULONG NumberOfBytesTransferred
+       );
+
+/*
+ * FUNCTION: Set properties for profiling
+ * ARGUMENTS: 
+ *      Interval = 
+ *     ClockSource = 
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS 
+STDCALL
+NtSetIntervalProfile(
+       ULONG Interval,
+       KPROFILE_SOURCE ClockSource
+       );
+
+NTSTATUS 
+STDCALL
+ZwSetIntervalProfile(
+       ULONG Interval,
+       KPROFILE_SOURCE ClockSource
+       );
+
+
+/*
+ * FUNCTION: Sets the low part of an event pair
+ * ARGUMENTS: 
+       EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetLowEventPair(
+       HANDLE EventPair
+       );
+NTSTATUS
+STDCALL
+ZwSetLowEventPair(
+       HANDLE EventPair
+       );
+/*
+ * FUNCTION: Sets the low part of an event pair and wait for the high part
+ * ARGUMENTS: 
+       EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetLowWaitHighEventPair(
+       HANDLE EventPair
+       );
+NTSTATUS
+STDCALL
+ZwSetLowWaitHighEventPair(
+       HANDLE EventPair
+       );
+
+NTSTATUS
+STDCALL
+NtSetSecurityObject(
+       IN HANDLE Handle, 
+       IN SECURITY_INFORMATION SecurityInformation, 
+       IN PSECURITY_DESCRIPTOR SecurityDescriptor 
+       ); 
+
+NTSTATUS
+STDCALL
+ZwSetSecurityObject(
+       IN HANDLE Handle, 
+       IN SECURITY_INFORMATION SecurityInformation, 
+       IN PSECURITY_DESCRIPTOR SecurityDescriptor 
+       ); 
+
+
+/*
+ * FUNCTION: Sets a system environment variable
+ * ARGUMENTS: 
+ *      ValueName = Name of the environment variable
+ *     Value = Value of the environment variable
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemEnvironmentValue(
+       IN PUNICODE_STRING VariableName,
+       IN PUNICODE_STRING Value
+       );
+NTSTATUS
+STDCALL
+ZwSetSystemEnvironmentValue(
+       IN PUNICODE_STRING VariableName,
+       IN PUNICODE_STRING Value
+       );
+/*
+ * FUNCTION: Sets system parameters
+ * ARGUMENTS: 
+ *      SystemInformationClass = Index to a particular set of system parameters
+ *                     Can be one of the following values:
+ *
+ *     SystemTimeAdjustmentInformation         SYSTEM_TIME_ADJUSTMENT
+ *
+ *     SystemInformation = Structure containing the parameters.
+ *      SystemInformationLength = Size of the structure.
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemInformation(
+       IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
+       IN      PVOID                           SystemInformation,
+       IN      ULONG                           SystemInformationLength
+       );
+
+NTSTATUS
+STDCALL
+ZwSetSystemInformation(
+       IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
+       IN      PVOID                           SystemInformation,
+       IN      ULONG                           SystemInformationLength
+       );
+
+/*
+ * FUNCTION: Sets the system time
+ * ARGUMENTS: 
+ *      SystemTime = Old System time
+ *     NewSystemTime = New System time
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemTime(
+       IN PLARGE_INTEGER SystemTime,
+       IN PLARGE_INTEGER NewSystemTime OPTIONAL
+       );
+NTSTATUS
+STDCALL
+ZwSetSystemTime(
+       IN PLARGE_INTEGER SystemTime,
+       IN PLARGE_INTEGER NewSystemTime OPTIONAL
+       );
+
+/*
+ * FUNCTION: Sets the frequency of the system timer
+ * ARGUMENTS: 
+ *      RequestedResolution = 
+ *     SetOrUnset = 
+ *      ActualResolution = 
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetTimerResolution(
+       IN ULONG RequestedResolution,
+       IN BOOL SetOrUnset,
+       OUT PULONG ActualResolution
+       );
+NTSTATUS
+STDCALL
+ZwSetTimerResolution(
+       IN ULONG RequestedResolution,
+       IN BOOL SetOrUnset,
+       OUT PULONG ActualResolution
+       );
+
+/*
+ * FUNCTION: Sets the value of a registry key
+ * ARGUMENTS: 
+ *      KeyHandle = Handle to a registry key
+ *     ValueName = Name of the value entry to change
+ *     TitleIndex = pointer to a structure containing the new volume information
+ *      Type = Type of the registry key. Can be one of the values:
+ *             REG_BINARY                      Unspecified binary data
+ *             REG_DWORD                       A 32 bit value
+ *             REG_DWORD_LITTLE_ENDIAN         Same as REG_DWORD
+ *             REG_DWORD_BIG_ENDIAN            A 32 bit value whose least significant byte is at the highest address
+ *             REG_EXPAND_SZ                   A zero terminated wide character string with unexpanded environment variables  ( "%PATH%" )
+ *             REG_LINK                        A zero terminated wide character string referring to a symbolic link.
+ *             REG_MULTI_SZ                    A series of zero-terminated strings including a additional trailing zero
+ *             REG_NONE                        Unspecified type
+ *             REG_SZ                          A wide character string ( zero terminated )
+ *             REG_RESOURCE_LIST               ??
+ *             REG_RESOURCE_REQUIREMENTS_LIST  ??
+ *             REG_FULL_RESOURCE_DESCRIPTOR    ??
+ *      Data = Contains the data for the registry key.
+ *     DataSize = size of the data.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName,
+       IN ULONG TitleIndex OPTIONAL,
+       IN ULONG Type,
+       IN PVOID Data,
+       IN ULONG DataSize
+       );
+NTSTATUS
+STDCALL
+ZwSetValueKey(
+       IN HANDLE KeyHandle,
+       IN PUNICODE_STRING ValueName,
+       IN ULONG TitleIndex OPTIONAL,
+       IN ULONG Type,
+       IN PVOID Data,
+       IN ULONG DataSize
+       );
+
+/*
+ * FUNCTION: Sets the volume information.
+ * ARGUMENTS:
+ *     FileHandle = Handle to the file
+ *     IoStatusBlock = Caller should supply storage for additional status information
+ *     VolumeInformation = pointer to a structure containing the new volume information
+ *     Length = size of the structure.
+ *     VolumeInformationClass = specifies the particular volume information to set
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetVolumeInformationFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PVOID FsInformation,
+       IN ULONG Length,
+       IN FS_INFORMATION_CLASS FsInformationClass
+       );
+
+NTSTATUS
+STDCALL
+ZwSetVolumeInformationFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PVOID FsInformation,
+       IN ULONG Length,
+       IN FS_INFORMATION_CLASS FsInformationClass
+       );
+
+/*
+ * FUNCTION: Shuts the system down
+ * ARGUMENTS:
+ *        Action = Specifies the type of shutdown, it can be one of the following values:
+ *              ShutdownNoReboot, ShutdownReboot, ShutdownPowerOff
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtShutdownSystem(
+       IN SHUTDOWN_ACTION Action
+       );
+
+NTSTATUS
+STDCALL
+ZwShutdownSystem(
+       IN SHUTDOWN_ACTION Action
+       );
+
+
+/* --- PROFILING --- */
+
+/*
+ * FUNCTION: Starts profiling
+ * ARGUMENTS: 
+ *       ProfileHandle = Handle to the profile
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtStartProfile(
+       HANDLE ProfileHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwStartProfile(
+       HANDLE ProfileHandle
+       );
+
+/*
+ * FUNCTION: Stops profiling
+ * ARGUMENTS: 
+ *       ProfileHandle = Handle to the profile
+ * RETURNS: Status    
+ */
+
+NTSTATUS
+STDCALL
+NtStopProfile(
+       HANDLE ProfileHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwStopProfile(
+       HANDLE ProfileHandle
+       );
+
+/* --- PROCESS MANAGEMENT --- */
+
+//--NtSystemDebugControl
+/*
+ * FUNCTION: Terminates the execution of a process. 
+ * ARGUMENTS: 
+ *      ThreadHandle = Handle to the process
+ *      ExitStatus  = The exit status of the process to terminate with.
+ * REMARKS
+       Native applications should kill themselves using this function.
+ * RETURNS: Status
+ */    
+NTSTATUS 
+STDCALL 
+NtTerminateProcess(
+       IN HANDLE ProcessHandle ,
+       IN NTSTATUS ExitStatus
+       );
+NTSTATUS 
+STDCALL 
+ZwTerminateProcess(
+       IN HANDLE ProcessHandle ,
+       IN NTSTATUS ExitStatus
+       );
+
+/* --- DEVICE DRIVER CONTROL --- */
+
+/*
+ * FUNCTION: Unloads a driver. 
+ * ARGUMENTS: 
+ *      DriverServiceName = Name of the driver to unload
+ * RETURNS: Status
+ */    
+NTSTATUS 
+STDCALL
+NtUnloadDriver(
+       IN PUNICODE_STRING DriverServiceName
+       );
+NTSTATUS 
+STDCALL
+ZwUnloadDriver(
+       IN PUNICODE_STRING DriverServiceName
+       );
+
+/* --- VIRTUAL MEMORY MANAGEMENT --- */
+
+/*
+ * FUNCTION: Writes a range of virtual memory
+ * ARGUMENTS: 
+ *       ProcessHandle = The handle to the process owning the address space.
+ *       BaseAddress  = The points to the address to  write to
+ *       Buffer = Pointer to the buffer to write
+ *       NumberOfBytesToWrite = Offset to the upper boundary to write
+ *       NumberOfBytesWritten = Total bytes written
+ * REMARKS:
+ *      This function maps to the win32 WriteProcessMemory
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL 
+NtWriteVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID  BaseAddress,
+       IN PVOID Buffer,
+       IN ULONG NumberOfBytesToWrite,
+       OUT PULONG NumberOfBytesWritten
+       );
+
+NTSTATUS
+STDCALL 
+ZwWriteVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID  BaseAddress,
+       IN PVOID Buffer,
+       IN ULONG NumberOfBytesToWrite,
+       OUT PULONG NumberOfBytesWritten
+       );
+
+/*
+ * FUNCTION: Unmaps a piece of virtual memory backed by a file. 
+ * ARGUMENTS: 
+ *       ProcessHandle = Handle to the process
+ *       BaseAddress =  The address where the mapping begins
+ * REMARK:
+       This procedure maps to the win32 UnMapViewOfFile
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtUnmapViewOfSection(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress
+       );
+NTSTATUS
+STDCALL
+ZwUnmapViewOfSection(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress
+       );
+
+/* --- OBJECT SYNCHRONIZATION --- */
+
+/*
+ * FUNCTION: Signals an object and wait for an other one.
+ * ARGUMENTS: 
+ *        SignalObject = Handle to the object that should be signaled
+ *        WaitObject = Handle to the object that should be waited for
+ *        Alertable = True if the wait is alertable
+ *        Time = The time to wait
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSignalAndWaitForSingleObject(
+       IN      HANDLE          SignalObject,
+       IN      HANDLE          WaitObject,
+       IN      BOOLEAN         Alertable,
+       IN      PLARGE_INTEGER  Time
+       );
+
+NTSTATUS
+STDCALL
+NtSignalAndWaitForSingleObject(
+       IN      HANDLE          SignalObject,
+       IN      HANDLE          WaitObject,
+       IN      BOOLEAN         Alertable,
+       IN      PLARGE_INTEGER  Time
+       );
+
+/*
+ * FUNCTION: Waits for an object to become signalled.
+ * ARGUMENTS: 
+ *       Object = The object handle
+ *       Alertable = If true the wait is alertable.
+ *       Time = The maximum wait time.
+ * REMARKS:
+ *       This function maps to the win32 WaitForSingleObjectEx.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitForSingleObject (
+       IN HANDLE Object,
+       IN BOOLEAN Alertable,
+       IN PLARGE_INTEGER Time
+       );
+
+NTSTATUS
+STDCALL
+ZwWaitForSingleObject (
+       IN HANDLE Object,
+       IN BOOLEAN Alertable,
+       IN PLARGE_INTEGER Time
+       );
+
+/* --- EVENT PAIR OBJECT --- */
+
+/*
+ * FUNCTION: Waits for the high part of an eventpair to become signalled
+ * ARGUMENTS:
+ *       EventPairHandle = Handle to the event pair.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtWaitHighEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwWaitHighEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+/*
+ * FUNCTION: Waits for the low part of an eventpair to become signalled
+ * ARGUMENTS:
+ *       EventPairHandle = Handle to the event pair.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitLowEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwWaitLowEventPair(
+       IN HANDLE EventPairHandle
+       );
+
+/* --- FILE MANAGEMENT --- */
+
+/*
+ * FUNCTION: Unlocks a range of bytes in a file. 
+ * ARGUMENTS: 
+ *       FileHandle = Handle to the file
+ *       IoStatusBlock = Caller should supply storage for a structure containing
+ *                      the completion status and information about the requested unlock operation.
+                       The information field is set to the number of bytes unlocked.
+ *       ByteOffset = Offset to start the range of bytes to unlock 
+ *       Length = Number of bytes to unlock.
+ *       Key = Special value to enable other threads to unlock a file than the
+               thread that locked the file. The key supplied must match with the one obtained
+               in a previous call to NtLockFile.
+ * REMARK:
+       This procedure maps to the win32 procedure UnlockFileEx. STATUS_PENDING is returned if the lock could
+       not be obtained immediately, the device queue is busy and the IRP is queued.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+       STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_RANGE_NOT_LOCKED ]
+ */    
+NTSTATUS 
+STDCALL
+NtUnlockFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PLARGE_INTEGER ByteOffset,
+       IN PLARGE_INTEGER Lenght,
+       OUT PULONG Key OPTIONAL
+       );
+NTSTATUS 
+STDCALL
+ZwUnlockFile(
+       IN HANDLE FileHandle,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PLARGE_INTEGER ByteOffset,
+       IN PLARGE_INTEGER Lenght,
+       OUT PULONG Key OPTIONAL
+       );
+       
+/*
+ * FUNCTION: Writes data to a file
+ * ARGUMENTS: 
+ *       FileHandle = The handle a file ( from NtCreateFile )
+ *       Event  = Specifies a event that will become signalled when the write operation completes.
+ *       ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ]
+ *       ApcContext = Argument to the Apc Routine 
+ *       IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation.
+ *       Buffer = Caller should supply storage for a buffer that will contain the information to be written to file.
+ *       Length = Size in bytest of the buffer
+ *       ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged.
+ *                   BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if
+ *                    the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset
+ *                    should be created by specifying FILE_USE_FILE_POINTER_POSITION.
+ *       Key =  Unused
+ * REMARKS:
+ *      This function maps to the win32 WriteFile. 
+ *      Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES
+       STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ]
+ */
+NTSTATUS
+STDCALL
+NtWriteFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PVOID Buffer,
+       IN ULONG Length,
+       IN PLARGE_INTEGER ByteOffset,
+       IN PULONG Key OPTIONAL
+    );
+
+NTSTATUS
+STDCALL
+ZwWriteFile(
+       IN HANDLE FileHandle,
+       IN HANDLE Event OPTIONAL,
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+       IN PVOID ApcContext OPTIONAL,
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN PVOID Buffer,
+       IN ULONG Length,
+       IN PLARGE_INTEGER ByteOffset ,
+       IN PULONG Key OPTIONAL
+    );
+
+/*
+ * FUNCTION: Writes a file 
+ * ARGUMENTS: 
+ *       FileHandle = The handle of the file 
+ *       Event  = 
+ *       ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ]
+ *       ApcContext = Argument to the Apc Routine 
+ *       IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation.
+ *       BufferDescription = Caller should supply storage for a buffer that will contain the information to be written to file.
+ *       BufferLength = Size in bytest of the buffer
+ *       ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged.
+ *                   BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if
+ *                    the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset
+ *                    should be created by specifying FILE_USE_FILE_POINTER_POSITION. Use FILE_WRITE_TO_END_OF_FILE to write to the EOF.
+ *       Key = If a matching key [ a key provided at NtLockFile ] is provided the write operation will continue even if a byte range is locked.
+ * REMARKS:
+ *      This function maps to the win32 WriteFile. 
+ *      Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES
+               STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ]
+ */
+
+NTSTATUS
+STDCALL 
+NtWriteFileGather( 
+       IN HANDLE FileHandle, 
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN FILE_SEGMENT_ELEMENT BufferDescription[], 
+       IN ULONG BufferLength, 
+       IN PLARGE_INTEGER ByteOffset, 
+       IN PULONG Key OPTIONAL
+       ); 
+
+NTSTATUS
+STDCALL 
+ZwWriteFileGather( 
+       IN HANDLE FileHandle, 
+       IN HANDLE Event OPTIONAL, 
+       IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
+       IN PVOID ApcContext OPTIONAL, 
+       OUT PIO_STATUS_BLOCK IoStatusBlock,
+       IN FILE_SEGMENT_ELEMENT BufferDescription[], 
+       IN ULONG BufferLength, 
+       IN PLARGE_INTEGER ByteOffset, 
+       IN PULONG Key OPTIONAL
+       ); 
+
+
+/* --- THREAD MANAGEMENT --- */
+
+/*
+ * FUNCTION: Increments a thread's resume count
+ * ARGUMENTS: 
+ *        ThreadHandle = Handle to the thread that should be resumed
+ *        PreviousSuspendCount =  The resulting/previous suspend count.
+ * REMARK:
+ *       A thread will be suspended if its suspend count is greater than 0. This procedure maps to
+ *        the win32 SuspendThread function. ( documentation about the the suspend count can be found here aswell )
+ *        The suspend count is not increased if it is greater than MAXIMUM_SUSPEND_COUNT.
+ * RETURNS: Status
+ */ 
+NTSTATUS 
+STDCALL 
+NtSuspendThread(
+       IN HANDLE ThreadHandle,
+       IN PULONG PreviousSuspendCount 
+       );
+
+NTSTATUS 
+STDCALL 
+ZwSuspendThread(
+       IN HANDLE ThreadHandle,
+       IN PULONG PreviousSuspendCount 
+       );
+
+/*
+ * FUNCTION: Terminates the execution of a thread. 
+ * ARGUMENTS: 
+ *      ThreadHandle = Handle to the thread
+ *      ExitStatus  = The exit status of the thread to terminate with.
+ * RETURNS: Status
+ */    
+NTSTATUS 
+STDCALL 
+NtTerminateThread(
+       IN HANDLE ThreadHandle ,
+       IN NTSTATUS ExitStatus
+       );
+NTSTATUS 
+STDCALL 
+ZwTerminateThread(
+       IN HANDLE ThreadHandle ,
+       IN NTSTATUS ExitStatus
+       );
+/*
+ * FUNCTION: Tests to see if there are any pending alerts for the calling thread 
+ * RETURNS: Status
+ */    
+NTSTATUS 
+STDCALL 
+NtTestAlert(
+       VOID 
+       );
+NTSTATUS 
+STDCALL 
+ZwTestAlert(
+       VOID 
+       );
+
+/*
+ * FUNCTION: Yields the callers thread.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL 
+NtYieldExecution(
+       VOID
+       );
+
+NTSTATUS
+STDCALL 
+ZwYieldExecution(
+       VOID
+       );
+
+/* --- PLUG AND PLAY --- */
+
+NTSTATUS
+STDCALL
+NtPlugPlayControl (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtGetPlugPlayEvent (
+       VOID
+       );
+
+/* --- POWER MANAGEMENT --- */
+
+NTSTATUS STDCALL 
+NtSetSystemPowerState(IN POWER_ACTION SystemAction,
+                     IN SYSTEM_POWER_STATE MinSystemState,
+                     IN ULONG Flags);
+
+/* --- DEBUG SUBSYSTEM --- */
+
+NTSTATUS STDCALL 
+NtSystemDebugControl(DEBUG_CONTROL_CODE ControlCode,
+                    PVOID InputBuffer,
+                    ULONG InputBufferLength,
+                    PVOID OutputBuffer,
+                    ULONG OutputBufferLength,
+                    PULONG ReturnLength);
+
+/* --- VIRTUAL DOS MACHINE (VDM) --- */
+
+NTSTATUS
+STDCALL
+NtVdmControl (ULONG ControlCode, PVOID ControlData);
+
+
+/* --- WIN32 --- */
+
+NTSTATUS STDCALL
+NtW32Call(IN ULONG RoutineIndex,
+         IN PVOID Argument,
+         IN ULONG ArgumentLength,
+         OUT PVOID* Result OPTIONAL,
+         OUT PULONG ResultLength OPTIONAL);
+
+/* --- CHANNELS --- */
+
+NTSTATUS
+STDCALL
+NtCreateChannel (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtListenChannel (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtOpenChannel (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtReplyWaitSendChannel (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtSendWaitReplyChannel (
+       VOID
+       );
+
+NTSTATUS
+STDCALL
+NtSetContextChannel (
+       VOID
+       );
+
+/* --- MISCELLANEA --- */
+
+//NTSTATUS STDCALL NtSetLdtEntries(VOID);
+NTSTATUS
+STDCALL
+NtSetLdtEntries (
+       HANDLE  Thread,
+       ULONG           FirstEntry,
+       PULONG  Entries
+       );
+
+NTSTATUS
+STDCALL
+NtQueryOleDirectoryFile (
+       VOID
+       );
+
+/*
+ * FUNCTION: Checks a clients access rights to a object
+ * ARGUMENTS: 
+ *       SecurityDescriptor = Security information against which the access is checked
+ *       ClientToken = Represents a client
+ *       DesiredAcces = 
+ *       GenericMapping =
+ *       PrivilegeSet =
+ *       ReturnLength = Bytes written
+ *       GrantedAccess = 
+ *       AccessStatus = Indicates if the ClientToken allows the requested access
+ * REMARKS: The arguments map to the win32 AccessCheck 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAccessCheck(
+       IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+       IN HANDLE ClientToken,
+       IN ACCESS_MASK DesiredAcces,
+       IN PGENERIC_MAPPING GenericMapping,
+       OUT PPRIVILEGE_SET PrivilegeSet,
+       OUT PULONG ReturnLength,
+       OUT PULONG GrantedAccess,
+       OUT PBOOLEAN AccessStatus
+       );
+
+NTSTATUS
+STDCALL
+ZwAccessCheck(
+       IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+       IN HANDLE ClientToken,
+       IN ACCESS_MASK DesiredAcces,
+       IN PGENERIC_MAPPING GenericMapping,
+       OUT PPRIVILEGE_SET PrivilegeSet,
+       OUT PULONG ReturnLength,
+       OUT PULONG GrantedAccess,
+       OUT PBOOLEAN AccessStatus
+       );
+
+NTSTATUS
+STDCALL
+RtlOpenCurrentUser(
+  IN  ACCESS_MASK  DesiredAccess,
+  OUT  PHANDLE  KeyHandle);
+
+
+#ifndef __USE_W32API
+
+/*
+ * FUNCTION: Continues a thread with the specified context
+ * ARGUMENTS: 
+ *        Context = Specifies the processor context
+ *       IrqLevel = Specifies the Interupt Request Level to continue with. Can
+ *                     be PASSIVE_LEVEL or APC_LEVEL
+ * REMARKS
+ *        NtContinue can be used to continue after an exception or apc.
+ * RETURNS: Status
+ */
+//FIXME This function might need another parameter
+
+NTSTATUS
+STDCALL
+NtContinue(
+       IN PCONTEXT Context,
+       IN BOOLEAN TestAlert
+       );
+
+NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel);
+
+/*
+ * FUNCTION: Retrieves the system time
+ * ARGUMENTS: 
+ *        CurrentTime (OUT) = Caller should supply storage for the resulting time.
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtQuerySystemTime (
+       OUT TIME *CurrentTime
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemTime (
+       OUT TIME *CurrentTime
+       );
+
+/*
+ * FUNCTION: Loads a registry key.
+ * ARGUMENTS:
+ *       KeyHandle = Handle to the registry key
+ *       ObjectAttributes = ???
+ *       Unknown3 = ???
+ * REMARK:
+ *       This procedure maps to the win32 procedure RegLoadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtLoadKey2 (
+       PHANDLE                 KeyHandle,
+       POBJECT_ATTRIBUTES      ObjectAttributes,
+       ULONG                   Unknown3
+       );
+NTSTATUS
+STDCALL
+ZwLoadKey2 (
+       PHANDLE                 KeyHandle,
+       POBJECT_ATTRIBUTES      ObjectAttributes,
+       ULONG                   Unknown3
+       );
+
+/*
+ * FUNCTION: Copies a handle from one process space to another
+ * ARGUMENTS:
+ *         SourceProcessHandle = The source process owning the handle. The source process should have opened
+ *                     the SourceHandle with PROCESS_DUP_HANDLE access.
+ *        SourceHandle = The handle to the object.
+ *        TargetProcessHandle = The destination process owning the handle 
+ *        TargetHandle (OUT) = Caller should supply storage for the duplicated handle. 
+ *        DesiredAccess = The desired access to the handle.
+ *        InheritHandle = Indicates wheter the new handle will be inheritable or not.
+ *        Options = Specifies special actions upon duplicating the handle. Can be
+ *                     one of the values DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS.
+ *                     DUPLICATE_CLOSE_SOURCE specifies that the source handle should be
+ *                     closed after duplicating. DUPLICATE_SAME_ACCESS specifies to ignore
+ *                     the DesiredAccess paramter and just grant the same access to the new
+ *                     handle.
+ * RETURNS: Status
+ * REMARKS: This function maps to the win32 DuplicateHandle.
+ */
+
+NTSTATUS
+STDCALL
+NtDuplicateObject(
+       IN HANDLE SourceProcessHandle,
+       IN HANDLE SourceHandle,
+       IN HANDLE TargetProcessHandle,
+       OUT PHANDLE TargetHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN BOOLEAN InheritHandle,
+       IN ULONG Options
+       );
+
+NTSTATUS
+STDCALL
+ZwDuplicateObject(
+       IN HANDLE SourceProcessHandle,
+       IN PHANDLE SourceHandle,
+       IN HANDLE TargetProcessHandle,
+       OUT PHANDLE TargetHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN BOOLEAN InheritHandle,
+       IN ULONG Options
+       );
+
+/*
+ * FUNCTION: Checks a clients access rights to a object and issues a audit a alarm. ( it logs the access )
+ * ARGUMENTS: 
+ *       SubsystemName = Specifies the name of the subsystem, can be "WIN32" or "DEBUG"
+ *       ObjectHandle =
+ *       ObjectAttributes =
+ *       DesiredAcces = 
+ *       GenericMapping =
+ *       ObjectCreation = 
+ *       GrantedAccess = 
+ *       AccessStatus =
+ *       GenerateOnClose =
+ * REMARKS: The arguments map to the win32 AccessCheck 
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAccessCheckAndAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PHANDLE ObjectHandle,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN ACCESS_MASK DesiredAccess,
+       IN PGENERIC_MAPPING GenericMapping,
+       IN BOOLEAN ObjectCreation,
+       OUT PULONG GrantedAccess,
+       OUT PBOOLEAN AccessStatus,
+       OUT PBOOLEAN GenerateOnClose
+       );
+
+NTSTATUS
+STDCALL
+ZwAccessCheckAndAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,
+       IN PHANDLE ObjectHandle,
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN ACCESS_MASK DesiredAccess,
+       IN PGENERIC_MAPPING GenericMapping,
+       IN BOOLEAN ObjectCreation,
+       OUT PULONG GrantedAccess,
+       OUT PBOOLEAN AccessStatus,
+       OUT PBOOLEAN GenerateOnClose
+       );
+
+/*
+ * FUNCTION: Adds an atom to the global atom table
+ * ARGUMENTS:
+ *        AtomString = The string to add to the atom table.
+ *        Atom (OUT) = Caller supplies storage for the resulting atom.
+ * REMARKS: The arguments map to the win32 add GlobalAddAtom.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAddAtom(
+       IN      PWSTR           AtomName,
+       IN OUT  PRTL_ATOM       Atom
+       );
+
+
+NTSTATUS
+STDCALL
+ZwAddAtom(
+       IN      PWSTR           AtomName,
+       IN OUT  PRTL_ATOM       Atom
+       );
+
+NTSTATUS
+STDCALL
+NtAllocateUuids(
+       PULARGE_INTEGER Time,
+       PULONG Range,
+       PULONG Sequence
+       );
+
+NTSTATUS
+STDCALL
+ZwAllocateUuids(
+       PULARGE_INTEGER Time,
+       PULONG Range,
+       PULONG Sequence
+       );
+
+/*
+ * FUNCTION: Cancels a timer
+ * ARGUMENTS: 
+ *        TimerHandle = Handle to the timer
+ *        CurrentState = Specifies the state of the timer when cancelled.
+ * REMARKS:
+ *        The arguments to this function map to the function CancelWaitableTimer. 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCancelTimer(
+       IN HANDLE TimerHandle,
+       OUT PBOOLEAN CurrentState OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwCancelTimer(
+       IN HANDLE TimerHandle,
+       OUT ULONG ElapsedTime
+       );
+
+/*
+ * FUNCTION: Creates a paging file.
+ * ARGUMENTS:
+ *        FileName  = Name of the pagefile
+ *        InitialSize = Specifies the initial size in bytes
+ *        MaximumSize = Specifies the maximum size in bytes
+ *        Reserved = Reserved for future use
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreatePagingFile(
+       IN PUNICODE_STRING FileName,
+       IN PLARGE_INTEGER InitialSize,
+       IN PLARGE_INTEGER MaxiumSize,
+       IN ULONG Reserved
+       );
+
+NTSTATUS
+STDCALL
+ZwCreatePagingFile(
+       IN PUNICODE_STRING FileName,
+       IN PLARGE_INTEGER InitialSize,
+       IN PLARGE_INTEGER MaxiumSize,
+       IN ULONG Reserved
+       );
+
+/*
+ * FUNCTION: Creates a user mode thread
+ * ARGUMENTS:
+ *        ThreadHandle (OUT) = Caller supplied storage for the resulting handle
+ *        DesiredAccess = Specifies the allowed or desired access to the thread. 
+ *        ObjectAttributes = Initialized attributes for the object.
+ *        ProcessHandle = Handle to the threads parent process.
+ *        ClientId (OUT) = Caller supplies storage for returned process id and thread id.
+ *        ThreadContext = Initial processor context for the thread.
+ *        InitialTeb = Initial user mode stack context for the thread.
+ *        CreateSuspended = Specifies if the thread is ready for scheduling
+ * REMARKS:
+ *        This function maps to the win32 function CreateThread.  
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL 
+NtCreateThread(
+       OUT     PHANDLE                 ThreadHandle,
+       IN      ACCESS_MASK             DesiredAccess,
+       IN      POBJECT_ATTRIBUTES      ObjectAttributes        OPTIONAL,
+       IN      HANDLE                  ProcessHandle,
+       OUT     PCLIENT_ID              ClientId,
+       IN      PCONTEXT                ThreadContext,
+       IN      PINITIAL_TEB            InitialTeb,
+       IN      BOOLEAN                 CreateSuspended
+       );
+
+NTSTATUS
+STDCALL 
+ZwCreateThread(
+       OUT PHANDLE ThreadHandle,
+       IN ACCESS_MASK DesiredAccess,
+       IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+       IN HANDLE ProcessHandle,
+       OUT PCLIENT_ID ClientId,
+       IN PCONTEXT ThreadContext,
+       IN PINITIAL_TEB InitialTeb,
+       IN BOOLEAN CreateSuspended
+       );
+
+NTSTATUS
+STDCALL
+NtDuplicateToken(  
+       IN HANDLE ExistingToken, 
+       IN ACCESS_MASK DesiredAccess, 
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+       IN TOKEN_TYPE TokenType,  
+       OUT PHANDLE NewToken     
+       );
+
+NTSTATUS
+STDCALL
+ZwDuplicateToken(  
+       IN HANDLE ExistingToken, 
+       IN ACCESS_MASK DesiredAccess, 
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+       IN TOKEN_TYPE TokenType,  
+       OUT PHANDLE NewToken     
+       );
+
+/*
+ * FUNCTION: Finds a atom
+ * ARGUMENTS:
+ *       AtomName = Name to search for.
+ *       Atom = Caller supplies storage for the resulting atom
+ * RETURNS: Status 
+ * REMARKS:
+ *     This funciton maps to the win32 GlobalFindAtom
+ */
+NTSTATUS
+STDCALL
+NtFindAtom(
+       IN      PWSTR           AtomName,
+       OUT     PRTL_ATOM       Atom OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwFindAtom(
+       IN      PWSTR           AtomName,
+       OUT     PRTL_ATOM       Atom OPTIONAL
+       );
+
+/*
+ * FUNCTION: Flushes a the processors instruction cache
+ * ARGUMENTS:
+ *       ProcessHandle = Points to the process owning the cache
+ *      BaseAddress = // might this be a image address ????
+ *      NumberOfBytesToFlush = 
+ * RETURNS: Status 
+ * REMARKS:
+ *     This funciton is used by debuggers
+ */
+NTSTATUS
+STDCALL
+NtFlushInstructionCache(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN UINT NumberOfBytesToFlush
+       );
+
+NTSTATUS
+STDCALL
+ZwFlushInstructionCache(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN UINT NumberOfBytesToFlush
+       );
+
+/*
+ * FUNCTION: Flushes virtual memory to file
+ * ARGUMENTS:
+ *        ProcessHandle = Points to the process that allocated the virtual memory
+ *        BaseAddress = Points to the memory address
+ *        NumberOfBytesToFlush = Limits the range to flush,
+ *        NumberOfBytesFlushed = Actual number of bytes flushed
+ * RETURNS: Status 
+ * REMARKS:
+ *       Check return status on STATUS_NOT_MAPPED_DATA 
+ */
+NTSTATUS
+STDCALL
+NtFlushVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG NumberOfBytesToFlush,
+       OUT PULONG NumberOfBytesFlushed OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwFlushVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG NumberOfBytesToFlush,
+       OUT PULONG NumberOfBytesFlushed OPTIONAL
+       );
+
+/*
+ * FUNCTION: Retrieves the uptime of the system
+ * ARGUMENTS:
+ *        UpTime = Number of clock ticks since boot.
+ * RETURNS: Status 
+ */
+NTSTATUS
+STDCALL 
+NtGetTickCount(
+       PULONG UpTime
+       );
+
+NTSTATUS
+STDCALL 
+ZwGetTickCount(
+       PULONG UpTime
+       );
+
+/*
+ * FUNCTION: Loads a registry key.
+ * ARGUMENTS:
+ *       KeyHandle = Handle to the registry key
+ *       ObjectAttributes = ???
+ * REMARK:
+ *      This procedure maps to the win32 procedure RegLoadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL 
+NtLoadKey(
+       PHANDLE KeyHandle,
+       POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+NTSTATUS
+STDCALL 
+ZwLoadKey(
+       PHANDLE KeyHandle,
+       POBJECT_ATTRIBUTES ObjectAttributes
+       );
+
+/*
+ * FUNCTION: Locks a range of virtual memory. 
+ * ARGUMENTS: 
+ *       ProcessHandle = Handle to the process
+ *       BaseAddress =  Lower boundary of the range of bytes to lock. 
+ *       NumberOfBytesLock = Offset to the upper boundary.
+ *       NumberOfBytesLocked (OUT) = Number of bytes actually locked.
+ * REMARK:
+       This procedure maps to the win32 procedure VirtualLock 
+ * RETURNS: Status [STATUS_SUCCESS | STATUS_WAS_LOCKED ]
+ */    
+NTSTATUS
+STDCALL 
+NtLockVirtualMemory(
+       HANDLE ProcessHandle,
+       PVOID BaseAddress,
+       ULONG NumberOfBytesToLock,
+       PULONG NumberOfBytesLocked
+       );
+
+NTSTATUS
+STDCALL 
+ZwLockVirtualMemory(
+       HANDLE ProcessHandle,
+       PVOID BaseAddress,
+       ULONG NumberOfBytesToLock,
+       PULONG NumberOfBytesLocked
+       );
+
+NTSTATUS
+STDCALL
+NtOpenObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,       
+       IN PVOID HandleId,      
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN HANDLE ClientToken,  
+       IN ULONG DesiredAccess, 
+       IN ULONG GrantedAccess, 
+       IN PPRIVILEGE_SET Privileges,
+       IN BOOLEAN ObjectCreation,      
+       IN BOOLEAN AccessGranted,       
+       OUT PBOOLEAN GenerateOnClose    
+       );
+
+NTSTATUS
+STDCALL
+ZwOpenObjectAuditAlarm(
+       IN PUNICODE_STRING SubsystemName,       
+       IN PVOID HandleId,      
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN HANDLE ClientToken,  
+       IN ULONG DesiredAccess, 
+       IN ULONG GrantedAccess, 
+       IN PPRIVILEGE_SET Privileges,
+       IN BOOLEAN ObjectCreation,      
+       IN BOOLEAN AccessGranted,       
+       OUT PBOOLEAN GenerateOnClose    
+       );
+
+/*
+ * FUNCTION: Set the access protection of a range of virtual memory
+ * ARGUMENTS:
+ *        ProcessHandle = Handle to process owning the virtual address space
+ *        BaseAddress   = Start address
+ *        NumberOfBytesToProtect = Delimits the range of virtual memory
+ *                             for which the new access protection holds
+ *        NewAccessProtection = The new access proctection for the pages
+ *        OldAccessProtection = Caller should supply storage for the old 
+ *                             access protection
+ *
+ * REMARKS:
+ *      The function maps to the win32 VirtualProtectEx
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtProtectVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG NumberOfBytesToProtect,
+       IN ULONG NewAccessProtection,
+       OUT PULONG OldAccessProtection
+       );
+
+NTSTATUS
+STDCALL
+ZwProtectVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG NumberOfBytesToProtect,
+       IN ULONG NewAccessProtection,
+       OUT PULONG OldAccessProtection
+       );
+
+NTSTATUS
+STDCALL
+NtQueryInformationAtom(
+       IN      RTL_ATOM                Atom,
+       IN      ATOM_INFORMATION_CLASS  AtomInformationClass,
+       OUT     PVOID                   AtomInformation,
+       IN      ULONG                   AtomInformationLength,
+       OUT     PULONG                  ReturnLength OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationAtom(
+       IN      RTL_ATOM                Atom,
+       IN      ATOM_INFORMATION_CLASS  AtomInformationClass,
+       OUT     PVOID                   AtomInformation,
+       IN      ULONG                   AtomInformationLength,
+       OUT     PULONG                  ReturnLength OPTIONAL
+       );
+
+/*
+ * FUNCTION: Query information about the content of a directory object
+ * ARGUMENTS:
+       DirObjInformation =   Buffer must be large enough to hold the name strings too
+        GetNextIndex = If TRUE :return the index of the next object in this directory in ObjectIndex
+                      If FALSE:  return the number of objects in this directory in ObjectIndex
+        IgnoreInputIndex= If TRUE:  ignore input value of ObjectIndex  always start at index 0
+                         If FALSE use input value of ObjectIndex
+       ObjectIndex =   zero based index of object in the directory  depends on GetNextIndex and IgnoreInputIndex
+        DataWritten  = Actual size of the ObjectIndex ???
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryDirectoryObject(
+       IN      HANDLE                  DirObjHandle,
+       OUT     POBJDIR_INFORMATION     DirObjInformation,
+       IN      ULONG                   BufferLength,
+       IN      BOOLEAN                 GetNextIndex,
+       IN      BOOLEAN                 IgnoreInputIndex,
+       IN OUT  PULONG                  ObjectIndex,
+       OUT     PULONG                  DataWritten OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryDirectoryObject(
+       IN HANDLE DirObjHandle,
+       OUT POBJDIR_INFORMATION DirObjInformation,
+       IN ULONG                BufferLength,
+       IN BOOLEAN              GetNextIndex,
+       IN BOOLEAN              IgnoreInputIndex,
+       IN OUT PULONG           ObjectIndex,
+       OUT PULONG              DataWritten OPTIONAL
+       );
+
+/*
+ * FUNCTION: Queries the information of a process object.
+ * ARGUMENTS: 
+ *        ProcessHandle = Handle to the process object
+ *        ProcessInformation = Index to a certain information structure
+
+               ProcessBasicInformation          PROCESS_BASIC_INFORMATION
+               ProcessQuotaLimits               QUOTA_LIMITS
+               ProcessIoCounters                IO_COUNTERS
+               ProcessVmCounters                VM_COUNTERS
+               ProcessTimes                     KERNEL_USER_TIMES
+               ProcessBasePriority              KPRIORITY
+               ProcessRaisePriority             KPRIORITY
+               ProcessDebugPort                 HANDLE
+               ProcessExceptionPort             HANDLE 
+               ProcessAccessToken               PROCESS_ACCESS_TOKEN
+               ProcessLdtInformation            LDT_ENTRY ??
+               ProcessLdtSize                   ULONG
+               ProcessDefaultHardErrorMode      ULONG
+               ProcessIoPortHandlers            // kernel mode only
+               ProcessPooledUsageAndLimits      POOLED_USAGE_AND_LIMITS
+               ProcessWorkingSetWatch           PROCESS_WS_WATCH_INFORMATION           
+               ProcessUserModeIOPL              (I/O Privilege Level)
+               ProcessEnableAlignmentFaultFixup BOOLEAN        
+               ProcessPriorityClass             ULONG
+               ProcessWx86Information           ULONG  
+               ProcessHandleCount               ULONG
+               ProcessAffinityMask              ULONG  
+               ProcessPooledQuotaLimits         QUOTA_LIMITS
+               MaxProcessInfoClass              
+
+ *        ProcessInformation = Caller supplies storage for the process information structure
+ *       ProcessInformationLength = Size of the process information structure
+ *        ReturnLength  = Actual number of bytes written
+               
+ * REMARK:
+ *       This procedure maps to the win32 GetProcessTimes, GetProcessVersion,
+          GetProcessWorkingSetSize, GetProcessPriorityBoost, GetProcessAffinityMask, GetPriorityClass,
+          GetProcessShutdownParameters  functions. 
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtQueryInformationProcess(
+       IN HANDLE ProcessHandle,
+       IN CINT ProcessInformationClass,
+       OUT PVOID ProcessInformation,
+       IN ULONG ProcessInformationLength,
+       OUT PULONG ReturnLength 
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationProcess(
+       IN HANDLE ProcessHandle,
+       IN CINT ProcessInformationClass,
+       OUT PVOID ProcessInformation,
+       IN ULONG ProcessInformationLength,
+       OUT PULONG ReturnLength 
+       );
+
+/*
+ * FUNCTION: Query the interval and the clocksource for profiling
+ * ARGUMENTS:
+       Interval =   
+        ClockSource = 
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryIntervalProfile(
+       OUT PULONG Interval,
+       OUT KPROFILE_SOURCE ClockSource
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryIntervalProfile(
+       OUT PULONG Interval,
+       OUT KPROFILE_SOURCE ClockSource
+       );
+
+/*
+ * FUNCTION: Queries the information of a  object.
+ * ARGUMENTS: 
+       ObjectHandle = Handle to a object
+       ObjectInformationClass = Index to a certain information structure
+
+       ObjectBasicInformation          
+       ObjectTypeInformation           OBJECT_TYPE_INFORMATION 
+       ObjectNameInformation           OBJECT_NAME_INFORMATION
+       ObjectDataInformation           OBJECT_DATA_INFORMATION
+
+       ObjectInformation = Caller supplies storage for resulting information
+       Length = Size of the supplied storage 
+       ResultLength = Bytes written
+ */
+
+NTSTATUS
+STDCALL
+NtQueryObject(
+       IN HANDLE ObjectHandle,
+       IN CINT ObjectInformationClass,
+       OUT PVOID ObjectInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryObject(
+       IN HANDLE ObjectHandle,
+       IN CINT ObjectInformationClass,
+       OUT PVOID ObjectInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+NtQuerySecurityObject(
+       IN HANDLE Object,
+       IN CINT SecurityObjectInformationClass,
+       OUT PVOID SecurityObjectInformation,
+       IN ULONG Length,
+       OUT PULONG ReturnLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySecurityObject(
+       IN HANDLE Object,
+       IN CINT SecurityObjectInformationClass,
+       OUT PVOID SecurityObjectInformation,
+       IN ULONG Length,
+       OUT PULONG ReturnLength
+       );
+
+/*
+ * FUNCTION: Queries the virtual memory information.
+ * ARGUMENTS: 
+         ProcessHandle = Process owning the virtual address space
+         BaseAddress = Points to the page where the information is queried for. 
+ *        VirtualMemoryInformationClass = Index to a certain information structure
+
+         MemoryBasicInformation                MEMORY_BASIC_INFORMATION
+
+ *       VirtualMemoryInformation = caller supplies storage for the information structure
+ *        Length = size of the structure
+         ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtQueryVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID Address,
+       IN IN CINT VirtualMemoryInformationClass,
+       OUT PVOID VirtualMemoryInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQueryVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID Address,
+       IN IN CINT VirtualMemoryInformationClass,
+       OUT PVOID VirtualMemoryInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+/*
+ * FUNCTION: Raises a hard error (stops the system)
+ * ARGUMENTS:
+ *       Status = Status code of the hard error
+ *       Unknown2 = ??
+ *       Unknown3 = ??
+ *       Unknown4 = ??
+ *       Unknown5 = ??
+ *       Unknown6 = ??
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS
+STDCALL
+NtRaiseHardError(
+       IN NTSTATUS Status,
+       ULONG Unknown2,
+       ULONG Unknown3,
+       ULONG Unknown4,
+       ULONG Unknown5,
+       ULONG Unknown6
+       );
+
+NTSTATUS
+STDCALL
+ZwRaiseHardError(
+       IN NTSTATUS Status,
+       ULONG Unknown2,
+       ULONG Unknown3,
+       ULONG Unknown4,
+       ULONG Unknown5,
+       ULONG Unknown6
+       );
+
+/*
+ * FUNCTION: Sets the information of a registry key.
+ * ARGUMENTS: 
+ *       KeyHandle = Handle to the registry key
+ *       KeyInformationClass =  Index to the a certain information structure.
+                       Can be one of the following values:
+
+ *      KeyWriteTimeInformation  KEY_WRITE_TIME_INFORMATION
+
+        KeyInformation = Storage for the new information
+ *       KeyInformationLength = Size of the information strucure
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetInformationKey(
+       IN HANDLE KeyHandle,
+       IN CINT KeyInformationClass,
+       IN PVOID KeyInformation,
+       IN ULONG KeyInformationLength
+       );
+
+NTSTATUS
+STDCALL
+ZwSetInformationKey(
+       IN HANDLE KeyHandle,
+       IN CINT KeyInformationClass,
+       IN PVOID KeyInformation,
+       IN ULONG KeyInformationLength
+       );
+
+/*
+ * FUNCTION: Changes a set of object specific parameters
+ * ARGUMENTS: 
+ *      ObjectHandle = 
+ *     ObjectInformationClass = Index to the set of parameters to change. 
+
+                       
+       ObjectBasicInformation          
+       ObjectTypeInformation           OBJECT_TYPE_INFORMATION 
+       ObjectAllInformation            
+       ObjectDataInformation           OBJECT_DATA_INFORMATION
+       ObjectNameInformation           OBJECT_NAME_INFORMATION 
+
+
+ *      ObjectInformation = Caller supplies storage for parameters to set.
+ *      Length = Size of the storage supplied
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationObject(
+       IN HANDLE ObjectHandle,
+       IN CINT ObjectInformationClass,
+       IN PVOID ObjectInformation,
+       IN ULONG Length 
+       );
+
+NTSTATUS
+STDCALL
+ZwSetInformationObject(
+       IN HANDLE ObjectHandle,
+       IN CINT ObjectInformationClass,
+       IN PVOID ObjectInformation,
+       IN ULONG Length 
+       );
+
+/*
+ * FUNCTION: Changes a set of process specific parameters
+ * ARGUMENTS: 
+ *      ProcessHandle = Handle to the process
+ *     ProcessInformationClass = Index to a information structure. 
+ *
+ *     ProcessBasicInformation                 PROCESS_BASIC_INFORMATION
+ *     ProcessQuotaLimits                      QUOTA_LIMITS
+ *     ProcessBasePriority                     KPRIORITY
+ *     ProcessRaisePriority                    KPRIORITY 
+ *     ProcessDebugPort                        HANDLE
+ *     ProcessExceptionPort                    HANDLE  
+ *     ProcessAccessToken                      PROCESS_ACCESS_TOKEN    
+ *     ProcessDefaultHardErrorMode             ULONG
+ *     ProcessPriorityClass                    ULONG
+ *     ProcessAffinityMask                     KAFFINITY //??
+ *
+ *      ProcessInformation = Caller supplies storage for information to set.
+ *      ProcessInformationLength = Size of the information structure
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationProcess(
+       IN HANDLE ProcessHandle,
+       IN CINT ProcessInformationClass,
+       IN PVOID ProcessInformation,
+       IN ULONG ProcessInformationLength
+       );
+
+NTSTATUS
+STDCALL
+ZwSetInformationProcess(
+       IN HANDLE ProcessHandle,
+       IN CINT ProcessInformationClass,
+       IN PVOID ProcessInformation,
+       IN ULONG ProcessInformationLength
+       );
+
+/*
+ * FUNCTION: Sets the characteristics of a timer
+ * ARGUMENTS: 
+ *      TimerHandle = Handle to the timer
+ *     DueTime = Time before the timer becomes signalled for the first time.
+ *      TimerApcRoutine = Completion routine can be called on time completion
+ *      TimerContext = Argument to the completion routine
+ *      Resume = Specifies if the timer should repeated after completing one cycle
+ *      Period = Cycle of the timer
+ * REMARKS: This routine maps to the win32 SetWaitableTimer.
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetTimer(
+       IN HANDLE TimerHandle,
+       IN PLARGE_INTEGER DueTime,
+       IN PTIMERAPCROUTINE TimerApcRoutine,
+       IN PVOID TimerContext,
+       IN BOOL WakeTimer,
+       IN ULONG Period OPTIONAL,
+       OUT PBOOLEAN PreviousState OPTIONAL
+       );
+
+NTSTATUS
+STDCALL
+ZwSetTimer(
+       IN HANDLE TimerHandle,
+       IN PLARGE_INTEGER DueTime,
+       IN PTIMERAPCROUTINE TimerApcRoutine,
+       IN PVOID TimerContext,
+       IN BOOL WakeTimer,
+       IN ULONG Period OPTIONAL,
+       OUT PBOOLEAN PreviousState OPTIONAL
+       );
+
+/*
+ * FUNCTION: Unloads a registry key.
+ * ARGUMENTS:
+ *       KeyHandle = Handle to the registry key
+ * REMARK:
+ *       This procedure maps to the win32 procedure RegUnloadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtUnloadKey(
+       HANDLE KeyHandle
+       );
+
+NTSTATUS
+STDCALL
+ZwUnloadKey(
+       HANDLE KeyHandle
+       );
+
+/*
+ * FUNCTION: Unlocks a range of virtual memory. 
+ * ARGUMENTS: 
+ *       ProcessHandle = Handle to the process
+ *       BaseAddress =   Lower boundary of the range of bytes to unlock. 
+ *       NumberOfBytesToUnlock = Offset to the upper boundary to unlock.
+ *       NumberOfBytesUnlocked (OUT) = Number of bytes actually unlocked.
+ * REMARK:
+       This procedure maps to the win32 procedure VirtualUnlock 
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PAGE_WAS_ULOCKED ]
+ */    
+NTSTATUS 
+STDCALL
+NtUnlockVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG  NumberOfBytesToUnlock,
+       OUT PULONG NumberOfBytesUnlocked OPTIONAL
+       );
+
+NTSTATUS 
+STDCALL
+ZwUnlockVirtualMemory(
+       IN HANDLE ProcessHandle,
+       IN PVOID BaseAddress,
+       IN ULONG  NumberOfBytesToUnlock,
+       OUT PULONG NumberOfBytesUnlocked OPTIONAL
+       );
+
+/*
+ * FUNCTION: Waits for multiple objects to become signalled.
+ * ARGUMENTS: 
+ *       Count = The number of objects
+ *       Object = The array of object handles
+ *       WaitType = Can be one of the values UserMode or KernelMode
+ *       Alertable = If true the wait is alertable.
+ *       Time = The maximum wait time.
+ * REMARKS:
+ *       This function maps to the win32 WaitForMultipleObjectEx.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitForMultipleObjects (
+       IN ULONG Count,
+       IN HANDLE Object[],
+       IN CINT WaitType,
+       IN BOOLEAN Alertable,
+       IN PLARGE_INTEGER Time
+       );
+
+NTSTATUS
+STDCALL
+ZwWaitForMultipleObjects (
+       IN ULONG Count,
+       IN HANDLE Object[],
+       IN CINT WaitType,
+       IN BOOLEAN Alertable,
+       IN PLARGE_INTEGER Time
+       );
+
+/*
+ * FUNCTION: Creates a profile
+ * ARGUMENTS:
+ *        ProfileHandle (OUT) = Caller supplied storage for the resulting handle
+ *        ObjectAttribute = Initialized attributes for the object
+ *        ImageBase = Start address of executable image
+ *        ImageSize = Size of the image
+ *        Granularity = Bucket size
+ *        Buffer =  Caller supplies buffer for profiling info
+ *        ProfilingSize = Buffer size
+ *        ClockSource = Specify 0 / FALSE ??
+ *        ProcessorMask = A value of -1 indicates disables  per processor profiling,
+                         otherwise bit set for the processor to profile.
+ * REMARKS:
+ *        This function maps to the win32 CreateProcess. 
+ * RETURNS: Status
+ */
+
+NTSTATUS 
+STDCALL
+NtCreateProfile(OUT PHANDLE ProfileHandle, 
+               IN HANDLE ProcessHandle,
+               IN PVOID ImageBase, 
+               IN ULONG ImageSize, 
+               IN ULONG Granularity,
+               OUT PULONG Buffer, 
+               IN ULONG ProfilingSize,
+               IN KPROFILE_SOURCE Source,
+               IN ULONG ProcessorMask);
+
+NTSTATUS 
+STDCALL
+ZwCreateProfile(
+       OUT PHANDLE ProfileHandle, 
+       IN POBJECT_ATTRIBUTES ObjectAttributes,
+       IN ULONG ImageBase, 
+       IN ULONG ImageSize, 
+       IN ULONG Granularity,
+       OUT PVOID Buffer, 
+       IN ULONG ProfilingSize,
+       IN ULONG ClockSource,
+       IN ULONG ProcessorMask
+       );
+
+/*
+ * FUNCTION: Delays the execution of the calling thread.
+ * ARGUMENTS:
+ *        Alertable = If TRUE the thread is alertable during is wait period
+ *        Interval  = Specifies the interval to wait.      
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDelayExecution(
+       IN ULONG Alertable,
+       IN TIME *Interval
+       );
+
+NTSTATUS
+STDCALL
+ZwDelayExecution(
+       IN BOOLEAN Alertable,
+       IN TIME *Interval
+       );
+
+/*
+ * FUNCTION: Extends a section
+ * ARGUMENTS:
+ *       SectionHandle = Handle to the section
+ *      NewMaximumSize = Adjusted size
+ * RETURNS: Status 
+ */
+NTSTATUS
+STDCALL
+NtExtendSection(
+       IN HANDLE SectionHandle,
+       IN ULONG NewMaximumSize
+       );
+
+NTSTATUS
+STDCALL
+ZwExtendSection(
+       IN HANDLE SectionHandle,
+       IN ULONG NewMaximumSize
+       );
+
+/*
+ * FUNCTION: Queries the information of a section object.
+ * ARGUMENTS: 
+ *        SectionHandle = Handle to the section link object
+ *       SectionInformationClass = Index to a certain information structure
+ *        SectionInformation (OUT)= Caller supplies storage for resulting information
+ *        Length =  Size of the supplied storage 
+ *        ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySection(
+       IN HANDLE SectionHandle,
+       IN CINT SectionInformationClass,
+       OUT PVOID SectionInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+NTSTATUS
+STDCALL
+ZwQuerySection(
+       IN HANDLE SectionHandle,
+       IN CINT SectionInformationClass,
+       OUT PVOID SectionInformation,
+       IN ULONG Length,
+       OUT PULONG ResultLength
+       );
+
+typedef struct _SECTION_IMAGE_INFORMATION
+{
+  PVOID EntryPoint;
+  ULONG Unknown1;
+  ULONG StackReserve;
+  ULONG StackCommit;
+  ULONG Subsystem;
+  USHORT MinorSubsystemVersion;
+  USHORT MajorSubsystemVersion;
+  ULONG Unknown2;
+  ULONG Characteristics;
+  USHORT ImageNumber;
+  BOOLEAN Executable;
+  UCHAR Unknown3;
+  ULONG Unknown4[3];
+} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
+
+#endif /* !__USE_W32API */
+
+#endif /* __DDK_ZW_H */
diff --git a/include/ntos/zwtypes.h b/include/ntos/zwtypes.h
new file mode 100755 (executable)
index 0000000..cc1fe02
--- /dev/null
@@ -0,0 +1,1623 @@
+#ifndef __INCLUDE_DDK_ZWTYPES_H
+#define __INCLUDE_DDK_ZWTYPES_H
+
+#ifndef __USE_W32API
+
+typedef enum _DEBUG_CONTROL_CODE
+{
+  DebugGetTraceInformation = 1,
+  DebugSetInternalBreakpoint,
+  DebugSetSpecialCalls,
+  DebugClearSpecialCalls,
+  DebugQuerySpecialCalls,
+  DebugDbgBreakPoint,
+  DebugDbgLoadSymbols
+} DEBUG_CONTROL_CODE;
+
+typedef enum _KPROFILE_SOURCE
+{
+  ProfileTime
+} KPROFILE_SOURCE;
+
+// file disposition values
+
+#define FILE_SUPERSEDE                  0x0000
+#define FILE_OPEN                       0x0001
+#define FILE_CREATE                     0x0002
+#define FILE_OPEN_IF                    0x0003
+#define FILE_OVERWRITE                  0x0004
+#define FILE_OVERWRITE_IF               0x0005
+#define FILE_MAXIMUM_DISPOSITION        0x0005
+
+// job query / set information class
+
+typedef enum _JOBOBJECTINFOCLASS {               // Q S
+    JobObjectBasicAccountingInformation = 1,     // Y N
+    JobObjectBasicLimitInformation,              // Y Y
+    JobObjectBasicProcessIdList,                 // Y N
+    JobObjectBasicUIRestrictions,                // Y Y
+    JobObjectSecurityLimitInformation,           // Y Y
+    JobObjectEndOfJobTimeInformation,            // N Y
+    JobObjectAssociateCompletionPortInformation, // N Y
+    JobObjectBasicAndIoAccountingInformation,    // Y N
+    JobObjectExtendedLimitInformation,           // Y Y
+} JOBOBJECTINFOCLASS;
+
+// system information
+// {Nt|Zw}{Query|Set}SystemInformation
+// (GN means Gary Nebbet in "NT/W2K Native API Reference")
+
+typedef
+enum _SYSTEM_INFORMATION_CLASS
+{
+       SystemInformationClassMin               = 0,
+       SystemBasicInformation                  = 0,    /* Q */
+       
+       SystemProcessorInformation              = 1,    /* Q */
+       
+       SystemPerformanceInformation            = 2,    /* Q */
+       
+       SystemTimeOfDayInformation              = 3,    /* Q */
+       
+       SystemPathInformation                   = 4,    /* Q (checked build only) */
+       SystemNotImplemented1                   = 4,    /* Q (GN) */
+       
+       SystemProcessInformation                = 5,    /* Q */
+       SystemProcessesAndThreadsInformation    = 5,    /* Q (GN) */
+       
+       SystemCallCountInfoInformation          = 6,    /* Q */
+       SystemCallCounts                        = 6,    /* Q (GN) */
+       
+       SystemDeviceInformation                 = 7,    /* Q */
+// It conflicts with symbol in ntoskrnl/io/resource.c
+//     SystemConfigurationInformation          = 7,    /* Q (GN) */
+       
+       SystemProcessorPerformanceInformation   = 8,    /* Q */
+       SystemProcessorTimes                    = 8,    /* Q (GN) */
+       
+       SystemFlagsInformation                  = 9,    /* QS */
+       SystemGlobalFlag                        = 9,    /* QS (GN) */
+       
+       SystemCallTimeInformation               = 10,
+       SystemNotImplemented2                   = 10,   /* (GN) */
+       
+       SystemModuleInformation                 = 11,   /* Q */
+       
+       SystemLocksInformation                  = 12,   /* Q */
+       SystemLockInformation                   = 12,   /* Q (GN) */
+       
+       SystemStackTraceInformation             = 13,
+       SystemNotImplemented3                   = 13,   /* Q (GN) */
+       
+       SystemPagedPoolInformation              = 14,
+       SystemNotImplemented4                   = 14,   /* Q (GN) */
+       
+       SystemNonPagedPoolInformation           = 15,
+       SystemNotImplemented5                   = 15,   /* Q (GN) */
+       
+       SystemHandleInformation                 = 16,   /* Q */
+       
+       SystemObjectInformation                 = 17,   /* Q */
+       
+       SystemPageFileInformation               = 18,   /* Q */
+       SystemPagefileInformation               = 18,   /* Q (GN) */
+       
+       SystemVdmInstemulInformation            = 19,   /* Q */
+       SystemInstructionEmulationCounts        = 19,   /* Q (GN) */
+       
+       SystemVdmBopInformation                 = 20,
+       SystemInvalidInfoClass1                 = 20,   /* (GN) */
+       
+       SystemFileCacheInformation              = 21,   /* QS */
+       SystemCacheInformation                  = 21,   /* QS (GN) */
+       
+       SystemPoolTagInformation                = 22,   /* Q (checked build only) */
+       
+       SystemInterruptInformation              = 23,   /* Q */
+       SystemProcessorStatistics               = 23,   /* Q (GN) */
+       
+       SystemDpcBehaviourInformation           = 24,   /* QS */
+       SystemDpcInformation                    = 24,   /* QS (GN) */
+       
+       SystemFullMemoryInformation             = 25,
+       SystemNotImplemented6                   = 25,   /* (GN) */
+       
+       SystemLoadImage                         = 26,   /* S (callable) (GN) */
+       
+       SystemUnloadImage                       = 27,   /* S (callable) (GN) */
+       
+       SystemTimeAdjustmentInformation         = 28,   /* QS */
+       SystemTimeAdjustment                    = 28,   /* QS (GN) */
+       
+       SystemSummaryMemoryInformation          = 29,
+       SystemNotImplemented7                   = 29,   /* (GN) */
+       
+       SystemNextEventIdInformation            = 30,
+       SystemNotImplemented8                   = 30,   /* (GN) */
+       
+       SystemEventIdsInformation               = 31,
+       SystemNotImplemented9                   = 31,   /* (GN) */
+       
+       SystemCrashDumpInformation              = 32,   /* Q */
+       
+       SystemExceptionInformation              = 33,   /* Q */
+       
+       SystemCrashDumpStateInformation         = 34,   /* Q */
+       
+       SystemKernelDebuggerInformation         = 35,   /* Q */
+       
+       SystemContextSwitchInformation          = 36,   /* Q */
+       
+       SystemRegistryQuotaInformation          = 37,   /* QS */
+       
+       SystemLoadAndCallImage                  = 38,   /* S (GN) */
+       
+       SystemPrioritySeparation                = 39,   /* S */
+       
+       SystemPlugPlayBusInformation            = 40,
+       SystemNotImplemented10                  = 40,   /* Q (GN) */
+       
+       SystemDockInformation                   = 41,
+       SystemNotImplemented11                  = 41,   /* Q (GN) */
+       
+       SystemPowerInformation                  = 42,
+       SystemInvalidInfoClass2                 = 42,   /* (GN) */
+       
+       SystemProcessorSpeedInformation         = 43,
+       SystemInvalidInfoClass3                 = 43,   /* (GN) */
+       
+       SystemCurrentTimeZoneInformation        = 44,   /* QS */
+       SystemTimeZoneInformation               = 44,   /* QS (GN) */
+       
+       SystemLookasideInformation              = 45,   /* Q */
+       
+       SystemSetTimeSlipEvent                  = 46,   /* S (GN) */
+       
+       SystemCreateSession                     = 47,   /* S (GN) */
+       
+       SystemDeleteSession                     = 48,   /* S (GN) */
+       
+       SystemInvalidInfoClass4                 = 49,   /* (GN) */
+       
+       SystemRangeStartInformation             = 50,   /* Q (GN) */
+       
+       SystemVerifierInformation               = 51,   /* QS (GN) */
+       
+       SystemAddVerifier                       = 52,   /* S (GN) */
+       
+       SystemSessionProcessesInformation       = 53,   /* Q (GN) */
+       SystemInformationClassMax
+
+} SYSTEM_INFORMATION_CLASS;
+
+// SystemBasicInformation (0)
+typedef
+struct _SYSTEM_BASIC_INFORMATION
+{
+       ULONG           Reserved;
+       ULONG           TimerResolution;
+       ULONG           PageSize;
+       ULONG           NumberOfPhysicalPages;
+       ULONG           LowestPhysicalPageNumber;
+       ULONG           HighestPhysicalPageNumber;
+       ULONG           AllocationGranularity;
+       ULONG           MinimumUserModeAddress;
+       ULONG           MaximumUserModeAddress;
+       KAFFINITY       ActiveProcessorsAffinityMask;
+       CCHAR           NumberOfProcessors;
+} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
+
+// SystemProcessorInformation (1)
+typedef
+struct _SYSTEM_PROCESSOR_INFORMATION
+{
+       USHORT  ProcessorArchitecture;
+       USHORT  ProcessorLevel;
+       USHORT  ProcessorRevision;
+       USHORT  Reserved;
+       ULONG   ProcessorFeatureBits;
+} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION;
+
+// SystemPerformanceInfo (2)
+typedef
+struct _SYSTEM_PERFORMANCE_INFORMATION
+{
+       LARGE_INTEGER   IdleProcessorTime;
+       LARGE_INTEGER   IoReadTransferCount;
+       LARGE_INTEGER   IoWriteTransferCount;
+       LARGE_INTEGER   IoOtherTransferCount;
+       ULONG           IoReadOperationCount;
+       ULONG           IoWriteOperationCount;
+       ULONG           IoOtherOperationCount;
+       ULONG           AvailablePages;
+       ULONG           CommitedPages;
+       ULONG           CommitLimit;
+       ULONG           PeakCommitment;
+       ULONG           PageFaultCount;
+       ULONG           CopyOnWriteCount;
+       ULONG           TransitionCount;
+       ULONG           CacheTransitionCount;
+       ULONG           DemandZeroCount;
+       ULONG           PageReadCount;
+       ULONG           PageReadIoCount;
+       ULONG           CacheReadCount;
+       ULONG           CacheIoCount;
+       ULONG           DirtyPagesWriteCount;
+       ULONG           DirtyWriteIoCount;
+       ULONG           MappedPagesWriteCount;
+       ULONG           MappedWriteIoCount;
+       ULONG           PagedPoolPages;
+       ULONG           NonPagedPoolPages;
+       ULONG           Unknown6;
+       ULONG           Unknown7;
+       ULONG           Unknown8;
+       ULONG           Unknown9;
+       ULONG           MmTotalSystemFreePtes;
+       ULONG           MmSystemCodepage;
+       ULONG           MmTotalSystemDriverPages;
+       ULONG           MmTotalSystemCodePages;
+       ULONG           Unknown10;
+       ULONG           Unknown11;
+       ULONG           Unknown12;
+       ULONG           MmSystemCachePage;
+       ULONG           MmPagedPoolPage;
+       ULONG           MmSystemDriverPage;
+       ULONG           CcFastReadNoWait;
+       ULONG           CcFastReadWait;
+       ULONG           CcFastReadResourceMiss;
+       ULONG           CcFastReadNotPossible;
+       ULONG           CcFastMdlReadNoWait;
+       ULONG           CcFastMdlReadWait;
+       ULONG           CcFastMdlReadResourceMiss;
+       ULONG           CcFastMdlReadNotPossible;
+       ULONG           CcMapDataNoWait;
+       ULONG           CcMapDataWait;
+       ULONG           CcMapDataNoWaitMiss;
+       ULONG           CcMapDataWaitMiss;
+       ULONG           CcPinMappedDataCount;
+       ULONG           CcPinReadNoWait;
+       ULONG           CcPinReadWait;
+       ULONG           CcPinReadNoWaitMiss;
+       ULONG           CcPinReadWaitMiss;
+       ULONG           CcCopyReadNoWait;
+       ULONG           CcCopyReadWait;
+       ULONG           CcCopyReadNoWaitMiss;
+       ULONG           CcCopyReadWaitMiss;
+       ULONG           CcMdlReadNoWait;
+       ULONG           CcMdlReadWait;
+       ULONG           CcMdlReadNoWaitMiss;
+       ULONG           CcMdlReadWaitMiss;
+       ULONG           CcReadaheadIos;
+       ULONG           CcLazyWriteIos;
+       ULONG           CcLazyWritePages;
+       ULONG           CcDataFlushes;
+       ULONG           CcDataPages;
+       ULONG           ContextSwitches;
+       ULONG           Unknown13;
+       ULONG           Unknown14;
+       ULONG           SystemCalls;
+
+} SYSTEM_PERFORMANCE_INFO, *PSYSTEM_PERFORMANCE_INFO;
+
+// SystemModuleInformation (11)
+typedef
+struct _SYSTEM_MODULE_ENTRY
+{
+       ULONG   Unknown1;
+       ULONG   Unknown2;
+       PVOID   BaseAddress;
+       ULONG   Size;
+       ULONG   Flags;
+       ULONG   EntryIndex;
+       USHORT  NameLength; /* Length of module name not including the path, this field contains valid value only for NTOSKRNL module*/
+       USHORT  PathLength; /* Length of 'directory path' part of modulename*/
+       CHAR    Name [256];
+} SYSTEM_MODULE_ENTRY, * PSYSTEM_MODULE_ENTRY;
+
+typedef
+struct _SYSTEM_MODULE_INFORMATION
+{
+       ULONG                   Count;
+       SYSTEM_MODULE_ENTRY     Module [1];
+} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
+
+// SystemHandleInformation (16)
+// (see ontypes.h)
+typedef
+struct _SYSTEM_HANDLE_ENTRY
+{
+       ULONG   OwnerPid;
+       BYTE    ObjectType;
+       BYTE    HandleFlags;
+       USHORT  HandleValue;
+       PVOID   ObjectPointer;
+       ULONG   AccessMask;
+       
+} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY;
+
+typedef
+struct _SYSTEM_HANDLE_INFORMATION
+{
+       ULONG                   Count;
+       SYSTEM_HANDLE_ENTRY     Handle [1];
+       
+} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
+
+// SystemObjectInformation (17)
+typedef
+struct _SYSTEM_OBJECT_TYPE_INFORMATION
+{
+       ULONG           NextEntryOffset;
+       ULONG           ObjectCount;
+       ULONG           HandleCount;
+       ULONG           TypeNumber;
+       ULONG           InvalidAttributes;
+       GENERIC_MAPPING GenericMapping;
+       ACCESS_MASK     ValidAccessMask;
+       POOL_TYPE       PoolType;
+       UCHAR           Unknown;
+       UNICODE_STRING  Name;
+       
+} SYSTEM_OBJECT_TYPE_INFORMATION, *PSYSTEM_OBJECT_TYPE_INFORMATION;
+
+typedef
+struct _SYSTEM_OBJECT_INFORMATION
+{
+       ULONG                   NextEntryOffset;
+       PVOID                   Object;
+       ULONG                   CreatorProcessId;
+       USHORT                  Unknown;
+       USHORT                  Flags;
+       ULONG                   PointerCount;
+       ULONG                   HandleCount;
+       ULONG                   PagedPoolUsage;
+       ULONG                   NonPagedPoolUsage;
+       ULONG                   ExclusiveProcessId;
+       PSECURITY_DESCRIPTOR    SecurityDescriptor;
+       UNICODE_STRING          Name;
+
+} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION;
+
+// SystemPageFileInformation (18)
+typedef
+struct _SYSTEM_PAGEFILE_INFORMATION
+{
+       ULONG           RelativeOffset;
+       ULONG           CurrentSizePages;
+       ULONG           TotalUsedPages;
+       ULONG           PeakUsedPages;
+       UNICODE_STRING  PagefileFileName;
+       
+} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION;
+
+// SystemCacheInformation (21)
+typedef
+struct _SYSTEM_CACHE_INFORMATION
+{
+       ULONG   CurrentSize;
+       ULONG   PeakSize;
+       ULONG   PageFaultCount;
+       ULONG   MinimumWorkingSet;
+       ULONG   MaximumWorkingSet;
+       ULONG   Unused[4];
+
+} SYSTEM_CACHE_INFORMATION;
+
+// SystemDpcInformation (24)
+typedef
+struct _SYSTEM_DPC_INFORMATION
+{
+       ULONG   Unused;
+       ULONG   KiMaximumDpcQueueDepth;
+       ULONG   KiMinimumDpcRate;
+       ULONG   KiAdjustDpcThreshold;
+       ULONG   KiIdealDpcRate;
+
+} SYSTEM_DPC_INFORMATION, *PSYSTEM_DPC_INFORMATION;
+
+// SystemLoadImage (26)
+typedef struct _SYSTEM_LOAD_IMAGE
+{
+  UNICODE_STRING ModuleName;
+  PVOID ModuleBase;
+  PVOID SectionPointer;
+  PVOID EntryPoint;
+  PVOID ExportDirectory;
+} SYSTEM_LOAD_IMAGE, *PSYSTEM_LOAD_IMAGE;
+
+// SystemUnloadImage (27)
+typedef struct _SYSTEM_UNLOAD_IMAGE
+{
+  PVOID ModuleBase;
+} SYSTEM_UNLOAD_IMAGE, *PSYSTEM_UNLOAD_IMAGE;
+
+// SystemTimeAdjustmentInformation (28)
+typedef
+struct _SYSTEM_QUERY_TIME_ADJUSTMENT
+{
+       ULONG   TimeAdjustment;
+       ULONG   MaximumIncrement;
+       BOOLEAN TimeSynchronization;
+
+} SYSTEM_QUERY_TIME_ADJUSTMENT, *PSYSTEM_QUERY_TIME_ADJUSTMENT;
+
+typedef
+struct _SYSTEM_SET_TIME_ADJUSTMENT
+{
+       ULONG   TimeAdjustment;
+       BOOLEAN TimeSynchronization;
+       
+} SYSTEM_TIME_ADJUSTMENT_INFO, *PSYSTEM_TIME_ADJUSTMENT_INFO;
+
+// atom information
+
+typedef enum _ATOM_INFORMATION_CLASS
+{
+   AtomBasicInformation                = 0,
+   AtomTableInformation                = 1,
+} ATOM_INFORMATION_CLASS;
+
+typedef struct _ATOM_BASIC_INFORMATION
+{
+   USHORT UsageCount;
+   USHORT Flags;
+   USHORT NameLength;
+   WCHAR Name[1];
+} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION;
+
+// SystemLoadAndCallImage(38)
+typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE
+{
+  UNICODE_STRING ModuleName;
+} SYSTEM_LOAD_AND_CALL_IMAGE, *PSYSTEM_LOAD_AND_CALL_IMAGE;
+
+// SystemTimeZoneInformation (44)
+typedef
+struct _SYSTEM_TIME_ZONE_INFORMATION
+{
+       LONG    Bias;
+       WCHAR   StandardName [32];
+       TIME    StandardDate;
+       LONG    StandardBias;
+       WCHAR   DaylightName [32];
+       TIME    DaylightDate;
+       LONG    DaylightBias;
+
+} SYSTEM_TIME_ZONE_INFORMATION, * PSYSTEM_TIME_ZONE_INFORMATION;
+
+// SystemLookasideInformation (45)
+typedef
+struct _SYSTEM_LOOKASIDE_INFORMATION
+{
+       USHORT          Depth;
+       USHORT          MaximumDepth;
+       ULONG           TotalAllocates;
+       ULONG           AllocatesMisses;
+       ULONG           TotalFrees;
+       ULONG           FreeMisses;
+       POOL_TYPE       Type;
+       ULONG           Tag;
+       ULONG           Size;
+       
+} SYSTEM_LOOKASIDE_INFORMATION, * PSYSTEM_LOOKASIDE_INFORMATION;
+
+// SystemSetTimeSlipEvent (46)
+typedef
+struct _SYSTEM_SET_TIME_SLIP_EVENT
+{
+       HANDLE  TimeSlipEvent; /* IN */
+
+} SYSTEM_SET_TIME_SLIP_EVENT, * PSYSTEM_SET_TIME_SLIP_EVENT;
+
+// SystemCreateSession (47)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_CREATE_SESSION
+{
+       ULONG   SessionId; /* OUT */
+
+} SYSTEM_CREATE_SESSION, * PSYSTEM_CREATE_SESSION;
+
+// SystemDeleteSession (48)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_DELETE_SESSION
+{
+       ULONG   SessionId; /* IN */
+
+} SYSTEM_DELETE_SESSION, * PSYSTEM_DELETE_SESSION;
+
+// SystemRangeStartInformation (50)
+typedef
+struct _SYSTEM_RANGE_START_INFORMATION
+{
+       PVOID   SystemRangeStart;
+
+} SYSTEM_RANGE_START_INFORMATION, * PSYSTEM_RANGE_START_INFORMATION;
+
+// SystemSessionProcessesInformation (53)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_SESSION_PROCESSES_INFORMATION
+{
+       ULONG   SessionId;
+       ULONG   BufferSize;
+       PVOID   Buffer; /* same format as in SystemProcessInformation */
+
+} SYSTEM_SESSION_PROCESSES_INFORMATION, * PSYSTEM_SESSION_PROCESSES_INFORMATION;
+
+// memory information
+
+typedef enum _MEMORY_INFORMATION_CLASS {
+ MemoryBasicInformation,
+ MemoryWorkingSetList,
+ MemorySectionName //,
+ //MemoryBasicVlmInformation //???
+} MEMORY_INFORMATION_CLASS;
+
+typedef struct _MEMORY_BASIC_INFORMATION { // Information Class 0
+ PVOID BaseAddress;
+ PVOID AllocationBase;
+ ULONG AllocationProtect;
+ ULONG RegionSize;
+ ULONG State;
+ ULONG Protect;
+ ULONG Type;
+} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
+
+typedef struct _MEMORY_WORKING_SET_LIST { // Information Class 1
+ ULONG NumberOfPages;
+ ULONG WorkingSetList[1];
+} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
+
+// Information Class 2
+#define _MEMORY_SECTION_NAME_STATIC(__bufsize__) \
+ { \
+ UNICODE_STRING SectionFileName; \
+ WCHAR          NameBuffer[(__bufsize__)]; \
+} 
+
+#define MEMORY_SECTION_NAME_STATIC(__bufsize__) \
+ struct _MEMORY_SECTION_NAME_STATIC((__bufsize__) 
+
+typedef struct _MEMORY_SECTION_NAME_STATIC(ANYSIZE_ARRAY)
+ MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME;
+
+// Information class 0
+typedef struct _PROCESS_BASIC_INFORMATION
+{
+       NTSTATUS ExitStatus;
+       PPEB PebBaseAddress;
+       KAFFINITY AffinityMask;
+       KPRIORITY BasePriority;
+       ULONG UniqueProcessId;
+       ULONG InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
+
+// Information class 1
+typedef struct _QUOTA_LIMITS
+{
+       ULONG PagedPoolLimit;
+       ULONG NonPagedPoolLimit;
+       ULONG MinimumWorkingSetSize;
+       ULONG MaximumWorkingSetSize;
+       ULONG PagefileLimit;
+       TIME TimeLimit;
+} QUOTA_LIMITS, *PQUOTA_LIMITS;
+
+// Information class 2
+typedef struct _IO_COUNTERS
+{
+       ULONG ReadOperationCount;
+       ULONG WriteOperationCount;
+       ULONG OtherOperationCount;
+       LARGE_INTEGER ReadTransferCount;
+       LARGE_INTEGER WriteTransferCount;
+       LARGE_INTEGER OtherTransferCount;
+} IO_COUNTERS, *PIO_COUNTERS;
+
+// Information class 3
+typedef struct _VM_COUNTERS_
+{
+       ULONG PeakVirtualSize;
+       ULONG VirtualSize;
+       ULONG PageFaultCount;
+       ULONG PeakWorkingSetSize;
+       ULONG WorkingSetSize;
+       ULONG QuotaPeakPagedPoolUsage;
+       ULONG QuotaPagedPoolUsage;
+       ULONG QuotaPeakNonPagedPoolUsage;
+       ULONG QuotaNonPagedPoolUsage;
+       ULONG PagefileUsage;
+       ULONG PeakPagefileUsage;
+} VM_COUNTERS, *PVM_COUNTERS;
+
+// Information class 4
+typedef struct _KERNEL_USER_TIMES
+{
+       TIME CreateTime;
+       TIME ExitTime;
+       TIME KernelTime;
+       TIME UserTime;
+} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES;
+
+// Information class 9
+typedef struct _PROCESS_ACCESS_TOKEN
+{
+       HANDLE Token;
+       HANDLE Thread;
+} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
+
+// Information class 14 
+typedef struct _POOLED_USAGE_AND_LIMITS_
+{
+       ULONG PeakPagedPoolUsage;
+       ULONG PagedPoolUsage;
+       ULONG PagedPoolLimit;
+       ULONG PeakNonPagedPoolUsage;
+       ULONG NonPagedPoolUsage;
+       ULONG NonPagedPoolLimit;
+       ULONG PeakPagefileUsage;
+       ULONG PagefileUsage;
+       ULONG PagefileLimit;
+} POOLED_USAGE_AND_LIMITS, *PPOOLED_USAGE_AND_LIMITS;
+
+// Information class 15
+typedef struct _PROCESS_WS_WATCH_INFORMATION
+{
+       PVOID FaultingPc;
+       PVOID FaultingVa;
+} PROCESS_WS_WATCH_INFORMATION, *PPROCESS_WS_WATCH_INFORMATION;
+
+// Information class 18
+typedef struct _PROCESS_PRIORITY_CLASS
+{
+       BOOLEAN Foreground;
+       UCHAR   PriorityClass;
+} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
+
+// Information class 23
+typedef struct _PROCESS_DEVICEMAP_INFORMATION
+{
+       union {
+               struct {
+                       HANDLE DirectoryHandle;
+               } Set;
+               struct {
+                       ULONG DriveMap;
+                       UCHAR DriveType[32];
+               } Query;
+       };
+} PROCESS_DEVICEMAP_INFORMATION, *pPROCESS_DEVICEMAP_INFORMATION;
+
+// Information class 24
+typedef struct _PROCESS_SESSION_INFORMATION
+{
+       ULONG SessionId;
+} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
+
+// thread information
+
+// incompatible with MS NT
+
+typedef struct _THREAD_BASIC_INFORMATION
+{
+  NTSTATUS  ExitStatus;
+  PVOID     TebBaseAddress;    // PNT_TIB (GN)
+  CLIENT_ID ClientId;
+  KAFFINITY AffinityMask;
+  KPRIORITY Priority;
+  KPRIORITY BasePriority;
+} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
+
+// object information
+
+typedef struct _OBJECT_NAME_INFORMATION
+{
+       UNICODE_STRING  Name;
+} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
+
+// file information
+
+typedef struct _FILE_BASIC_INFORMATION
+{
+       TIME CreationTime;
+       TIME LastAccessTime;
+       TIME LastWriteTime;
+       TIME ChangeTime;
+       ULONG FileAttributes;
+} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+
+typedef struct _FILE_STANDARD_INFORMATION
+{
+       LARGE_INTEGER AllocationSize;
+       LARGE_INTEGER EndOfFile;
+       ULONG NumberOfLinks;
+       BOOLEAN DeletePending;
+       BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+
+typedef struct _FILE_POSITION_INFORMATION
+{
+       LARGE_INTEGER CurrentByteOffset;
+} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
+
+typedef struct _FILE_ALIGNMENT_INFORMATION
+{
+       ULONG AlignmentRequirement;
+} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
+
+typedef struct _FILE_DISPOSITION_INFORMATION
+{
+       BOOLEAN DoDeleteFile;
+} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
+
+typedef struct _FILE_END_OF_FILE_INFORMATION
+{
+       LARGE_INTEGER EndOfFile;
+} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
+
+typedef struct _FILE_NETWORK_OPEN_INFORMATION
+{
+       TIME CreationTime;
+       TIME LastAccessTime;
+       TIME LastWriteTime;
+       TIME ChangeTime;
+       LARGE_INTEGER AllocationSize;
+       LARGE_INTEGER EndOfFile;
+       ULONG FileAttributes;
+} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
+
+typedef struct _FILE_FULL_EA_INFORMATION
+{
+       ULONG NextEntryOffset;
+       UCHAR Flags;
+       UCHAR EaNameLength;
+       USHORT EaValueLength;
+       CHAR  EaName[0];
+} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
+
+
+typedef struct _FILE_EA_INFORMATION {
+       ULONG EaSize;
+} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
+
+
+typedef struct _FILE_GET_EA_INFORMATION {
+       ULONG NextEntryOffset;
+       UCHAR EaNameLength;
+       CHAR EaName[0];
+} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
+
+typedef struct _FILE_STREAM_INFORMATION {
+       ULONG NextEntryOffset;
+       ULONG StreamNameLength;
+       LARGE_INTEGER StreamSize;
+       LARGE_INTEGER StreamAllocationSize;
+       WCHAR StreamName[0];
+} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
+
+typedef struct _FILE_ALLOCATION_INFORMATION {
+       LARGE_INTEGER AllocationSize;
+} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION;
+
+typedef struct _FILE_NAME_INFORMATION {
+       ULONG FileNameLength;
+       WCHAR FileName[0];
+} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+
+typedef struct _FILE_NAMES_INFORMATION 
+{
+       ULONG NextEntryOffset;
+       ULONG FileIndex;
+       ULONG FileNameLength;
+       WCHAR FileName[0];
+} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
+
+
+typedef struct _FILE_RENAME_INFORMATION {
+       BOOLEAN Replace;
+       HANDLE RootDir;
+       ULONG FileNameLength;
+       WCHAR FileName[0];
+} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
+
+
+typedef struct _FILE_INTERNAL_INFORMATION {
+       LARGE_INTEGER IndexNumber;
+} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
+
+typedef struct _FILE_ACCESS_INFORMATION {
+       ACCESS_MASK AccessFlags;
+} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
+
+
+typedef struct _FILE_MODE_INFORMATION {
+       ULONG Mode;
+} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
+
+
+typedef struct _FILE_PIPE_INFORMATION {
+       ULONG ReadMode;
+       ULONG CompletionMode;
+} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION;
+
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+       ULONG NamedPipeType;
+       ULONG NamedPipeConfiguration;
+       ULONG MaximumInstances;
+       ULONG CurrentInstances;
+       ULONG InboundQuota;
+       ULONG ReadDataAvailable;
+       ULONG OutboundQuota;
+       ULONG WriteQuotaAvailable;
+       ULONG NamedPipeState;
+       ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _FILE_PIPE_REMOTE_INFORMATION {
+       LARGE_INTEGER CollectDataTime;
+       ULONG MaximumCollectionCount;
+} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION;
+
+typedef struct _FILE_MAILSLOT_QUERY_INFORMATION {
+       ULONG MaxMessageSize;
+       ULONG Unknown; /* ?? */
+       ULONG NextSize;
+       ULONG MessageCount;
+       LARGE_INTEGER Timeout;
+} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION;
+
+typedef struct _FILE_MAILSLOT_SET_INFORMATION {
+       LARGE_INTEGER Timeout;
+} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION;
+
+typedef struct _FILE_COMPRESSION_INFORMATION {
+       LARGE_INTEGER CompressedFileSize;
+       USHORT CompressionFormat;
+       UCHAR CompressionUnitShift;
+       UCHAR ChunkShift;
+       UCHAR ClusterShift;
+       UCHAR Reserved[3];
+} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
+
+typedef struct _FILE_ALL_INFORMATION {
+       FILE_BASIC_INFORMATION BasicInformation;
+       FILE_STANDARD_INFORMATION StandardInformation;
+       FILE_INTERNAL_INFORMATION InternalInformation;
+       FILE_EA_INFORMATION EaInformation;
+       FILE_ACCESS_INFORMATION AccessInformation;
+       FILE_POSITION_INFORMATION PositionInformation;
+       FILE_MODE_INFORMATION ModeInformation;
+       FILE_ALIGNMENT_INFORMATION AlignmentInformation;
+       FILE_NAME_INFORMATION NameInformation;
+} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
+
+
+// file system information structures
+
+typedef struct _FILE_FS_DEVICE_INFORMATION {
+       DEVICE_TYPE DeviceType;
+       ULONG Characteristics;
+} FILE_FS_DEVICE_INFORMATION,  *PFILE_FS_DEVICE_INFORMATION;
+
+
+typedef struct _FILE_FS_VOLUME_INFORMATION {
+       TIME VolumeCreationTime;
+       ULONG VolumeSerialNumber;
+       ULONG VolumeLabelLength;
+       BOOLEAN SupportsObjects;
+       WCHAR VolumeLabel[0];
+} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
+
+typedef struct _FILE_FS_SIZE_INFORMATION {
+       LARGE_INTEGER TotalAllocationUnits;
+       LARGE_INTEGER AvailableAllocationUnits;
+       ULONG SectorsPerAllocationUnit;
+       ULONG BytesPerSector;
+} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
+
+typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
+       ULONG FileSystemAttributes;
+       LONG MaximumComponentNameLength;
+       ULONG FileSystemNameLength;
+       WCHAR FileSystemName[0];
+} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
+
+/*
+       FileSystemAttributes is one of the following values:
+
+       FILE_CASE_SENSITIVE_SEARCH      0x00000001
+        FILE_CASE_PRESERVED_NAMES       0x00000002
+        FILE_UNICODE_ON_DISK            0x00000004
+        FILE_PERSISTENT_ACLS            0x00000008
+        FILE_FILE_COMPRESSION           0x00000010
+        FILE_VOLUME_QUOTAS              0x00000020
+        FILE_VOLUME_IS_COMPRESSED       0x00008000
+*/
+typedef struct _FILE_FS_LABEL_INFORMATION {
+       ULONG VolumeLabelLength;
+       WCHAR VolumeLabel[0];
+} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION;
+
+// read file scatter / write file scatter
+//FIXME I am a win32 struct aswell
+
+typedef union _FILE_SEGMENT_ELEMENT {
+       PVOID Buffer;
+       ULONG Alignment;
+}FILE_SEGMENT_ELEMENT, *PFILE_SEGMENT_ELEMENT;
+
+typedef struct _FILE_DIRECTORY_INFORMATION {
+       ULONG   NextEntryOffset;
+       ULONG   FileIndex;
+       TIME CreationTime;
+       TIME LastAccessTime;
+       TIME LastWriteTime;
+       TIME ChangeTime;
+       LARGE_INTEGER EndOfFile;
+       LARGE_INTEGER AllocationSize;
+       ULONG FileAttributes;
+       ULONG FileNameLength;
+       WCHAR FileName[0];
+} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
+
+typedef struct _FILE_FULL_DIRECTORY_INFORMATION {
+       ULONG   NextEntryOffset;
+       ULONG   FileIndex;
+       TIME CreationTime;
+       TIME LastAccessTime;
+       TIME LastWriteTime;
+       TIME ChangeTime;
+       LARGE_INTEGER EndOfFile;
+       LARGE_INTEGER AllocationSize;
+       ULONG FileAttributes;
+       ULONG FileNameLength;
+       ULONG EaSize;
+       WCHAR FileName[0]; // variable size
+} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION,
+  FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
+
+
+typedef struct _FILE_BOTH_DIRECTORY_INFORMATION {
+       ULONG           NextEntryOffset;
+       ULONG           FileIndex;
+       TIME            CreationTime;
+       TIME            LastAccessTime;
+       TIME            LastWriteTime;
+       TIME            ChangeTime;
+       LARGE_INTEGER   EndOfFile;
+       LARGE_INTEGER   AllocationSize;
+       ULONG           FileAttributes;
+       ULONG           FileNameLength;
+       ULONG           EaSize;
+       CHAR            ShortNameLength;
+       WCHAR           ShortName[12]; // 8.3 name
+       WCHAR           FileName[0];
+} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION,
+  FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
+
+/*
+       NotifyFilter / CompletionFilter:
+
+       FILE_NOTIFY_CHANGE_FILE_NAME        0x00000001
+       FILE_NOTIFY_CHANGE_DIR_NAME         0x00000002
+       FILE_NOTIFY_CHANGE_NAME             0x00000003
+       FILE_NOTIFY_CHANGE_ATTRIBUTES       0x00000004
+       FILE_NOTIFY_CHANGE_SIZE             0x00000008
+       FILE_NOTIFY_CHANGE_LAST_WRITE       0x00000010
+       FILE_NOTIFY_CHANGE_LAST_ACCESS      0x00000020
+       FILE_NOTIFY_CHANGE_CREATION         0x00000040
+       FILE_NOTIFY_CHANGE_EA               0x00000080
+       FILE_NOTIFY_CHANGE_SECURITY         0x00000100
+       FILE_NOTIFY_CHANGE_STREAM_NAME      0x00000200
+       FILE_NOTIFY_CHANGE_STREAM_SIZE      0x00000400
+       FILE_NOTIFY_CHANGE_STREAM_WRITE     0x00000800
+*/
+
+typedef struct _FILE_NOTIFY_INFORMATION {
+       ULONG Action;
+       ULONG FileNameLength;
+       WCHAR FileName[0]; 
+} FILE_NOTIFY_INFORMATION;
+
+#define FSCTL_GET_VOLUME_BITMAP                        0x9006F
+#define FSCTL_GET_RETRIEVAL_POINTERS           0x90073
+#define FSCTL_MOVE_FILE                                0x90074
+
+typedef struct _MAPPING_PAIR
+{
+       ULONGLONG       Vcn;
+       ULONGLONG       Lcn;
+} MAPPING_PAIR, *PMAPPING_PAIR;
+
+typedef struct _GET_RETRIEVAL_DESCRIPTOR
+{
+       ULONG           NumberOfPairs;
+       ULONGLONG       StartVcn;
+       MAPPING_PAIR    Pair[0]; // variable size 
+} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR;
+
+typedef struct _MOVEFILE_DESCRIPTOR
+{
+       HANDLE            FileHandle;
+       ULONG             Reserved;
+       LARGE_INTEGER     StartVcn;
+       LARGE_INTEGER     TargetLcn;
+       ULONG             NumVcns;
+       ULONG             Reserved1;
+} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
+
+typedef struct _SECTION_BASIC_INFORMATION
+{
+  PVOID BaseAddress;
+  ULONG Attributes;
+  LARGE_INTEGER Size;
+} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
+
+typedef enum _SECTION_INFORMATION_CLASS 
+{
+  SectionBasicInformation,
+  SectionImageInformation,
+} SECTION_INFORMATION_CLASS;
+
+// shutdown action
+
+typedef enum SHUTDOWN_ACTION_TAG {
+  ShutdownNoReboot,
+  ShutdownReboot,
+  ShutdownPowerOff
+} SHUTDOWN_ACTION;
+
+#else /* __USE_W32API */
+
+#define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
+
+#endif /* __USE_W32API */
+
+#define NtCurrentProcess() ( (HANDLE) 0xFFFFFFFF )
+#define NtCurrentThread() ( (HANDLE) 0xFFFFFFFE )
+#if 1
+extern ULONG NtBuildNumber;
+#else
+#ifdef __NTOSKRNL__
+extern ULONG NtBuildNumber;
+#else
+extern ULONG NtBuildNumber;
+#endif
+#endif
+
+// event access mask
+
+#define EVENT_READ_ACCESS                      1
+#define EVENT_WRITE_ACCESS                     2
+
+//process query / set information class
+
+#define ProcessBasicInformation                        0
+#define ProcessQuotaLimits                     1
+#define ProcessIoCounters                      2
+#define ProcessVmCounters                      3
+#define ProcessTimes                           4
+#define ProcessBasePriority                    5
+#define ProcessRaisePriority                   6
+#define ProcessDebugPort                       7
+#define ProcessExceptionPort                   8
+#define ProcessAccessToken                     9
+#define ProcessLdtInformation                  10
+#define ProcessLdtSize                         11
+#define ProcessDefaultHardErrorMode            12
+#define ProcessIoPortHandlers                  13
+#define ProcessPooledUsageAndLimits            14
+#define ProcessWorkingSetWatch                 15
+#define ProcessUserModeIOPL                    16
+#define ProcessEnableAlignmentFaultFixup       17
+#define ProcessPriorityClass                   18
+#define ProcessWx86Information                 19
+#define ProcessHandleCount                     20
+#define ProcessAffinityMask                    21
+#define ProcessPriorityBoost                   22
+#define ProcessDeviceMap                       23
+#define ProcessSessionInformation              24
+#define ProcessForegroundInformation           25
+#define ProcessWow64Information                        26
+/* ReactOS private. */
+#define ProcessImageFileName                   27
+#define ProcessDesktop                          28
+#define MaxProcessInfoClass                    29
+
+/*
+ * thread query / set information class
+ */
+#define ThreadBasicInformation                 0
+#define ThreadTimes                            1
+#define ThreadPriority                         2
+#define ThreadBasePriority                     3
+#define ThreadAffinityMask                     4
+#define ThreadImpersonationToken               5
+#define ThreadDescriptorTableEntry             6
+#define ThreadEnableAlignmentFaultFixup                7
+#define ThreadEventPair                                8
+#define ThreadQuerySetWin32StartAddress                9
+#define ThreadZeroTlsCell                      10
+#define ThreadPerformanceCount                 11
+#define ThreadAmILastThread                    12
+#define ThreadIdealProcessor                   13
+#define ThreadPriorityBoost                    14
+#define ThreadSetTlsArrayAddress               15
+#define ThreadIsIoPending                      16
+#define ThreadHideFromDebugger                 17
+#define MaxThreadInfoClass                     17
+
+// object handle information
+
+#define ObjectBasicInformation                 0
+#define ObjectNameInformation                  1
+#define ObjectTypeInformation                  2
+#define ObjectAllInformation                   3
+#define ObjectDataInformation                  4
+
+typedef struct _ATOM_TABLE_INFORMATION
+{
+   ULONG NumberOfAtoms;
+   RTL_ATOM Atoms[1];
+} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION;
+
+
+// mutant information
+
+typedef enum _MUTANT_INFORMATION_CLASS
+{
+  MutantBasicInformation = 0
+} MUTANT_INFORMATION_CLASS;
+
+typedef struct _MUTANT_BASIC_INFORMATION
+{
+  LONG Count;
+  BOOLEAN Owned;
+  BOOLEAN Abandoned;
+} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
+
+
+// SystemTimeOfDayInformation (3)
+typedef
+struct _SYSTEM_TIMEOFDAY_INFORMATION
+{
+       LARGE_INTEGER   BootTime;
+       LARGE_INTEGER   CurrentTime;
+       LARGE_INTEGER   TimeZoneBias;
+       ULONG           TimeZoneId;
+       ULONG           Reserved;
+} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
+
+// SystemPathInformation (4)
+// IT DOES NOT WORK
+typedef
+struct _SYSTEM_PATH_INFORMATION
+{
+       PVOID   Dummy;
+
+} SYSTEM_PATH_INFORMATION, * PSYSTEM_PATH_INFORMATION;
+
+// SystemProcessInformation (5)
+typedef
+struct _SYSTEM_THREAD_INFORMATION
+{
+       TIME            KernelTime;
+       TIME            UserTime;
+       TIME            CreateTime;
+       ULONG           TickCount;
+       ULONG           StartEIP;
+       CLIENT_ID       ClientId;
+       ULONG           DynamicPriority;
+       ULONG           BasePriority;
+       ULONG           nSwitches;
+       DWORD           State;
+       KWAIT_REASON    WaitReason;
+       
+} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
+
+typedef
+struct SYSTEM_PROCESS_INFORMATION
+{
+       ULONG                           RelativeOffset;
+       ULONG                           ThreadCount;
+       ULONG                           Unused1 [6];
+       TIME                            CreateTime;
+       TIME                            UserTime;
+       TIME                            KernelTime;
+       UNICODE_STRING                  Name;
+       ULONG                           BasePriority;
+       ULONG                           ProcessId;
+       ULONG                           ParentProcessId;
+       ULONG                           HandleCount;
+       ULONG                           Unused2[2];
+       ULONG                           PeakVirtualSizeBytes;
+       ULONG                           TotalVirtualSizeBytes;
+       ULONG                           PageFaultCount;
+       ULONG                           PeakWorkingSetSizeBytes;
+       ULONG                           TotalWorkingSetSizeBytes;
+       ULONG                           PeakPagedPoolUsagePages;
+       ULONG                           TotalPagedPoolUsagePages;
+       ULONG                           PeakNonPagedPoolUsagePages;
+       ULONG                           TotalNonPagedPoolUsagePages;
+       ULONG                           TotalPageFileUsageBytes;
+       ULONG                           PeakPageFileUsageBytes;
+       ULONG                           TotalPrivateBytes;
+       SYSTEM_THREAD_INFORMATION       ThreadSysInfo [1];
+       
+} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
+
+// SystemCallCountInformation (6)
+typedef
+struct _SYSTEM_SDT_INFORMATION
+{
+       ULONG   BufferLength;
+       ULONG   NumberOfSystemServiceTables;
+       ULONG   NumberOfServices [1];
+       ULONG   ServiceCounters [1];
+
+} SYSTEM_SDT_INFORMATION, *PSYSTEM_SDT_INFORMATION;
+
+// SystemDeviceInformation (7)
+typedef
+struct _SYSTEM_DEVICE_INFORMATION
+{
+       ULONG   NumberOfDisks;
+       ULONG   NumberOfFloppies;
+       ULONG   NumberOfCdRoms;
+       ULONG   NumberOfTapes;
+       ULONG   NumberOfSerialPorts;
+       ULONG   NumberOfParallelPorts;
+} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION;
+
+// SystemProcessorPerformanceInformation (8)
+// (one per processor in the system)
+typedef
+struct _SYSTEM_PROCESSORTIME_INFO
+{
+       TIME    TotalProcessorRunTime;
+       TIME    TotalProcessorTime;
+       TIME    TotalProcessorUserTime;
+       TIME    TotalDPCTime;
+       TIME    TotalInterruptTime;
+       ULONG   TotalInterrupts;
+       ULONG   Unused;
+
+} SYSTEM_PROCESSORTIME_INFO, *PSYSTEM_PROCESSORTIME_INFO;
+
+// SystemFlagsInformation (9)
+typedef
+struct _SYSTEM_FLAGS_INFORMATION
+{
+       ULONG   Flags;
+
+} SYSTEM_FLAGS_INFORMATION, * PSYSTEM_FLAGS_INFORMATION;
+
+#define FLG_STOP_ON_EXCEPTION          0x00000001
+#define FLG_SHOW_LDR_SNAPS             0x00000002
+#define FLG_DEBUG_INITIAL_COMMAND      0x00000004
+#define FLG_STOP_ON_HANG_GUI           0x00000008
+#define FLG_HEAP_ENABLE_TAIL_CHECK     0x00000010
+#define FLG_HEAP_ENABLE_FREE_CHECK     0x00000020
+#define FLG_HEAP_VALIDATE_PARAMETERS   0x00000040
+#define FLG_HEAP_VALIDATE_ALL          0x00000080
+#define FLG_POOL_ENABLE_TAIL_CHECK     0x00000100
+#define FLG_POOL_ENABLE_FREE_CHECK     0x00000200
+#define FLG_POOL_ENABLE_TAGGING                0x00000400
+#define FLG_HEAP_ENABLE_TAGGING                0x00000800
+#define FLG_USER_STACK_TRACE_DB                0x00001000
+#define FLG_KERNEL_STACK_TRACE_DB      0x00002000
+#define FLG_MAINTAIN_OBJECT_TYPELIST   0x00004000
+#define FLG_HEAP_ENABLE_TAG_BY_DLL     0x00008000
+#define FLG_IGNORE_DEBUG_PRIV          0x00010000
+#define FLG_ENABLE_CSRDEBUG            0x00020000
+#define FLG_ENABLE_KDEBUG_SYMBOL_LOAD  0x00040000
+#define FLG_DISABLE_PAGE_KERNEL_STACKS 0x00080000
+#define FLG_HEAP_ENABLE_CALL_TRACING   0x00100000
+#define FLG_HEAP_DISABLE_COALESCING    0x00200000
+#define FLG_ENABLE_CLOSE_EXCEPTION     0x00400000
+#define FLG_ENABLE_EXCEPTION_LOGGING   0x00800000
+#define FLG_UNKNOWN_01000000           0x01000000
+#define FLG_UNKNOWN_02000000           0x02000000
+#define FLG_UNKNOWN_04000000           0x04000000
+#define FLG_ENABLE_DBGPRINT_BUFFERING  0x08000000
+#define FLG_UNKNOWN_10000000           0x10000000
+#define FLG_UNKNOWN_20000000           0x20000000
+#define FLG_UNKNOWN_40000000           0x40000000
+#define FLG_UNKNOWN_80000000           0x80000000
+
+// SystemCallTimeInformation (10)
+// UNKNOWN
+
+// SystemLocksInformation (12)
+typedef
+struct _SYSTEM_RESOURCE_LOCK_ENTRY
+{
+       ULONG   ResourceAddress;
+       ULONG   Always1;
+       ULONG   Unknown;
+       ULONG   ActiveCount;
+       ULONG   ContentionCount;
+       ULONG   Unused[2];
+       ULONG   NumberOfSharedWaiters;
+       ULONG   NumberOfExclusiveWaiters;
+       
+} SYSTEM_RESOURCE_LOCK_ENTRY, *PSYSTEM_RESOURCE_LOCK_ENTRY;
+
+typedef
+struct _SYSTEM_RESOURCE_LOCK_INFO
+{
+       ULONG                           Count;
+       SYSTEM_RESOURCE_LOCK_ENTRY      Lock [1];
+       
+} SYSTEM_RESOURCE_LOCK_INFO, *PSYSTEM_RESOURCE_LOCK_INFO;
+
+// SystemInformation13 (13)
+// UNKNOWN
+
+// SystemInformation14 (14)
+// UNKNOWN
+
+// SystemInformation15 (15)
+// UNKNOWN
+
+// SystemInstructionEmulationInfo (19)
+typedef
+struct _SYSTEM_VDM_INFORMATION
+{
+       ULONG VdmSegmentNotPresentCount;
+       ULONG VdmINSWCount;
+       ULONG VdmESPREFIXCount;
+       ULONG VdmCSPREFIXCount;
+       ULONG VdmSSPREFIXCount;
+       ULONG VdmDSPREFIXCount;
+       ULONG VdmFSPREFIXCount;
+       ULONG VdmGSPREFIXCount;
+       ULONG VdmOPER32PREFIXCount;
+       ULONG VdmADDR32PREFIXCount;
+       ULONG VdmINSBCount;
+       ULONG VdmINSWV86Count;
+       ULONG VdmOUTSBCount;
+       ULONG VdmOUTSWCount;
+       ULONG VdmPUSHFCount;
+       ULONG VdmPOPFCount;
+       ULONG VdmINTNNCount;
+       ULONG VdmINTOCount;
+       ULONG VdmIRETCount;
+       ULONG VdmINBIMMCount;
+       ULONG VdmINWIMMCount;
+       ULONG VdmOUTBIMMCount;
+       ULONG VdmOUTWIMMCount;
+       ULONG VdmINBCount;
+       ULONG VdmINWCount;
+       ULONG VdmOUTBCount;
+       ULONG VdmOUTWCount;
+       ULONG VdmLOCKPREFIXCount;
+       ULONG VdmREPNEPREFIXCount;
+       ULONG VdmREPPREFIXCount;
+       ULONG VdmHLTCount;
+       ULONG VdmCLICount;
+       ULONG VdmSTICount;
+       ULONG VdmBopCount;
+
+} SYSTEM_VDM_INFORMATION, *PSYSTEM_VDM_INFORMATION;
+
+// SystemInformation20 (20)
+// UNKNOWN
+
+// SystemPoolTagInformation (22)
+// found by Klaus P. Gerlicher
+// (implemented only in checked builds)
+typedef
+struct _POOL_TAG_STATS
+{
+       ULONG AllocationCount;
+       ULONG FreeCount;
+       ULONG SizeBytes;
+       
+} POOL_TAG_STATS;
+
+typedef
+struct _SYSTEM_POOL_TAG_ENTRY
+{
+       ULONG           Tag;
+       POOL_TAG_STATS  Paged;
+       POOL_TAG_STATS  NonPaged;
+
+} SYSTEM_POOL_TAG_ENTRY, * PSYSTEM_POOL_TAG_ENTRY;
+
+typedef
+struct _SYSTEM_POOL_TAG_INFO
+{
+       ULONG                   Count;
+       SYSTEM_POOL_TAG_ENTRY   PoolEntry [1];
+
+} SYSTEM_POOL_TAG_INFO, *PSYSTEM_POOL_TAG_INFO;
+
+// SystemProcessorScheduleInfo (23)
+typedef
+struct _SYSTEM_PROCESSOR_SCHEDULE_INFO
+{
+       ULONG nContextSwitches;
+       ULONG nDPCQueued;
+       ULONG nDPCRate;
+       ULONG TimerResolution;
+       ULONG nDPCBypasses;
+       ULONG nAPCBypasses;
+       
+} SYSTEM_PROCESSOR_SCHEDULE_INFO, *PSYSTEM_PROCESSOR_SCHEDULE_INFO;
+
+// SystemInformation25 (25)
+// UNKNOWN
+
+// SystemProcessorFaultCountInfo (33)
+typedef
+struct _SYSTEM_PROCESSOR_FAULT_INFO
+{
+       ULONG   nAlignmentFixup;
+       ULONG   nExceptionDispatches;
+       ULONG   nFloatingEmulation;
+       ULONG   Unknown;
+       
+} SYSTEM_PROCESSOR_FAULT_INFO, *PSYSTEM_PROCESSOR_FAULT_INFO;
+
+// SystemCrashDumpStateInfo (34)
+//
+
+// SystemDebuggerInformation (35)
+typedef
+struct _SYSTEM_DEBUGGER_INFO
+{
+       BOOLEAN KdDebuggerEnabled;
+       BOOLEAN KdDebuggerPresent;
+       
+} SYSTEM_DEBUGGER_INFO, *PSYSTEM_DEBUGGER_INFO;
+
+// SystemInformation36 (36)
+// UNKNOWN
+
+// SystemQuotaInformation (37)
+typedef
+struct _SYSTEM_QUOTA_INFORMATION
+{
+       ULONG   CmpGlobalQuota;
+       ULONG   CmpGlobalQuotaUsed;
+       ULONG   MmSizeofPagedPoolInBytes;
+       
+} SYSTEM_QUOTA_INFORMATION, *PSYSTEM_QUOTA_INFORMATION;
+
+// (49)
+// UNKNOWN
+
+// SystemVerifierInformation (51)
+// UNKNOWN
+
+// SystemAddVerifier (52)
+// UNKNOWN
+
+// wait type
+
+#define WaitAll                                        0
+#define WaitAny                                        1
+
+// number of wait objects
+
+#define THREAD_WAIT_OBJECTS                    3
+//#define MAXIMUM_WAIT_OBJECTS                 64
+
+// key restore flags
+
+#define REG_WHOLE_HIVE_VOLATILE                        1
+#define REG_REFRESH_HIVE                       2
+
+// object type  access rights
+
+#define OBJECT_TYPE_CREATE             0x0001
+#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+
+// directory access rights
+
+#define DIRECTORY_QUERY                                0x0001
+#define DIRECTORY_TRAVERSE                     0x0002
+#define DIRECTORY_CREATE_OBJECT                        0x0004
+#define DIRECTORY_CREATE_SUBDIRECTORY          0x0008
+
+#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)
+
+// symbolic link access rights
+
+#define SYMBOLIC_LINK_QUERY                    0x0001
+#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+
+
+typedef struct _OBJECT_DATA_INFORMATION
+{
+       BOOLEAN bInheritHandle;
+       BOOLEAN bProtectFromClose;
+} OBJECT_DATA_INFORMATION, *POBJECT_DATA_INFORMATION;
+
+
+typedef struct _OBJECT_TYPE_INFORMATION
+{
+       UNICODE_STRING  Name;
+       UNICODE_STRING Type;
+       ULONG TotalHandles;
+       ULONG ReferenceCount;
+} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
+
+
+// directory information
+
+typedef struct _OBJDIR_INFORMATION {
+       UNICODE_STRING ObjectName;
+       UNICODE_STRING ObjectTypeName; // Directory, Device ...
+       UCHAR          Data[0];
+} OBJDIR_INFORMATION, *POBJDIR_INFORMATION;
+
+
+/*
+        Action is one of the following values:
+
+       FILE_ACTION_ADDED               0x00000001
+       FILE_ACTION_REMOVED             0x00000002
+       FILE_ACTION_MODIFIED            0x00000003
+       FILE_ACTION_RENAMED_OLD_NAME    0x00000004
+       FILE_ACTION_RENAMED_NEW_NAME    0x00000005
+       FILE_ACTION_ADDED_STREAM        0x00000006
+       FILE_ACTION_REMOVED_STREAM      0x00000007
+       FILE_ACTION_MODIFIED_STREAM     0x00000008
+
+*/
+
+
+// File System Control commands ( related to defragging )
+
+#define        FSCTL_READ_MFT_RECORD                   0x90068 // NTFS only
+
+typedef struct _BITMAP_DESCRIPTOR
+{
+       ULONGLONG       StartLcn;
+       ULONGLONG       ClustersToEndOfVol;
+       BYTE            Map[0]; // variable size
+} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR;
+
+
+//typedef enum _TIMER_TYPE 
+//{
+//     NotificationTimer,
+//     SynchronizationTimer
+//} TIMER_TYPE;
+
+typedef struct _TIMER_BASIC_INFORMATION
+{
+  LARGE_INTEGER TimeRemaining;
+  BOOLEAN SignalState;
+} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION;
+
+typedef enum _TIMER_INFORMATION_CLASS
+{
+  TimerBasicInformation
+} TIMER_INFORMATION_CLASS;
+
+typedef
+struct _LPC_PORT_BASIC_INFORMATION
+{
+       DWORD   Unknown0;
+       DWORD   Unknown1;
+       DWORD   Unknown2;
+       DWORD   Unknown3;
+       DWORD   Unknown4;
+       DWORD   Unknown5;
+       DWORD   Unknown6;
+       DWORD   Unknown7;
+       DWORD   Unknown8;
+       DWORD   Unknown9;
+       DWORD   Unknown10;
+       DWORD   Unknown11;
+       DWORD   Unknown12;
+       DWORD   Unknown13;
+
+} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION;
+
+#endif
diff --git a/include/wine/commctrl.h b/include/wine/commctrl.h
new file mode 100644 (file)
index 0000000..cfaa14e
--- /dev/null
@@ -0,0 +1,4492 @@
+/*
+ * Common controls definitions
+ *
+ * Copyright (C) the Wine project
+ *
+ * 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
+ */
+
+#ifndef __WINE_COMMCTRL_H
+#define __WINE_COMMCTRL_H
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "prsht.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GetWindowWord GetWindowLongA
+
+/* Macros to map Winelib names to the correct implementation name */
+/* depending on __WINE__ and UNICODE macros.                      */
+/* Note that Winelib is purely Win32.                             */
+
+#ifdef __WINE__
+# define WINELIB_NAME_AW(func) \
+    func##_must_be_suffixed_with_W_or_A_in_this_context \
+    func##_must_be_suffixed_with_W_or_A_in_this_context
+#else  /* __WINE__ */
+# ifdef UNICODE
+#  define WINELIB_NAME_AW(func) func##W
+# else
+#  define WINELIB_NAME_AW(func) func##A
+# endif  /* UNICODE */
+#endif  /* __WINE__ */
+
+#ifdef __WINE__
+# define DECL_WINELIB_TYPE_AW(type)  /* nothing */
+#else   /* __WINE__ */
+# define DECL_WINELIB_TYPE_AW(type)  typedef WINELIB_NAME_AW(type) type;
+#endif  /* __WINE__ */
+
+
+
+BOOL WINAPI ShowHideMenuCtl (HWND, UINT, LPINT);
+VOID WINAPI GetEffectiveClientRect (HWND, LPRECT, LPINT);
+VOID WINAPI InitCommonControls (VOID);
+
+typedef struct tagINITCOMMONCONTROLSEX {
+    DWORD dwSize;
+    DWORD dwICC;
+} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
+
+BOOL WINAPI InitCommonControlsEx (LPINITCOMMONCONTROLSEX);
+
+LANGID WINAPI GetMUILanguage (VOID);
+VOID WINAPI InitMUILanguage (LANGID uiLang);
+
+
+#define COMCTL32_VERSION                5  /* dll version */
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0400
+#endif
+
+#define ICC_LISTVIEW_CLASSES   0x00000001  /* listview, header */
+#define ICC_TREEVIEW_CLASSES   0x00000002  /* treeview, tooltips */
+#define ICC_BAR_CLASSES        0x00000004  /* toolbar, statusbar, trackbar, tooltips */
+#define ICC_TAB_CLASSES        0x00000008  /* tab, tooltips */
+#define ICC_UPDOWN_CLASS       0x00000010  /* updown */
+#define ICC_PROGRESS_CLASS     0x00000020  /* progress */
+#define ICC_HOTKEY_CLASS       0x00000040  /* hotkey */
+#define ICC_ANIMATE_CLASS      0x00000080  /* animate */
+#define ICC_WIN95_CLASSES      0x000000FF
+#define ICC_DATE_CLASSES       0x00000100  /* month picker, date picker, time picker, updown */
+#define ICC_USEREX_CLASSES     0x00000200  /* comboex */
+#define ICC_COOL_CLASSES       0x00000400  /* rebar (coolbar) */
+#define ICC_INTERNET_CLASSES   0x00000800  /* IP address, ... */
+#define ICC_PAGESCROLLER_CLASS 0x00001000  /* page scroller */
+#define ICC_NATIVEFNTCTL_CLASS 0x00002000  /* native font control ???*/
+
+
+/* common control styles */
+#define CCS_TOP             0x00000001L
+#define CCS_NOMOVEY         0x00000002L
+#define CCS_BOTTOM          0x00000003L
+#define CCS_NORESIZE        0x00000004L
+#define CCS_NOPARENTALIGN   0x00000008L
+#define CCS_ADJUSTABLE      0x00000020L
+#define CCS_NODIVIDER       0x00000040L
+#define CCS_VERT            0x00000080L
+#define CCS_LEFT            (CCS_VERT|CCS_TOP)
+#define CCS_RIGHT           (CCS_VERT|CCS_BOTTOM)
+#define CCS_NOMOVEX         (CCS_VERT|CCS_NOMOVEY)
+
+
+/* common control shared messages */
+#define CCM_FIRST            0x2000
+
+#define CCM_SETBKCOLOR       (CCM_FIRST+1)     /* lParam = bkColor */
+#define CCM_SETCOLORSCHEME   (CCM_FIRST+2)     /* lParam = COLORSCHEME struct ptr */
+#define CCM_GETCOLORSCHEME   (CCM_FIRST+3)     /* lParam = COLORSCHEME struct ptr */
+#define CCM_GETDROPTARGET    (CCM_FIRST+4)
+#define CCM_SETUNICODEFORMAT (CCM_FIRST+5)
+#define CCM_GETUNICODEFORMAT (CCM_FIRST+6)
+#define CCM_SETVERSION       (CCM_FIRST+7)
+#define CCM_GETVERSION       (CCM_FIRST+8)
+#define CCM_SETNOTIFYWINDOW  (CCM_FIRST+9)     /* wParam = hwndParent */
+
+
+/* common notification codes (WM_NOTIFY)*/
+#define NM_FIRST                (0U-  0U)
+#define NM_LAST                 (0U- 99U)
+#define NM_OUTOFMEMORY          (NM_FIRST-1)
+#define NM_CLICK                (NM_FIRST-2)
+#define NM_DBLCLK               (NM_FIRST-3)
+#define NM_RETURN               (NM_FIRST-4)
+#define NM_RCLICK               (NM_FIRST-5)
+#define NM_RDBLCLK              (NM_FIRST-6)
+#define NM_SETFOCUS             (NM_FIRST-7)
+#define NM_KILLFOCUS            (NM_FIRST-8)
+#define NM_CUSTOMDRAW           (NM_FIRST-12)
+#define NM_HOVER                (NM_FIRST-13)
+#define NM_NCHITTEST            (NM_FIRST-14)
+#define NM_KEYDOWN              (NM_FIRST-15)
+#define NM_RELEASEDCAPTURE      (NM_FIRST-16)
+#define NM_SETCURSOR            (NM_FIRST-17)
+#define NM_CHAR                 (NM_FIRST-18)
+#define NM_TOOLTIPSCREATED      (NM_FIRST-19)
+
+#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \
+    (fn)((hwnd), (int)(wParam), (NMHDR*)(lParam))
+#define FORWARD_WM_NOTIFY(hwnd, idFrom, pnmhdr, fn) \
+    (LRESULT)(fn)((hwnd), WM_NOTIFY, (WPARAM)(int)(idFrom), (LPARAM)(NMHDR*)(pnmhdr))
+
+
+/* callback constants */
+#define LPSTR_TEXTCALLBACKA    ((LPSTR)-1L)
+#define LPSTR_TEXTCALLBACKW    ((LPWSTR)-1L)
+#define LPSTR_TEXTCALLBACK WINELIB_NAME_AW(LPSTR_TEXTCALLBACK)
+
+#define I_IMAGECALLBACK          (-1)
+#define I_IMAGENONE              (-2)
+#define I_INDENTCALLBACK         (-1)
+#define I_CHILDRENCALLBACK       (-1)
+
+/* owner drawn types */
+#define ODT_HEADER      100
+#define ODT_TAB         101
+#define ODT_LISTVIEW    102
+
+/* common notification structures */
+typedef struct tagNMTOOLTIPSCREATED
+{
+    NMHDR  hdr;
+    HWND hwndToolTips;
+} NMTOOLTIPSCREATED, *LPNMTOOLTIPSCREATED;
+
+typedef struct tagNMMOUSE
+{
+    NMHDR   hdr;
+    DWORD   dwItemSpec;
+    DWORD   dwItemData;
+    POINT   pt;
+    DWORD   dwHitInfo;   /* info where on item or control the mouse is */
+} NMMOUSE, *LPNMMOUSE;
+
+typedef struct tagNMOBJECTNOTIFY
+{
+    NMHDR   hdr;
+    int     iItem;
+#ifdef __IID_DEFINED__
+    const IID *piid;
+#else
+    const void *piid;
+#endif
+    void    *pObject;
+    HRESULT hResult;
+    DWORD   dwFlags;
+} NMOBJECTNOTIFY, *LPNMOBJECTNOTIFY;
+
+typedef struct tagNMKEY
+{
+    NMHDR   hdr;
+    UINT    nVKey;
+    UINT    uFlags;
+} NMKEY, *LPNMKEY;
+
+typedef struct tagNMCHAR
+{
+    NMHDR   hdr;
+    UINT    ch;
+    DWORD   dwItemPrev;           /* Item previously selected */
+    DWORD   dwItemNext;           /* Item to be selected */
+} NMCHAR, *LPNMCHAR;
+
+#ifndef CCSIZEOF_STRUCT
+#define CCSIZEOF_STRUCT(name, member) \
+    (((INT)((LPBYTE)(&((name*)0)->member)-((LPBYTE)((name*)0))))+ \
+    sizeof(((name*)0)->member))
+#endif
+
+
+/* This is only for Winelib applications. DON't use it wine itself!!! */
+#ifndef SNDMSG
+#ifdef __cplusplus
+#define SNDMSG ::SendMessage
+#else   /* __cplusplus */
+#define SNDMSG SendMessage
+#endif  /* __cplusplus */
+#endif  /* SNDMSG */
+
+
+#ifdef __cplusplus
+#define SNDMSGA ::SendMessageA
+#define SNDMSGW ::SendMessageW
+#else
+#define SNDMSGA SendMessageA
+#define SNDMSGW SendMessageW
+#endif
+
+/* Custom Draw messages */
+
+#define CDRF_DODEFAULT          0x0
+#define CDRF_NEWFONT            0x00000002
+#define CDRF_SKIPDEFAULT        0x00000004
+#define CDRF_NOTIFYPOSTPAINT    0x00000010
+#define CDRF_NOTIFYITEMDRAW     0x00000020
+#define CDRF_NOTIFYSUBITEMDRAW  0x00000020
+#define CDRF_NOTIFYPOSTERASE    0x00000040
+#define CDRF_NOTIFYITEMERASE    0x00000080      /*  obsolete ??? */
+
+
+/* drawstage flags */
+
+#define CDDS_PREPAINT           1
+#define CDDS_POSTPAINT          2
+#define CDDS_PREERASE           3
+#define CDDS_POSTERASE          4
+
+#define CDDS_ITEM                              0x00010000
+#define CDDS_ITEMPREPAINT              (CDDS_ITEM | CDDS_PREPAINT)
+#define CDDS_ITEMPOSTPAINT             (CDDS_ITEM | CDDS_POSTPAINT)
+#define CDDS_ITEMPREERASE              (CDDS_ITEM | CDDS_PREERASE)
+#define CDDS_ITEMPOSTERASE             (CDDS_ITEM | CDDS_POSTERASE)
+#define CDDS_SUBITEM            0x00020000
+
+/* itemState flags */
+
+#define CDIS_SELECTED          0x0001
+#define CDIS_GRAYED                    0x0002
+#define CDIS_DISABLED          0x0004
+#define CDIS_CHECKED           0x0008
+#define CDIS_FOCUS                     0x0010
+#define CDIS_DEFAULT           0x0020
+#define CDIS_HOT                       0x0040
+#define CDIS_MARKED         0x0080
+#define CDIS_INDETERMINATE  0x0100
+
+
+typedef struct tagNMCUSTOMDRAWINFO
+{
+       NMHDR   hdr;
+       DWORD   dwDrawStage;
+       HDC     hdc;
+       RECT    rc;
+       DWORD   dwItemSpec;
+       UINT    uItemState;
+       LPARAM  lItemlParam;
+} NMCUSTOMDRAW, *LPNMCUSTOMDRAW;
+
+typedef struct tagNMTTCUSTOMDRAW
+{
+    NMCUSTOMDRAW nmcd;
+    UINT       uDrawFlags;
+} NMTTCUSTOMDRAW, *LPNMTTCUSTOMDRAW;
+
+
+
+
+/* StatusWindow */
+
+#define STATUSCLASSNAME16      "msctls_statusbar"
+#define STATUSCLASSNAMEA       "msctls_statusbar32"
+#if defined(__GNUC__)
+# define STATUSCLASSNAMEW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+  's','t','a','t','u','s','b','a','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define STATUSCLASSNAMEW       L"msctls_statusbar32"
+#else
+static const WCHAR STATUSCLASSNAMEW[] = { 'm','s','c','t','l','s','_',
+  's','t','a','t','u','s','b','a','r','3','2',0 };
+#endif
+#define STATUSCLASSNAME                WINELIB_NAME_AW(STATUSCLASSNAME)
+
+#define SBT_NOBORDERS          0x0100
+#define SBT_POPOUT             0x0200
+#define SBT_RTLREADING         0x0400  /* not supported */
+#define SBT_TOOLTIPS           0x0800
+#define SBT_OWNERDRAW          0x1000
+
+#define SBARS_SIZEGRIP         0x0100
+
+#define SB_SETTEXTA            (WM_USER+1)
+#define SB_SETTEXTW            (WM_USER+11)
+#define SB_SETTEXT             WINELIB_NAME_AW(SB_SETTEXT)
+#define SB_GETTEXTA            (WM_USER+2)
+#define SB_GETTEXTW            (WM_USER+13)
+#define SB_GETTEXT             WINELIB_NAME_AW(SB_GETTEXT)
+#define SB_GETTEXTLENGTHA      (WM_USER+3)
+#define SB_GETTEXTLENGTHW      (WM_USER+12)
+#define SB_GETTEXTLENGTH       WINELIB_NAME_AW(SB_GETTEXTLENGTH)
+#define SB_SETPARTS            (WM_USER+4)
+#define SB_SETBORDERS          (WM_USER+5)
+#define SB_GETPARTS            (WM_USER+6)
+#define SB_GETBORDERS          (WM_USER+7)
+#define SB_SETMINHEIGHT                (WM_USER+8)
+#define SB_SIMPLE              (WM_USER+9)
+#define SB_GETRECT             (WM_USER+10)
+#define SB_ISSIMPLE            (WM_USER+14)
+#define SB_SETICON             (WM_USER+15)
+#define SB_SETTIPTEXTA (WM_USER+16)
+#define SB_SETTIPTEXTW (WM_USER+17)
+#define SB_SETTIPTEXT          WINELIB_NAME_AW(SB_SETTIPTEXT)
+#define SB_GETTIPTEXTA (WM_USER+18)
+#define SB_GETTIPTEXTW (WM_USER+19)
+#define SB_GETTIPTEXT          WINELIB_NAME_AW(SB_GETTIPTEXT)
+#define SB_GETICON             (WM_USER+20)
+#define SB_SETBKCOLOR          CCM_SETBKCOLOR   /* lParam = bkColor */
+#define SB_GETUNICODEFORMAT    CCM_GETUNICODEFORMAT
+#define SB_SETUNICODEFORMAT    CCM_SETUNICODEFORMAT
+
+#define SBN_FIRST              (0U-880U)
+#define SBN_LAST               (0U-899U)
+#define SBN_SIMPLEMODECHANGE   (SBN_FIRST-0)
+
+HWND WINAPI CreateStatusWindowA (INT, LPCSTR, HWND, UINT);
+HWND WINAPI CreateStatusWindowW (INT, LPCWSTR, HWND, UINT);
+#define CreateStatusWindow WINELIB_NAME_AW(CreateStatusWindow)
+VOID WINAPI DrawStatusTextA (HDC, LPRECT, LPCSTR, UINT);
+VOID WINAPI DrawStatusTextW (HDC, LPRECT, LPCWSTR, UINT);
+#define DrawStatusText WINELIB_NAME_AW(DrawStatusText)
+VOID WINAPI MenuHelp (UINT, WPARAM, LPARAM, HMENU,
+                      HINSTANCE, HWND, UINT*);
+
+typedef struct tagCOLORSCHEME
+{
+   DWORD            dwSize;
+   COLORREF         clrBtnHighlight;       /* highlight color */
+   COLORREF         clrBtnShadow;          /* shadow color */
+} COLORSCHEME, *LPCOLORSCHEME;
+
+/**************************************************************************
+ *  Drag List control
+ */
+
+typedef struct tagDRAGLISTINFO
+{
+    UINT  uNotification;
+    HWND  hWnd;
+    POINT ptCursor;
+} DRAGLISTINFO, *LPDRAGLISTINFO;
+
+#define DL_BEGINDRAG            (WM_USER+133)
+#define DL_DRAGGING             (WM_USER+134)
+#define DL_DROPPED              (WM_USER+135)
+#define DL_CANCELDRAG           (WM_USER+136)
+
+#define DL_CURSORSET            0
+#define DL_STOPCURSOR           1
+#define DL_COPYCURSOR           2
+#define DL_MOVECURSOR           3
+
+#define DRAGLISTMSGSTRING       TEXT("commctrl_DragListMsg")
+
+BOOL WINAPI MakeDragList (HWND);
+VOID   WINAPI DrawInsert (HWND, HWND, INT);
+INT  WINAPI LBItemFromPt (HWND, POINT, BOOL);
+
+
+/* UpDown */
+
+#define UPDOWN_CLASS16          "msctls_updown"
+#define UPDOWN_CLASSA           "msctls_updown32"
+#if defined(__GNUC__)
+# define UPDOWN_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+  'u','p','d','o','w','n','3','2',0 }
+#elif defined(_MSC_VER)
+# define UPDOWN_CLASSW          L"msctls_updown32"
+#else
+static const WCHAR UPDOWN_CLASSW[] = { 'm','s','c','t','l','s','_',
+  'u','p','d','o','w','n','3','2',0 };
+#endif
+#define UPDOWN_CLASS            WINELIB_NAME_AW(UPDOWN_CLASS)
+
+typedef struct tagUDACCEL
+{
+    UINT nSec;
+    UINT nInc;
+} UDACCEL, *LPUDACCEL;
+
+#define UD_MAXVAL          0x7fff
+#define UD_MINVAL          0x8001
+
+#define UDS_WRAP           0x0001
+#define UDS_SETBUDDYINT    0x0002
+#define UDS_ALIGNRIGHT     0x0004
+#define UDS_ALIGNLEFT      0x0008
+#define UDS_AUTOBUDDY      0x0010
+#define UDS_ARROWKEYS      0x0020
+#define UDS_HORZ           0x0040
+#define UDS_NOTHOUSANDS    0x0080
+#define UDS_HOTTRACK       0x0100
+
+#define UDN_FIRST          (0U-721)
+#define UDN_LAST           (0U-740)
+#define UDN_DELTAPOS       (UDN_FIRST-1)
+
+#define UDM_SETRANGE       (WM_USER+101)
+#define UDM_GETRANGE       (WM_USER+102)
+#define UDM_SETPOS         (WM_USER+103)
+#define UDM_GETPOS         (WM_USER+104)
+#define UDM_SETBUDDY       (WM_USER+105)
+#define UDM_GETBUDDY       (WM_USER+106)
+#define UDM_SETACCEL       (WM_USER+107)
+#define UDM_GETACCEL       (WM_USER+108)
+#define UDM_SETBASE        (WM_USER+109)
+#define UDM_GETBASE        (WM_USER+110)
+#define UDM_SETRANGE32     (WM_USER+111)
+#define UDM_GETRANGE32     (WM_USER+112)
+#define UDM_SETUNICODEFORMAT    CCM_SETUNICODEFORMAT
+#define UDM_GETUNICODEFORMAT    CCM_GETUNICODEFORMAT
+#define UDM_SETPOS32       (WM_USER+113)
+#define UDM_GETPOS32       (WM_USER+114)
+
+
+#define NMUPDOWN    NM_UPDOWN
+#define LPNMUPDOWN  LPNM_UPDOWN
+
+typedef struct tagNM_UPDOWN
+{
+  NMHDR hdr;
+  int iPos;
+  int iDelta;
+} NM_UPDOWN, *LPNM_UPDOWN;
+
+HWND WINAPI CreateUpDownControl (DWORD, INT, INT, INT, INT,
+                                   HWND, INT, HINSTANCE, HWND,
+                                   INT, INT, INT);
+
+/* Progress Bar */
+
+#define PROGRESS_CLASS16  "msctls_progress"
+#define PROGRESS_CLASSA   "msctls_progress32"
+#if defined(__GNUC__)
+# define PROGRESS_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+  'p','r','o','g','r','e','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define PROGRESS_CLASSW  L"msctls_progress32"
+#else
+static const WCHAR PROGRESS_CLASSW[] = { 'm','s','c','t','l','s','_',
+  'p','r','o','g','r','e','s','s','3','2',0 };
+#endif
+#define PROGRESS_CLASS      WINELIB_NAME_AW(PROGRESS_CLASS)
+
+#define PBM_SETRANGE        (WM_USER+1)
+#define PBM_SETPOS          (WM_USER+2)
+#define PBM_DELTAPOS        (WM_USER+3)
+#define PBM_SETSTEP         (WM_USER+4)
+#define PBM_STEPIT          (WM_USER+5)
+#define PBM_SETRANGE32      (WM_USER+6)
+#define PBM_GETRANGE        (WM_USER+7)
+#define PBM_GETPOS          (WM_USER+8)
+#define PBM_SETBARCOLOR     (WM_USER+9)
+#define PBM_SETBKCOLOR      CCM_SETBKCOLOR
+
+#define PBS_SMOOTH          0x01
+#define PBS_VERTICAL        0x04
+
+typedef struct
+{
+    INT iLow;
+    INT iHigh;
+} PBRANGE, *PPBRANGE;
+
+
+/* ImageList */
+
+struct _IMAGELIST;
+typedef struct _IMAGELIST *HIMAGELIST;
+
+#ifndef CLR_NONE
+#define CLR_NONE         0xFFFFFFFF
+#endif
+
+#ifndef CLR_DEFAULT
+#define CLR_DEFAULT      0xFF000000
+#endif
+
+#define CLR_HILIGHT      CLR_DEFAULT
+
+#define ILC_MASK         0x0001
+#define ILC_COLOR        0x0000
+#define ILC_COLORDDB     0x00FE
+#define ILC_COLOR4       0x0004
+#define ILC_COLOR8       0x0008
+#define ILC_COLOR16      0x0010
+#define ILC_COLOR24      0x0018
+#define ILC_COLOR32      0x0020
+#define ILC_PALETTE      0x0800  /* no longer supported by M$ */
+
+#define ILD_NORMAL        0x0000
+#define ILD_TRANSPARENT   0x0001
+#define ILD_BLEND25       0x0002
+#define ILD_BLEND50       0x0004
+#define ILD_MASK          0x0010
+#define ILD_IMAGE         0x0020
+#define ILD_ROP           0x0040
+#define ILD_OVERLAYMASK   0x0F00
+#define ILD_PRESERVEALPHA 0x1000
+#define ILD_SCALE         0x2000
+#define ILD_DPISCALE      0x4000
+
+#define ILD_SELECTED     ILD_BLEND50
+#define ILD_FOCUS        ILD_BLEND25
+#define ILD_BLEND        ILD_BLEND50
+
+#define INDEXTOOVERLAYMASK(i)  ((i)<<8)
+#define INDEXTOSTATEIMAGEMASK(i) ((i)<<12)
+
+#define ILCF_MOVE        (0x00000000)
+#define ILCF_SWAP        (0x00000001)
+
+#define ILS_NORMAL     0x0000
+#define ILS_GLOW       0x0001
+#define ILS_SHADOW     0x0002
+#define ILS_SATURATE   0x0004
+#define ILS_ALPHA      0x0008
+
+typedef struct _IMAGEINFO
+{
+    HBITMAP hbmImage;
+    HBITMAP hbmMask;
+    INT     Unused1;
+    INT     Unused2;
+    RECT    rcImage;
+} IMAGEINFO, *LPIMAGEINFO;
+
+
+typedef struct _IMAGELISTDRAWPARAMS
+{
+    DWORD       cbSize;
+    HIMAGELIST  himl;
+    INT         i;
+    HDC         hdcDst;
+    INT         x;
+    INT         y;
+    INT         cx;
+    INT         cy;
+    INT         xBitmap;  /* x offest from the upperleft of bitmap */
+    INT         yBitmap;  /* y offset from the upperleft of bitmap */
+    COLORREF    rgbBk;
+    COLORREF    rgbFg;
+    UINT        fStyle;
+    DWORD       dwRop;
+    DWORD       fState;
+    DWORD       Frame;
+    DWORD       crEffect;
+} IMAGELISTDRAWPARAMS, *LPIMAGELISTDRAWPARAMS;
+
+
+INT      WINAPI ImageList_Add(HIMAGELIST,HBITMAP,HBITMAP);
+INT      WINAPI ImageList_AddIcon (HIMAGELIST, HICON);
+INT      WINAPI ImageList_AddMasked(HIMAGELIST,HBITMAP,COLORREF);
+BOOL     WINAPI ImageList_BeginDrag(HIMAGELIST,INT,INT,INT);
+BOOL     WINAPI ImageList_Copy(HIMAGELIST,INT,HIMAGELIST,INT,INT);
+HIMAGELIST WINAPI ImageList_Create(INT,INT,UINT,INT,INT);
+BOOL     WINAPI ImageList_Destroy(HIMAGELIST);
+BOOL     WINAPI ImageList_DragEnter(HWND,INT,INT);
+BOOL     WINAPI ImageList_DragLeave(HWND);
+BOOL     WINAPI ImageList_DragMove(INT,INT);
+BOOL     WINAPI ImageList_DragShowNolock (BOOL);
+BOOL     WINAPI ImageList_Draw(HIMAGELIST,INT,HDC,INT,INT,UINT);
+BOOL     WINAPI ImageList_DrawEx(HIMAGELIST,INT,HDC,INT,INT,INT,
+                                   INT,COLORREF,COLORREF,UINT);
+BOOL     WINAPI ImageList_DrawIndirect(IMAGELISTDRAWPARAMS*);
+HIMAGELIST WINAPI ImageList_Duplicate(HIMAGELIST);
+BOOL     WINAPI ImageList_EndDrag(VOID);
+COLORREF   WINAPI ImageList_GetBkColor(HIMAGELIST);
+HIMAGELIST WINAPI ImageList_GetDragImage(POINT*,POINT*);
+HICON    WINAPI ImageList_GetIcon(HIMAGELIST,INT,UINT);
+BOOL     WINAPI ImageList_GetIconSize(HIMAGELIST,INT*,INT*);
+INT      WINAPI ImageList_GetImageCount(HIMAGELIST);
+BOOL     WINAPI ImageList_GetImageInfo(HIMAGELIST,INT,IMAGEINFO*);
+BOOL     WINAPI ImageList_GetImageRect(HIMAGELIST,INT,LPRECT);
+HIMAGELIST WINAPI ImageList_LoadImageA(HINSTANCE,LPCSTR,INT,INT,
+                                         COLORREF,UINT,UINT);
+HIMAGELIST WINAPI ImageList_LoadImageW(HINSTANCE,LPCWSTR,INT,INT,
+                                         COLORREF,UINT,UINT);
+#define    ImageList_LoadImage WINELIB_NAME_AW(ImageList_LoadImage)
+HIMAGELIST WINAPI ImageList_Merge(HIMAGELIST,INT,HIMAGELIST,INT,INT,INT);
+#ifdef IStream_IMETHODS
+HIMAGELIST WINAPI ImageList_Read(LPSTREAM);
+#endif
+BOOL     WINAPI ImageList_Remove(HIMAGELIST,INT);
+BOOL     WINAPI ImageList_Replace(HIMAGELIST,INT,HBITMAP,HBITMAP);
+INT      WINAPI ImageList_ReplaceIcon(HIMAGELIST,INT,HICON);
+COLORREF   WINAPI ImageList_SetBkColor(HIMAGELIST,COLORREF);
+BOOL     WINAPI ImageList_SetDragCursorImage(HIMAGELIST,INT,INT,INT);
+
+BOOL     WINAPI ImageList_SetIconSize(HIMAGELIST,INT,INT);
+BOOL     WINAPI ImageList_SetImageCount(HIMAGELIST,INT);
+BOOL     WINAPI ImageList_SetOverlayImage(HIMAGELIST,INT,INT);
+#ifdef IStream_IMETHODS
+BOOL     WINAPI ImageList_Write(HIMAGELIST, LPSTREAM);
+#endif
+
+#ifndef __WINE__
+#define ImageList_AddIcon(himl,hicon) ImageList_ReplaceIcon(himl,-1,hicon)
+#endif
+#define ImageList_ExtractIcon(hi,himl,i) ImageList_GetIcon(himl,i,0)
+#define ImageList_LoadBitmap(hi,lpbmp,cx,cGrow,crMask) \
+  ImageList_LoadImage(hi,lpbmp,cx,cGrow,crMask,IMAGE_BITMAP,0)
+#define ImageList_RemoveAll(himl) ImageList_Remove(himl,-1)
+
+
+#ifndef WM_MOUSEHOVER
+#define WM_MOUSEHOVER                   0x02A1
+#define WM_MOUSELEAVE                   0x02A3
+#endif
+
+#ifndef TME_HOVER
+
+#define TME_HOVER       0x00000001
+#define TME_LEAVE       0x00000002
+#define TME_QUERY       0x40000000
+#define TME_CANCEL      0x80000000
+
+
+#define HOVER_DEFAULT   0xFFFFFFFF
+
+typedef struct tagTRACKMOUSEEVENT {
+    DWORD cbSize;
+    DWORD dwFlags;
+    HWND  hwndTrack;
+    DWORD dwHoverTime;
+} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
+
+#endif
+
+BOOL
+WINAPI
+_TrackMouseEvent(
+    LPTRACKMOUSEEVENT lpEventTrack);
+
+/* Flat Scrollbar control */
+
+#define FLATSB_CLASS16        "flatsb_class"
+#define FLATSB_CLASSA         "flatsb_class32"
+#if defined(__GNUC__)
+# define FLATSB_CLASSW (const WCHAR []){ 'f','l','a','t','s','b','_', \
+  'c','l','a','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define FLATSB_CLASSW        L"flatsb_class32"
+#else
+static const WCHAR FLATSB_CLASSW[] = { 'f','l','a','t','s','b','_',
+  'c','l','a','s','s','3','2',0 };
+#endif
+#define FLATSB_CLASS          WINELIB_NAME_AW(FLATSB_CLASS)
+
+#define WSB_PROP_CYVSCROLL     0x00000001L
+#define WSB_PROP_CXHSCROLL     0x00000002L
+#define WSB_PROP_CYHSCROLL     0x00000004L
+#define WSB_PROP_CXVSCROLL     0x00000008L
+#define WSB_PROP_CXHTHUMB      0x00000010L
+#define WSB_PROP_CYVTHUMB      0x00000020L
+#define WSB_PROP_VBKGCOLOR     0x00000040L
+#define WSB_PROP_HBKGCOLOR     0x00000080L
+#define WSB_PROP_VSTYLE        0x00000100L
+#define WSB_PROP_HSTYLE        0x00000200L
+#define WSB_PROP_WINSTYLE      0x00000400L
+#define WSB_PROP_PALETTE       0x00000800L
+#define WSB_PROP_MASK          0x00000FFFL
+
+#define FSB_REGULAR_MODE       0
+#define FSB_ENCARTA_MODE       1
+#define FSB_FLAT_MODE          2
+
+
+BOOL  WINAPI FlatSB_EnableScrollBar(HWND, INT, UINT);
+BOOL  WINAPI FlatSB_ShowScrollBar(HWND, INT, BOOL);
+BOOL  WINAPI FlatSB_GetScrollRange(HWND, INT, LPINT, LPINT);
+BOOL  WINAPI FlatSB_GetScrollInfo(HWND, INT, LPSCROLLINFO);
+INT   WINAPI FlatSB_GetScrollPos(HWND, INT);
+BOOL  WINAPI FlatSB_GetScrollProp(HWND, INT, LPINT);
+INT   WINAPI FlatSB_SetScrollPos(HWND, INT, INT, BOOL);
+INT   WINAPI FlatSB_SetScrollInfo(HWND, INT, LPSCROLLINFO, BOOL);
+INT   WINAPI FlatSB_SetScrollRange(HWND, INT, INT, INT, BOOL);
+BOOL  WINAPI FlatSB_SetScrollProp(HWND, UINT, INT, BOOL);
+BOOL  WINAPI InitializeFlatSB(HWND);
+HRESULT WINAPI UninitializeFlatSB(HWND);
+
+/* Subclassing stuff */
+typedef LRESULT (CALLBACK *SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
+BOOL WINAPI SetWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+BOOL WINAPI GetWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR*);
+BOOL WINAPI RemoveWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR);
+LRESULT WINAPI DefSubclassProc(HWND, UINT, WPARAM, LPARAM);
+
+/* Header control */
+
+#define WC_HEADER16            "SysHeader"
+#define WC_HEADERA             "SysHeader32"
+#if defined(__GNUC__)
+# define WC_HEADERW (const WCHAR []){ 'S','y','s','H','e','a','d','e','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_HEADERW             L"SysHeader32"
+#else
+static const WCHAR WC_HEADERW[] = { 'S','y','s','H','e','a','d','e','r','3','2',0 };
+#endif
+#define WC_HEADER              WINELIB_NAME_AW(WC_HEADER)
+
+#define HDS_HORZ                0x0000
+#define HDS_BUTTONS             0x0002
+#define HDS_HOTTRACK            0x0004
+#define HDS_HIDDEN              0x0008
+#define HDS_DRAGDROP            0x0040
+#define HDS_FULLDRAG            0x0080
+
+#define HDI_WIDTH               0x0001
+#define HDI_HEIGHT              HDI_WIDTH
+#define HDI_TEXT                0x0002
+#define HDI_FORMAT              0x0004
+#define HDI_LPARAM              0x0008
+#define HDI_BITMAP              0x0010
+#define HDI_IMAGE               0x0020
+#define HDI_DI_SETITEM          0x0040
+#define HDI_ORDER               0x0080
+
+#define HDF_LEFT                0x0000
+#define HDF_RIGHT               0x0001
+#define HDF_CENTER              0x0002
+#define HDF_JUSTIFYMASK         0x0003
+#define HDF_RTLREADING          0x0004
+
+#define HDF_IMAGE               0x0800
+#define HDF_BITMAP_ON_RIGHT     0x1000
+#define HDF_BITMAP              0x2000
+#define HDF_STRING              0x4000
+#define HDF_OWNERDRAW           0x8000
+
+#define HHT_NOWHERE             0x0001
+#define HHT_ONHEADER            0x0002
+#define HHT_ONDIVIDER           0x0004
+#define HHT_ONDIVOPEN           0x0008
+#define HHT_ABOVE               0x0100
+#define HHT_BELOW               0x0200
+#define HHT_TORIGHT             0x0400
+#define HHT_TOLEFT              0x0800
+
+#define HDM_FIRST               0x1200
+#define HDM_GETITEMCOUNT        (HDM_FIRST+0)
+#define HDM_INSERTITEMA       (HDM_FIRST+1)
+#define HDM_INSERTITEMW       (HDM_FIRST+10)
+#define HDM_INSERTITEM         WINELIB_NAME_AW(HDM_INSERTITEM)
+#define HDM_DELETEITEM          (HDM_FIRST+2)
+#define HDM_GETITEMA          (HDM_FIRST+3)
+#define HDM_GETITEMW          (HDM_FIRST+11)
+#define HDM_GETITEM            WINELIB_NAME_AW(HDM_GETITEM)
+#define HDM_SETITEMA          (HDM_FIRST+4)
+#define HDM_SETITEMW          (HDM_FIRST+12)
+#define HDM_SETITEM            WINELIB_NAME_AW(HDM_SETITEM)
+#define HDM_LAYOUT              (HDM_FIRST+5)
+#define HDM_HITTEST             (HDM_FIRST+6)
+#define HDM_GETITEMRECT         (HDM_FIRST+7)
+#define HDM_SETIMAGELIST        (HDM_FIRST+8)
+#define HDM_GETIMAGELIST        (HDM_FIRST+9)
+
+#define HDM_ORDERTOINDEX        (HDM_FIRST+15)
+#define HDM_CREATEDRAGIMAGE     (HDM_FIRST+16)
+#define HDM_GETORDERARRAY       (HDM_FIRST+17)
+#define HDM_SETORDERARRAY       (HDM_FIRST+18)
+#define HDM_SETHOTDIVIDER       (HDM_FIRST+19)
+#define HDM_GETUNICODEFORMAT    CCM_GETUNICODEFORMAT
+#define HDM_SETUNICODEFORMAT    CCM_SETUNICODEFORMAT
+
+#define HDN_FIRST               (0U-300U)
+#define HDN_LAST                (0U-399U)
+#define HDN_ITEMCHANGINGA     (HDN_FIRST-0)
+#define HDN_ITEMCHANGINGW     (HDN_FIRST-20)
+#define HDN_ITEMCHANGING WINELIB_NAME_AW(HDN_ITEMCHANGING)
+#define HDN_ITEMCHANGEDA      (HDN_FIRST-1)
+#define HDN_ITEMCHANGEDW      (HDN_FIRST-21)
+#define HDN_ITEMCHANGED WINELIB_NAME_AW(HDN_ITEMCHANGED)
+#define HDN_ITEMCLICKA        (HDN_FIRST-2)
+#define HDN_ITEMCLICKW        (HDN_FIRST-22)
+#define HDN_ITEMCLICK WINELIB_NAME_AW(HDN_ITEMCLICK)
+#define HDN_ITEMDBLCLICKA     (HDN_FIRST-3)
+#define HDN_ITEMDBLCLICKW     (HDN_FIRST-23)
+#define HDN_ITEMDBLCLICK WINELIB_NAME_AW(HDN_ITEMDBLCLICK)
+#define HDN_DIVIDERDBLCLICKA  (HDN_FIRST-5)
+#define HDN_DIVIDERDBLCLICKW  (HDN_FIRST-25)
+#define HDN_DIVIDERDBLCLICK WINELIB_NAME_AW(HDN_DIVIDERDBLCLICK)
+#define HDN_BEGINTRACKA       (HDN_FIRST-6)
+#define HDN_BEGINTRACKW       (HDN_FIRST-26)
+#define HDN_BEGINTRACK WINELIB_NAME_AW(HDN_BEGINTRACK)
+#define HDN_ENDTRACKA         (HDN_FIRST-7)
+#define HDN_ENDTRACKW         (HDN_FIRST-27)
+#define HDN_ENDTRACK WINELIB_NAME_AW(HDN_ENDTRACK)
+#define HDN_TRACKA            (HDN_FIRST-8)
+#define HDN_TRACKW            (HDN_FIRST-28)
+#define HDN_TRACK WINELIB_NAME_AW(HDN_TRACK)
+#define HDN_GETDISPINFOA      (HDN_FIRST-9)
+#define HDN_GETDISPINFOW      (HDN_FIRST-29)
+#define HDN_GETDISPINFO WINELIB_NAME_AW(HDN_GETDISPINFO)
+#define HDN_BEGINDRAG         (HDN_FIRST-10)
+#define HDN_ENDDRAG           (HDN_FIRST-11)
+
+typedef struct _HD_LAYOUT
+{
+    RECT      *prc;
+    WINDOWPOS *pwpos;
+} HDLAYOUT, *LPHDLAYOUT;
+
+#define HD_LAYOUT   HDLAYOUT
+
+typedef struct _HD_ITEMA
+{
+    UINT    mask;
+    INT     cxy;
+    LPSTR     pszText;
+    HBITMAP hbm;
+    INT     cchTextMax;
+    INT     fmt;
+    LPARAM    lParam;
+    INT     iImage;
+    INT     iOrder;
+    UINT    type;
+    LPVOID  pvFilter;
+} HDITEMA, *LPHDITEMA;
+
+typedef struct _HD_ITEMW
+{
+    UINT    mask;
+    INT     cxy;
+    LPWSTR    pszText;
+    HBITMAP hbm;
+    INT     cchTextMax;
+    INT     fmt;
+    LPARAM    lParam;
+    INT     iImage;
+    INT     iOrder;
+    UINT    type;
+    LPVOID  pvFilter;
+} HDITEMW, *LPHDITEMW;
+
+#define HDITEM   WINELIB_NAME_AW(HDITEM)
+#define LPHDITEM WINELIB_NAME_AW(LPHDITEM)
+#define HD_ITEM  HDITEM
+
+#define HDITEM_V1_SIZEA CCSIZEOF_STRUCT(HDITEMA, lParam)
+#define HDITEM_V1_SIZEW CCSIZEOF_STRUCT(HDITEMW, lParam)
+#define HDITEM_V1_SIZE WINELIB_NAME_AW(HDITEM_V1_SIZE)
+
+typedef struct _HD_HITTESTINFO
+{
+    POINT pt;
+    UINT  flags;
+    INT   iItem;
+} HDHITTESTINFO, *LPHDHITTESTINFO;
+
+#define HD_HITTESTINFO   HDHITTESTINFO
+
+typedef struct tagNMHEADERA
+{
+    NMHDR     hdr;
+    INT     iItem;
+    INT     iButton;
+    HDITEMA *pitem;
+} NMHEADERA, *LPNMHEADERA;
+
+typedef struct tagNMHEADERW
+{
+    NMHDR     hdr;
+    INT     iItem;
+    INT     iButton;
+    HDITEMW *pitem;
+} NMHEADERW, *LPNMHEADERW;
+
+#define NMHEADER               WINELIB_NAME_AW(NMHEADER)
+#define LPNMHEADER             WINELIB_NAME_AW(LPNMHEADER)
+#define HD_NOTIFY               NMHEADER
+
+typedef struct tagNMHDDISPINFOA
+{
+    NMHDR     hdr;
+    INT     iItem;
+    UINT    mask;
+    LPSTR     pszText;
+    INT     cchTextMax;
+    INT     iImage;
+    LPARAM    lParam;
+} NMHDDISPINFOA, *LPNMHDDISPINFOA;
+
+typedef struct tagNMHDDISPINFOW
+{
+    NMHDR     hdr;
+    INT     iItem;
+    UINT    mask;
+    LPWSTR    pszText;
+    INT     cchTextMax;
+    INT     iImage;
+    LPARAM    lParam;
+} NMHDDISPINFOW, *LPNMHDDISPINFOW;
+
+#define NMHDDISPINFO           WINELIB_NAME_AW(NMHDDISPINFO)
+#define LPNMHDDISPINFO         WINELIB_NAME_AW(LPNMHDDISPINFO)
+
+#define Header_GetItemCount(hwndHD) \
+  (INT)SNDMSGA((hwndHD),HDM_GETITEMCOUNT,0,0L)
+#define Header_InsertItemA(hwndHD,i,phdi) \
+  (INT)SNDMSGA((hwndHD),HDM_INSERTITEMA,(WPARAM)(INT)(i),(LPARAM)(const HDITEMA*)(phdi))
+#define Header_InsertItemW(hwndHD,i,phdi) \
+  (INT)SNDMSGW((hwndHD),HDM_INSERTITEMW,(WPARAM)(INT)(i),(LPARAM)(const HDITEMW*)(phdi))
+#define Header_InsertItem WINELIB_NAME_AW(Header_InsertItem)
+#define Header_DeleteItem(hwndHD,i) \
+  (BOOL)SNDMSGA((hwndHD),HDM_DELETEITEM,(WPARAM)(INT)(i),0L)
+#define Header_GetItemA(hwndHD,i,phdi) \
+  (BOOL)SNDMSGA((hwndHD),HDM_GETITEMA,(WPARAM)(INT)(i),(LPARAM)(HDITEMA*)(phdi))
+#define Header_GetItemW(hwndHD,i,phdi) \
+  (BOOL)SNDMSGW((hwndHD),HDM_GETITEMW,(WPARAM)(INT)(i),(LPARAM)(HDITEMW*)(phdi))
+#define Header_GetItem WINELIB_NAME_AW(Header_GetItem)
+#define Header_SetItemA(hwndHD,i,phdi) \
+  (BOOL)SNDMSGA((hwndHD),HDM_SETITEMA,(WPARAM)(INT)(i),(LPARAM)(const HDITEMA*)(phdi))
+#define Header_SetItemW(hwndHD,i,phdi) \
+  (BOOL)SNDMSGW((hwndHD),HDM_SETITEMW,(WPARAM)(INT)(i),(LPARAM)(const HDITEMW*)(phdi))
+#define Header_SetItem WINELIB_NAME_AW(Header_SetItem)
+#define Header_Layout(hwndHD,playout) \
+  (BOOL)SNDMSGA((hwndHD),HDM_LAYOUT,0,(LPARAM)(LPHDLAYOUT)(playout))
+#define Header_GetItemRect(hwnd,iItem,lprc) \
+  (BOOL)SNDMSGA((hwnd),HDM_GETITEMRECT,(WPARAM)iItem,(LPARAM)lprc)
+#define Header_SetImageList(hwnd,himl) \
+  (HIMAGELIST)SNDMSGA((hwnd),HDM_SETIMAGELIST,0,(LPARAM)himl)
+#define Header_GetImageList(hwnd) \
+  (HIMAGELIST)SNDMSGA((hwnd),HDM_GETIMAGELIST,0,0)
+#define Header_OrderToIndex(hwnd,i) \
+  (INT)SNDMSGA((hwnd),HDM_ORDERTOINDEX,(WPARAM)i,0)
+#define Header_CreateDragImage(hwnd,i) \
+  (HIMAGELIST)SNDMSGA((hwnd),HDM_CREATEDRAGIMAGE,(WPARAM)i,0)
+#define Header_GetOrderArray(hwnd,iCount,lpi) \
+  (BOOL)SNDMSGA((hwnd),HDM_GETORDERARRAY,(WPARAM)iCount,(LPARAM)lpi)
+#define Header_SetOrderArray(hwnd,iCount,lpi) \
+  (BOOL)SNDMSGA((hwnd),HDM_SETORDERARRAY,(WPARAM)iCount,(LPARAM)lpi)
+#define Header_SetHotDivider(hwnd,fPos,dw) \
+  (INT)SNDMSGA((hwnd),HDM_SETHOTDIVIDER,(WPARAM)fPos,(LPARAM)dw)
+#define Header_SetUnicodeFormat(hwnd,fUnicode) \
+  (BOOL)SNDMSGA((hwnd),HDM_SETUNICODEFORMAT,(WPARAM)(fUnicode),0)
+#define Header_GetUnicodeFormat(hwnd) \
+  (BOOL)SNDMSGA((hwnd),HDM_GETUNICODEFORMAT,0,0)
+
+
+/* Toolbar */
+
+#define TOOLBARCLASSNAME16      "ToolbarWindow"
+#define TOOLBARCLASSNAMEA       "ToolbarWindow32"
+#if defined(__GNUC__)
+# define TOOLBARCLASSNAMEW (const WCHAR []){ 'T','o','o','l','b','a','r', \
+  'W','i','n','d','o','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define TOOLBARCLASSNAMEW      L"ToolbarWindow32"
+#else
+static const WCHAR TOOLBARCLASSNAMEW[] = { 'T','o','o','l','b','a','r',
+  'W','i','n','d','o','w','3','2',0 };
+#endif
+#define TOOLBARCLASSNAME WINELIB_NAME_AW(TOOLBARCLASSNAME)
+
+#define CMB_MASKED              0x02
+
+#define TBSTATE_CHECKED         0x01
+#define TBSTATE_PRESSED         0x02
+#define TBSTATE_ENABLED         0x04
+#define TBSTATE_HIDDEN          0x08
+#define TBSTATE_INDETERMINATE   0x10
+#define TBSTATE_WRAP            0x20
+#define TBSTATE_ELLIPSES        0x40
+#define TBSTATE_MARKED          0x80
+
+
+/* as of _WIN32_IE >= 0x0500 the following symbols are obsolete,
+ * "everyone" should use the BTNS_... stuff below
+ */
+#define TBSTYLE_BUTTON          0x00
+#define TBSTYLE_SEP             0x01
+#define TBSTYLE_CHECK           0x02
+#define TBSTYLE_GROUP           0x04
+#define TBSTYLE_CHECKGROUP      (TBSTYLE_GROUP | TBSTYLE_CHECK)
+#define TBSTYLE_DROPDOWN        0x08
+#define TBSTYLE_AUTOSIZE        0x10
+#define TBSTYLE_NOPREFIX        0x20
+#define BTNS_BUTTON             TBSTYLE_BUTTON
+#define BTNS_SEP                TBSTYLE_SEP
+#define BTNS_CHECK              TBSTYLE_CHECK
+#define BTNS_GROUP              TBSTYLE_GROUP
+#define BTNS_CHECKGROUP         TBSTYLE_CHECKGROUP
+#define BTNS_DROPDOWN           TBSTYLE_DROPDOWN
+#define BTNS_AUTOSIZE           TBSTYLE_AUTOSIZE
+#define BTNS_NOPREFIX           TBSTYLE_NOPREFIX
+#define BTNS_SHOWTEXT           0x40  /* ignored unless TBSTYLE_EX_MIXEDB set */
+#define BTNS_WHOLEDROPDOWN      0x80  /* draw dropdown arrow, but without split arrow section */
+
+#define TBSTYLE_TOOLTIPS        0x0100
+#define TBSTYLE_WRAPABLE        0x0200
+#define TBSTYLE_ALTDRAG         0x0400
+#define TBSTYLE_FLAT            0x0800
+#define TBSTYLE_LIST            0x1000
+#define TBSTYLE_CUSTOMERASE     0x2000
+#define TBSTYLE_REGISTERDROP    0x4000
+#define TBSTYLE_TRANSPARENT     0x8000
+#define TBSTYLE_EX_DRAWDDARROWS         0x00000001
+#define TBSTYLE_EX_UNDOC1               0x00000004 /* similar to TBSTYLE_WRAPABLE */
+#define TBSTYLE_EX_MIXEDBUTTONS         0x00000008
+#define TBSTYLE_EX_HIDECLIPPEDBUTTONS   0x00000010 /* don't show partially obscured buttons */
+#define TBSTYLE_EX_DOUBLEBUFFER         0x00000080 /* Double Buffer the toolbar ??? */
+
+#define TBIF_IMAGE              0x00000001
+#define TBIF_TEXT               0x00000002
+#define TBIF_STATE              0x00000004
+#define TBIF_STYLE              0x00000008
+#define TBIF_LPARAM             0x00000010
+#define TBIF_COMMAND            0x00000020
+#define TBIF_SIZE               0x00000040
+
+#define TBBF_LARGE             0x0001
+
+#define TB_ENABLEBUTTON          (WM_USER+1)
+#define TB_CHECKBUTTON           (WM_USER+2)
+#define TB_PRESSBUTTON           (WM_USER+3)
+#define TB_HIDEBUTTON            (WM_USER+4)
+#define TB_INDETERMINATE         (WM_USER+5)
+#define TB_MARKBUTTON           (WM_USER+6)
+#define TB_ISBUTTONENABLED       (WM_USER+9)
+#define TB_ISBUTTONCHECKED       (WM_USER+10)
+#define TB_ISBUTTONPRESSED       (WM_USER+11)
+#define TB_ISBUTTONHIDDEN        (WM_USER+12)
+#define TB_ISBUTTONINDETERMINATE (WM_USER+13)
+#define TB_ISBUTTONHIGHLIGHTED   (WM_USER+14)
+#define TB_SETSTATE              (WM_USER+17)
+#define TB_GETSTATE              (WM_USER+18)
+#define TB_ADDBITMAP             (WM_USER+19)
+#define TB_ADDBUTTONSA         (WM_USER+20)
+#define TB_ADDBUTTONSW         (WM_USER+68)
+#define TB_ADDBUTTONS WINELIB_NAME_AW(TB_ADDBUTTONS)
+#define TB_HITTEST               (WM_USER+69)
+#define TB_INSERTBUTTONA       (WM_USER+21)
+#define TB_INSERTBUTTONW       (WM_USER+67)
+#define TB_INSERTBUTTON WINELIB_NAME_AW(TB_INSERTBUTTON)
+#define TB_DELETEBUTTON          (WM_USER+22)
+#define TB_GETBUTTON             (WM_USER+23)
+#define TB_BUTTONCOUNT           (WM_USER+24)
+#define TB_COMMANDTOINDEX        (WM_USER+25)
+#define TB_SAVERESTOREA        (WM_USER+26)
+#define TB_SAVERESTOREW        (WM_USER+76)
+#define TB_SAVERESTORE WINELIB_NAME_AW(TB_SAVERESTORE)
+#define TB_CUSTOMIZE             (WM_USER+27)
+#define TB_ADDSTRINGA          (WM_USER+28)
+#define TB_ADDSTRINGW          (WM_USER+77)
+#define TB_ADDSTRING WINELIB_NAME_AW(TB_ADDSTRING)
+#define TB_GETITEMRECT           (WM_USER+29)
+#define TB_BUTTONSTRUCTSIZE      (WM_USER+30)
+#define TB_SETBUTTONSIZE         (WM_USER+31)
+#define TB_SETBITMAPSIZE         (WM_USER+32)
+#define TB_AUTOSIZE              (WM_USER+33)
+#define TB_GETTOOLTIPS           (WM_USER+35)
+#define TB_SETTOOLTIPS           (WM_USER+36)
+#define TB_SETPARENT             (WM_USER+37)
+#define TB_SETROWS               (WM_USER+39)
+#define TB_GETROWS               (WM_USER+40)
+#define TB_GETBITMAPFLAGS        (WM_USER+41)
+#define TB_SETCMDID              (WM_USER+42)
+#define TB_CHANGEBITMAP          (WM_USER+43)
+#define TB_GETBITMAP             (WM_USER+44)
+#define TB_GETBUTTONTEXTA      (WM_USER+45)
+#define TB_GETBUTTONTEXTW      (WM_USER+75)
+#define TB_GETBUTTONTEXT WINELIB_NAME_AW(TB_GETBUTTONTEXT)
+#define TB_REPLACEBITMAP         (WM_USER+46)
+#define TB_SETINDENT             (WM_USER+47)
+#define TB_SETIMAGELIST          (WM_USER+48)
+#define TB_GETIMAGELIST          (WM_USER+49)
+#define TB_LOADIMAGES            (WM_USER+50)
+#define TB_GETRECT               (WM_USER+51) /* wParam is the Cmd instead of index */
+#define TB_SETHOTIMAGELIST       (WM_USER+52)
+#define TB_GETHOTIMAGELIST       (WM_USER+53)
+#define TB_SETDISABLEDIMAGELIST  (WM_USER+54)
+#define TB_GETDISABLEDIMAGELIST  (WM_USER+55)
+#define TB_SETSTYLE              (WM_USER+56)
+#define TB_GETSTYLE              (WM_USER+57)
+#define TB_GETBUTTONSIZE         (WM_USER+58)
+#define TB_SETBUTTONWIDTH        (WM_USER+59)
+#define TB_SETMAXTEXTROWS        (WM_USER+60)
+#define TB_GETTEXTROWS           (WM_USER+61)
+#define TB_GETOBJECT             (WM_USER+62)
+#define TB_GETBUTTONINFOW      (WM_USER+63)
+#define TB_GETBUTTONINFOA      (WM_USER+65)
+#define TB_GETBUTTONINFO WINELIB_NAME_AW(TB_GETBUTTONINFO)
+#define TB_SETBUTTONINFOW      (WM_USER+64)
+#define TB_SETBUTTONINFOA      (WM_USER+66)
+#define TB_SETBUTTONINFO WINELIB_NAME_AW(TB_SETBUTTONINFO)
+#define TB_SETDRAWTEXTFLAGS      (WM_USER+70)
+#define TB_GETHOTITEM            (WM_USER+71)
+#define TB_SETHOTITEM            (WM_USER+72)
+#define TB_SETANCHORHIGHLIGHT    (WM_USER+73)
+#define TB_GETANCHORHIGHLIGHT    (WM_USER+74)
+#define TB_MAPACCELERATORA     (WM_USER+78)
+#define TB_MAPACCELERATORW     (WM_USER+90)
+#define TB_MAPACCELERATOR WINELIB_NAME_AW(TB_MAPACCELERATOR)
+#define TB_GETINSERTMARK         (WM_USER+79)
+#define TB_SETINSERTMARK         (WM_USER+80)
+#define TB_INSERTMARKHITTEST     (WM_USER+81)
+#define TB_MOVEBUTTON            (WM_USER+82)
+#define TB_GETMAXSIZE            (WM_USER+83)
+#define TB_SETEXTENDEDSTYLE      (WM_USER+84)
+#define TB_GETEXTENDEDSTYLE      (WM_USER+85)
+#define TB_GETPADDING            (WM_USER+86)
+#define TB_SETPADDING            (WM_USER+87)
+#define TB_SETINSERTMARKCOLOR    (WM_USER+88)
+#define TB_GETINSERTMARKCOLOR    (WM_USER+89)
+#define TB_SETCOLORSCHEME        CCM_SETCOLORSCHEME
+#define TB_GETCOLORSCHEME        CCM_GETCOLORSCHEME
+#define TB_SETUNICODEFORMAT      CCM_SETUNICODEFORMAT
+#define TB_GETUNICODEFORMAT      CCM_GETUNICODEFORMAT
+#define TB_GETSTRINGW            (WM_USER+91)
+#define TB_GETSTRINGA            (WM_USER+92)
+#define TB_GETSTRING  WINELIB_NAME_AW(TB_GETSTRING)
+
+/* undocumented messages in Toolbar */
+#define TB_UNKWN45D              (WM_USER+93)
+#define TB_UNKWN45E              (WM_USER+94)
+#define TB_UNKWN460              (WM_USER+96)
+#define TB_UNKWN463              (WM_USER+99)
+#define TB_UNKWN464              (WM_USER+100)
+
+
+#define TBN_FIRST               (0U-700U)
+#define TBN_LAST                (0U-720U)
+#define TBN_GETBUTTONINFOA    (TBN_FIRST-0)
+#define TBN_GETBUTTONINFOW    (TBN_FIRST-20)
+#define TBN_GETBUTTONINFO WINELIB_NAME_AW(TBN_GETBUTTONINFO)
+#define TBN_BEGINDRAG          (TBN_FIRST-1)
+#define TBN_ENDDRAG            (TBN_FIRST-2)
+#define TBN_BEGINADJUST                (TBN_FIRST-3)
+#define TBN_ENDADJUST          (TBN_FIRST-4)
+#define TBN_RESET              (TBN_FIRST-5)
+#define TBN_QUERYINSERT                (TBN_FIRST-6)
+#define TBN_QUERYDELETE                (TBN_FIRST-7)
+#define TBN_TOOLBARCHANGE      (TBN_FIRST-8)
+#define TBN_CUSTHELP           (TBN_FIRST-9)
+#define TBN_DROPDOWN           (TBN_FIRST-10)
+#define TBN_GETOBJECT          (TBN_FIRST-12)
+#define TBN_HOTITEMCHANGE      (TBN_FIRST-13)
+#define TBN_DRAGOUT            (TBN_FIRST-14)
+#define TBN_DELETINGBUTTON     (TBN_FIRST-15)
+#define TBN_GETDISPINFOA       (TBN_FIRST-16)
+#define TBN_GETDISPINFOW       (TBN_FIRST-17)
+#define TBN_GETDISPINFO                WINELIB_NAME_AW(TBN_GETDISPINFO)
+#define TBN_GETINFOTIPA       (TBN_FIRST-18)
+#define TBN_GETINFOTIPW       (TBN_FIRST-19)
+#define TBN_GETINFOTIP WINELIB_NAME_AW(TBN_GETINFOTIP)
+#define TBN_INITCUSTOMIZE      (TBN_FIRST-23)
+#define TBNRF_HIDEHELP         0x00000001
+
+
+/* Return values from TBN_DROPDOWN */
+#define TBDDRET_DEFAULT  0
+#define TBDDRET_NODEFAULT  1
+#define TBDDRET_TREATPRESSED  2
+
+typedef struct _NMTBCUSTOMDRAW
+{
+    NMCUSTOMDRAW nmcd;
+    HBRUSH hbrMonoDither;
+    HBRUSH hbrLines;
+    HPEN hpenLines;
+    COLORREF clrText;
+    COLORREF clrMark;
+    COLORREF clrTextHighlight;
+    COLORREF clrBtnFace;
+    COLORREF clrBtnHighlight;
+    COLORREF clrHighlightHotTrack;
+    RECT rcText;
+    int nStringBkMode;
+    int nHLStringBkMode;
+} NMTBCUSTOMDRAW, *LPNMTBCUSTOMDRAW;
+
+/* return flags for Toolbar NM_CUSTOMDRAW notifications */
+#define TBCDRF_NOEDGES        0x00010000  /* Don't draw button edges       */
+#define TBCDRF_HILITEHOTTRACK 0x00020000  /* Use color of the button bkgnd */
+                                          /* when hottracked               */
+#define TBCDRF_NOOFFSET       0x00040000  /* No offset button if pressed   */
+#define TBCDRF_NOMARK         0x00080000  /* Don't draw default highlight  */
+                                          /* for TBSTATE_MARKED            */
+#define TBCDRF_NOETCHEDEFFECT 0x00100000  /* No etched effect for          */
+                                          /* disabled items                */
+#define TBCDRF_BLENDICON      0x00200000  /* ILD_BLEND50 on the icon image */
+#define TBCDRF_NOBACKGROUND   0x00400000  /* ILD_BLEND50 on the icon image */
+
+
+/* This is just for old CreateToolbar. */
+/* Don't use it in new programs. */
+typedef struct _OLDTBBUTTON {
+    INT iBitmap;
+    INT idCommand;
+    BYTE  fsState;
+    BYTE  fsStyle;
+    BYTE  bReserved[2];
+    DWORD dwData;
+} OLDTBBUTTON, *POLDTBBUTTON, *LPOLDTBBUTTON;
+typedef const OLDTBBUTTON *LPCOLDTBBUTTON;
+
+
+typedef struct _TBBUTTON {
+    INT iBitmap;
+    INT idCommand;
+    BYTE  fsState;
+    BYTE  fsStyle;
+    BYTE  bReserved[2];
+    DWORD dwData;
+    INT iString;
+} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;
+typedef const TBBUTTON *LPCTBBUTTON;
+
+
+typedef struct _COLORMAP {
+    COLORREF from;
+    COLORREF to;
+} COLORMAP, *LPCOLORMAP;
+
+
+typedef struct tagTBADDBITMAP {
+    HINSTANCE hInst;
+    UINT      nID;
+} TBADDBITMAP, *LPTBADDBITMAP;
+
+#define HINST_COMMCTRL         ((HINSTANCE)-1)
+#define IDB_STD_SMALL_COLOR     0
+#define IDB_STD_LARGE_COLOR     1
+#define IDB_VIEW_SMALL_COLOR    4
+#define IDB_VIEW_LARGE_COLOR    5
+#define IDB_HIST_SMALL_COLOR    8
+#define IDB_HIST_LARGE_COLOR    9
+
+#define STD_CUT                 0
+#define STD_COPY                1
+#define STD_PASTE               2
+#define STD_UNDO                3
+#define STD_REDOW               4
+#define STD_DELETE              5
+#define STD_FILENEW             6
+#define STD_FILEOPEN            7
+#define STD_FILESAVE            8
+#define STD_PRINTPRE            9
+#define STD_PROPERTIES          10
+#define STD_HELP                11
+#define STD_FIND                12
+#define STD_REPLACE             13
+#define STD_PRINT               14
+
+#define VIEW_LARGEICONS         0
+#define VIEW_SMALLICONS         1
+#define VIEW_LIST               2
+#define VIEW_DETAILS            3
+#define VIEW_SORTNAME           4
+#define VIEW_SORTSIZE           5
+#define VIEW_SORTDATE           6
+#define VIEW_SORTTYPE           7
+#define VIEW_PARENTFOLDER       8
+#define VIEW_NETCONNECT         9
+#define VIEW_NETDISCONNECT      10
+#define VIEW_NEWFOLDER          11
+#define VIEW_VIEWMENU           12
+
+#define HIST_BACK               0
+#define HIST_FORWARD            1
+#define HIST_FAVORITES          2
+#define HIST_ADDTOFAVORITES     3
+#define HIST_VIEWTREE           4
+
+typedef struct tagTBSAVEPARAMSA {
+    HKEY   hkr;
+    LPCSTR pszSubKey;
+    LPCSTR pszValueName;
+} TBSAVEPARAMSA, *LPTBSAVEPARAMSA;
+
+typedef struct tagTBSAVEPARAMSW {
+    HKEY   hkr;
+    LPCWSTR pszSubKey;
+    LPCWSTR pszValueName;
+} TBSAVEPARAMSW, *LPTBSAVEPARAMSW;
+
+#define TBSAVEPARAMS   WINELIB_NAME_AW(TBSAVEPARAMS)
+#define LPTBSAVEPARAMS WINELIB_NAME_AW(LPTBSAVEPARAMS)
+
+typedef struct
+{
+    UINT cbSize;
+    DWORD  dwMask;
+    INT  idCommand;
+    INT  iImage;
+    BYTE   fsState;
+    BYTE   fsStyle;
+    WORD   cx;
+    DWORD  lParam;
+    LPSTR  pszText;
+    INT  cchText;
+} TBBUTTONINFOA, *LPTBBUTTONINFOA;
+
+typedef struct
+{
+    UINT cbSize;
+    DWORD  dwMask;
+    INT  idCommand;
+    INT  iImage;
+    BYTE   fsState;
+    BYTE   fsStyle;
+    WORD   cx;
+    DWORD  lParam;
+    LPWSTR pszText;
+    INT  cchText;
+} TBBUTTONINFOW, *LPTBBUTTONINFOW;
+
+#define TBBUTTONINFO   WINELIB_NAME_AW(TBBUTTONINFO)
+#define LPTBBUTTONINFO WINELIB_NAME_AW(LPTBBUTTONINFO)
+
+typedef struct tagNMTBHOTITEM
+{
+    NMHDR hdr;
+    int idOld;
+    int idNew;
+    DWORD dwFlags;
+} NMTBHOTITEM, *LPNMTBHOTITEM;
+
+typedef struct tagNMTBGETINFOTIPA
+{
+    NMHDR  hdr;
+    LPSTR  pszText;
+    INT  cchTextMax;
+    INT  iItem;
+    LPARAM lParam;
+} NMTBGETINFOTIPA, *LPNMTBGETINFOTIPA;
+
+typedef struct tagNMTBGETINFOTIPW
+{
+    NMHDR  hdr;
+    LPWSTR pszText;
+    INT  cchTextMax;
+    INT  iItem;
+    LPARAM lParam;
+} NMTBGETINFOTIPW, *LPNMTBGETINFOTIPW;
+
+#define NMTBGETINFOTIP   WINELIB_NAME_AW(NMTBGETINFOFTIP)
+#define LPNMTBGETINFOTIP WINELIB_NAME_AW(LPNMTBGETINFOTIP)
+
+typedef struct
+{
+    NMHDR hdr;
+    DWORD dwMask;
+    int idCommand;
+    DWORD lParam;
+    int iImage;
+    LPSTR pszText;
+    int cchText;
+} NMTBDISPINFOA, *LPNMTBDISPINFOA;
+
+typedef struct
+{
+    NMHDR hdr;
+    DWORD dwMask;
+    int idCommand;
+    DWORD lParam;
+    int iImage;
+    LPWSTR pszText;
+    int cchText;
+} NMTBDISPINFOW, *LPNMTBDISPINFOW;
+
+#define NMTBDISPINFO WINELIB_NAME_AW(NMTBDISPINFO)
+#define LPNMTBDISPINFO WINELIB_NAME_AW(LPNMTBDISPINFO)
+
+/* contents of dwMask in the NMTBDISPINFO structure */
+#define TBNF_IMAGE     0x00000001
+#define TBNF_TEXT      0x00000002
+#define TBNF_DI_SETITEM  0x10000000
+
+
+typedef struct tagNMTOOLBARA
+{
+    NMHDR    hdr;
+    INT      iItem;
+    TBBUTTON tbButton;
+    INT      cchText;
+    LPSTR    pszText;
+    RECT     rcButton; /* Version 5.80 */
+} NMTOOLBARA, *LPNMTOOLBARA, TBNOTIFYA, *LPTBNOTIFYA;
+
+typedef struct tagNMTOOLBARW
+{
+    NMHDR    hdr;
+    INT      iItem;
+    TBBUTTON tbButton;
+    INT      cchText;
+    LPWSTR   pszText;
+    RECT     rcButton; /* Version 5.80 */
+} NMTOOLBARW, *LPNMTOOLBARW, TBNOTIFYW, *LPTBNOTIFYW;
+
+#define NMTOOLBAR   WINELIB_NAME_AW(NMTOOLBAR)
+#define LPNMTOOLBAR WINELIB_NAME_AW(LPNMTOOLBAR)
+#define TBNOTIFY    WINELIB_NAME_AW(TBNOTIFY)
+#define LPTBNOTIFY  WINELIB_NAME_AW(LPTBNOTIFY)
+
+typedef struct
+{
+       HINSTANCE hInstOld;
+       UINT      nIDOld;
+       HINSTANCE hInstNew;
+       UINT      nIDNew;
+       INT       nButtons;
+} TBREPLACEBITMAP, *LPTBREPLACEBITMAP;
+
+#define HICF_OTHER          0x00000000
+#define HICF_MOUSE          0x00000001   /* Triggered by mouse             */
+#define HICF_ARROWKEYS      0x00000002   /* Triggered by arrow keys        */
+#define HICF_ACCELERATOR    0x00000004   /* Triggered by accelerator       */
+#define HICF_DUPACCEL       0x00000008   /* This accelerator is not unique */
+#define HICF_ENTERING       0x00000010   /* idOld is invalid               */
+#define HICF_LEAVING        0x00000020   /* idNew is invalid               */
+#define HICF_RESELECT       0x00000040   /* hot item reselected            */
+#define HICF_LMOUSE         0x00000080   /* left mouse button selected     */
+#define HICF_TOGGLEDROPDOWN 0x00000100   /* Toggle button's dropdown state */
+
+typedef struct
+{
+    int   iButton;
+    DWORD dwFlags;
+} TBINSERTMARK, *LPTBINSERTMARK;
+#define TBIMHT_AFTER      0x00000001 /* TRUE = insert After iButton, otherwise before */
+#define TBIMHT_BACKGROUND 0x00000002 /* TRUE if and only if missed buttons completely */
+
+HWND WINAPI
+CreateToolbar(HWND, DWORD, UINT, INT, HINSTANCE,
+              UINT, LPCOLDTBBUTTON, INT);
+
+HWND WINAPI
+CreateToolbarEx(HWND, DWORD, UINT, INT,
+                HINSTANCE, UINT, LPCTBBUTTON,
+                INT, INT, INT, INT, INT, UINT);
+
+HBITMAP WINAPI
+CreateMappedBitmap (HINSTANCE, INT, UINT, LPCOLORMAP, INT);
+
+
+/* Tool tips */
+
+#define TOOLTIPS_CLASS16        "tooltips_class"
+#define TOOLTIPS_CLASSA         "tooltips_class32"
+#if defined(__GNUC__)
+# define TOOLTIPS_CLASSW (const WCHAR []){ 't','o','o','l','t','i','p','s','_', \
+  'c','l','a','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define TOOLTIPS_CLASSW        L"tooltips_class32"
+#else
+static const WCHAR TOOLTIPS_CLASSW[] = { 't','o','o','l','t','i','p','s','_',
+  'c','l','a','s','s','3','2',0 };
+#endif
+#define TOOLTIPS_CLASS          WINELIB_NAME_AW(TOOLTIPS_CLASS)
+
+#define INFOTIPSIZE             1024
+
+#define TTS_ALWAYSTIP           0x01
+#define TTS_NOPREFIX            0x02
+
+#define TTF_IDISHWND            0x0001
+#define TTF_CENTERTIP           0x0002
+#define TTF_RTLREADING          0x0004
+#define TTF_SUBCLASS            0x0010
+#define TTF_TRACK               0x0020
+#define TTF_ABSOLUTE            0x0080
+#define TTF_TRANSPARENT         0x0100
+#define TTF_DI_SETITEM          0x8000  /* valid only on the TTN_NEEDTEXT callback */
+
+
+#define TTDT_AUTOMATIC          0
+#define TTDT_RESHOW             1
+#define TTDT_AUTOPOP            2
+#define TTDT_INITIAL            3
+
+
+#define TTM_ACTIVATE            (WM_USER+1)
+#define TTM_SETDELAYTIME        (WM_USER+3)
+#define TTM_ADDTOOLA            (WM_USER+4)
+#define TTM_ADDTOOLW            (WM_USER+50)
+#define TTM_ADDTOOL WINELIB_NAME_AW(TTM_ADDTOOL)
+#define TTM_DELTOOLA            (WM_USER+5)
+#define TTM_DELTOOLW            (WM_USER+51)
+#define TTM_DELTOOL WINELIB_NAME_AW(TTM_DELTOOL)
+#define TTM_NEWTOOLRECTA        (WM_USER+6)
+#define TTM_NEWTOOLRECTW        (WM_USER+52)
+#define TTM_NEWTOOLRECT WINELIB_NAME_AW(TTM_NEWTOOLRECT)
+#define TTM_RELAYEVENT          (WM_USER+7)
+#define TTM_GETTOOLINFOA        (WM_USER+8)
+#define TTM_GETTOOLINFOW        (WM_USER+53)
+#define TTM_GETTOOLINFO WINELIB_NAME_AW(TTM_GETTOOLINFO)
+#define TTM_SETTOOLINFOA        (WM_USER+9)
+#define TTM_SETTOOLINFOW        (WM_USER+54)
+#define TTM_SETTOOLINFO WINELIB_NAME_AW(TTM_SETTOOLINFO)
+#define TTM_HITTESTA            (WM_USER+10)
+#define TTM_HITTESTW            (WM_USER+55)
+#define TTM_HITTEST WINELIB_NAME_AW(TTM_HITTEST)
+#define TTM_GETTEXTA            (WM_USER+11)
+#define TTM_GETTEXTW            (WM_USER+56)
+#define TTM_GETTEXT WINELIB_NAME_AW(TTM_GETTEXT)
+#define TTM_UPDATETIPTEXTA      (WM_USER+12)
+#define TTM_UPDATETIPTEXTW      (WM_USER+57)
+#define TTM_UPDATETIPTEXT WINELIB_NAME_AW(TTM_UPDATETIPTEXT)
+#define TTM_GETTOOLCOUNT        (WM_USER+13)
+#define TTM_ENUMTOOLSA          (WM_USER+14)
+#define TTM_ENUMTOOLSW          (WM_USER+58)
+#define TTM_ENUMTOOLS WINELIB_NAME_AW(TTM_ENUMTOOLS)
+#define TTM_GETCURRENTTOOLA     (WM_USER+15)
+#define TTM_GETCURRENTTOOLW     (WM_USER+59)
+#define TTM_GETCURRENTTOOL WINELIB_NAME_AW(TTM_GETCURRENTTOOL)
+#define TTM_WINDOWFROMPOINT     (WM_USER+16)
+#define TTM_TRACKACTIVATE       (WM_USER+17)
+#define TTM_TRACKPOSITION       (WM_USER+18)
+#define TTM_SETTIPBKCOLOR       (WM_USER+19)
+#define TTM_SETTIPTEXTCOLOR     (WM_USER+20)
+#define TTM_GETDELAYTIME        (WM_USER+21)
+#define TTM_GETTIPBKCOLOR       (WM_USER+22)
+#define TTM_GETTIPTEXTCOLOR     (WM_USER+23)
+#define TTM_SETMAXTIPWIDTH      (WM_USER+24)
+#define TTM_GETMAXTIPWIDTH      (WM_USER+25)
+#define TTM_SETMARGIN           (WM_USER+26)
+#define TTM_GETMARGIN           (WM_USER+27)
+#define TTM_POP                 (WM_USER+28)
+#define TTM_UPDATE              (WM_USER+29)
+#define TTM_GETBUBBLESIZE       (WM_USER+30)
+
+
+#define TTN_FIRST               (0U-520U)
+#define TTN_LAST                (0U-549U)
+#define TTN_GETDISPINFOA        (TTN_FIRST-0)
+#define TTN_GETDISPINFOW        (TTN_FIRST-10)
+#define TTN_GETDISPINFO WINELIB_NAME_AW(TTN_GETDISPINFO)
+#define TTN_SHOW                (TTN_FIRST-1)
+#define TTN_POP                 (TTN_FIRST-2)
+
+#define TTN_NEEDTEXT TTN_GETDISPINFO
+#define TTN_NEEDTEXTA TTN_GETDISPINFOA
+#define TTN_NEEDTEXTW TTN_GETDISPINFOW
+
+typedef struct tagTOOLINFOA {
+    UINT cbSize;
+    UINT uFlags;
+    HWND hwnd;
+    UINT uId;
+    RECT rect;
+    HINSTANCE hinst;
+    LPSTR lpszText;
+    LPARAM lParam;
+} TTTOOLINFOA, *LPTOOLINFOA, *PTOOLINFOA, *LPTTTOOLINFOA;
+
+typedef struct tagTOOLINFOW {
+    UINT cbSize;
+    UINT uFlags;
+    HWND hwnd;
+    UINT uId;
+    RECT rect;
+    HINSTANCE hinst;
+    LPWSTR lpszText;
+    LPARAM lParam;
+} TTTOOLINFOW, *LPTOOLINFOW, *PTOOLINFOW, *LPTTTOOLINFOW;
+
+#define TTTOOLINFO WINELIB_NAME_AW(TTTOOLINFO)
+#define TOOLINFO WINELIB_NAME_AW(TTTOOLINFO)
+#define PTOOLINFO WINELIB_NAME_AW(PTOOLINFO)
+#define LPTTTOOLINFO WINELIB_NAME_AW(LPTTTOOLINFO)
+#define LPTOOLINFO WINELIB_NAME_AW(LPTOOLINFO)
+
+#define TTTOOLINFO_V1_SIZEA CCSIZEOF_STRUCT(TTTOOLINFOA, lpszText)
+#define TTTOOLINFO_V1_SIZEW CCSIZEOF_STRUCT(TTTOOLINFOW, lpszText)
+#define TTTOOLINFO_V1_SIZE WINELIB_NAME_AW(TTTOOLINFO_V1_SIZE)
+
+typedef struct _TT_HITTESTINFOA
+{
+    HWND        hwnd;
+    POINT       pt;
+    TTTOOLINFOA ti;
+} TTHITTESTINFOA, *LPTTHITTESTINFOA;
+#define LPHITTESTINFOA LPTTHITTESTINFOA
+
+typedef struct _TT_HITTESTINFOW
+{
+    HWND        hwnd;
+    POINT       pt;
+    TTTOOLINFOW ti;
+} TTHITTESTINFOW, *LPTTHITTESTINFOW;
+#define LPHITTESTINFOW LPTTHITTESTINFOW
+
+#define TTHITTESTINFO WINELIB_NAME_AW(TTHITTESTINFO)
+#define LPTTHITTESTINFO WINELIB_NAME_AW(LPTTHITTESTINFO)
+#define LPHITTESTINFO WINELIB_NAME_AW(LPHITTESTINFO)
+
+typedef struct tagNMTTDISPINFOA
+{
+    NMHDR hdr;
+    LPSTR lpszText;
+    CHAR  szText[80];
+    HINSTANCE hinst;
+    UINT      uFlags;
+    LPARAM      lParam;
+} NMTTDISPINFOA, *LPNMTTDISPINFOA;
+
+typedef struct tagNMTTDISPINFOW
+{
+    NMHDR       hdr;
+    LPWSTR      lpszText;
+    WCHAR       szText[80];
+    HINSTANCE hinst;
+    UINT      uFlags;
+    LPARAM      lParam;
+} NMTTDISPINFOW, *LPNMTTDISPINFOW;
+
+#define NMTTDISPINFO WINELIB_NAME_AW(NMTTDISPINFO)
+#define LPNMTTDISPINFO WINELIB_NAME_AW(LPNMTTDISPINFO)
+
+#define NMTTDISPINFO_V1_SIZEA CCSIZEOF_STRUCT(NMTTDISPINFOA, uFlags)
+#define NMTTDISPINFO_V1_SIZEW CCSIZEOF_STRUCT(NMTTDISPINFOW, uFlags)
+#define NMTTDISPINFO_V1_SIZE WINELIB_NAME_AW(NMTTDISPINFO_V1_SIZE)
+
+#define TOOLTIPTEXTW    NMTTDISPINFOW
+#define TOOLTIPTEXTA    NMTTDISPINFOA
+#define TOOLTIPTEXT     NMTTDISPINFO
+#define LPTOOLTIPTEXTW  LPNMTTDISPINFOW
+#define LPTOOLTIPTEXTA  LPNMTTDISPINFOA
+#define LPTOOLTIPTEXT   LPNMTTDISPINFO
+
+
+/* Rebar control */
+
+#define REBARCLASSNAME16        "ReBarWindow"
+#define REBARCLASSNAMEA         "ReBarWindow32"
+#if defined(__GNUC__)
+# define REBARCLASSNAMEW (const WCHAR []){ 'R','e','B','a','r', \
+  'W','i','n','d','o','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define REBARCLASSNAMEW        L"ReBarWindow32"
+#else
+static const WCHAR REBARCLASSNAMEW[] = { 'R','e','B','a','r',
+  'W','i','n','d','o','w','3','2',0 };
+#endif
+#define REBARCLASSNAME          WINELIB_NAME_AW(REBARCLASSNAME)
+
+#define RBS_TOOLTIPS            0x0100
+#define RBS_VARHEIGHT           0x0200
+#define RBS_BANDBORDERS         0x0400
+#define RBS_FIXEDORDER          0x0800
+#define RBS_REGISTERDROP        0x1000
+#define RBS_AUTOSIZE            0x2000
+#define RBS_VERTICALGRIPPER     0x4000
+#define RBS_DBLCLKTOGGLE        0x8000
+
+#define RBIM_IMAGELIST          0x00000001
+
+#define RBBIM_STYLE             0x00000001
+#define RBBIM_COLORS            0x00000002
+#define RBBIM_TEXT              0x00000004
+#define RBBIM_IMAGE             0x00000008
+#define RBBIM_CHILD             0x00000010
+#define RBBIM_CHILDSIZE         0x00000020
+#define RBBIM_SIZE              0x00000040
+#define RBBIM_BACKGROUND        0x00000080
+#define RBBIM_ID                0x00000100
+#define RBBIM_IDEALSIZE         0x00000200
+#define RBBIM_LPARAM            0x00000400
+#define RBBIM_HEADERSIZE        0x00000800
+
+#define RBBS_BREAK              0x00000001
+#define RBBS_FIXEDSIZE          0x00000002
+#define RBBS_CHILDEDGE          0x00000004
+#define RBBS_HIDDEN             0x00000008
+#define RBBS_NOVERT             0x00000010
+#define RBBS_FIXEDBMP           0x00000020
+#define RBBS_VARIABLEHEIGHT     0x00000040
+#define RBBS_GRIPPERALWAYS      0x00000080
+#define RBBS_NOGRIPPER          0x00000100
+
+#define RBNM_ID                 0x00000001
+#define RBNM_STYLE              0x00000002
+#define RBNM_LPARAM             0x00000004
+
+#define RBHT_NOWHERE            0x0001
+#define RBHT_CAPTION            0x0002
+#define RBHT_CLIENT             0x0003
+#define RBHT_GRABBER            0x0004
+
+#define RB_INSERTBANDA        (WM_USER+1)
+#define RB_INSERTBANDW        (WM_USER+10)
+#define RB_INSERTBAND           WINELIB_NAME_AW(RB_INSERTBAND)
+#define RB_DELETEBAND           (WM_USER+2)
+#define RB_GETBARINFO           (WM_USER+3)
+#define RB_SETBARINFO           (WM_USER+4)
+#define RB_GETBANDINFO        (WM_USER+5)   /* just for compatibility */
+#define RB_SETBANDINFOA       (WM_USER+6)
+#define RB_SETBANDINFOW       (WM_USER+11)
+#define RB_SETBANDINFO          WINELIB_NAME_AW(RB_SETBANDINFO)
+#define RB_SETPARENT            (WM_USER+7)
+#define RB_HITTEST              (WM_USER+8)
+#define RB_GETRECT              (WM_USER+9)
+#define RB_GETBANDCOUNT         (WM_USER+12)
+#define RB_GETROWCOUNT          (WM_USER+13)
+#define RB_GETROWHEIGHT         (WM_USER+14)
+#define RB_IDTOINDEX            (WM_USER+16)
+#define RB_GETTOOLTIPS          (WM_USER+17)
+#define RB_SETTOOLTIPS          (WM_USER+18)
+#define RB_SETBKCOLOR           (WM_USER+19)
+#define RB_GETBKCOLOR           (WM_USER+20)
+#define RB_SETTEXTCOLOR         (WM_USER+21)
+#define RB_GETTEXTCOLOR         (WM_USER+22)
+#define RB_SIZETORECT           (WM_USER+23)
+#define RB_BEGINDRAG            (WM_USER+24)
+#define RB_ENDDRAG              (WM_USER+25)
+#define RB_DRAGMOVE             (WM_USER+26)
+#define RB_GETBARHEIGHT         (WM_USER+27)
+#define RB_GETBANDINFOW       (WM_USER+28)
+#define RB_GETBANDINFOA       (WM_USER+29)
+#define RB_GETBANDINFO16          WINELIB_NAME_AW(RB_GETBANDINFO16)
+#define RB_MINIMIZEBAND         (WM_USER+30)
+#define RB_MAXIMIZEBAND         (WM_USER+31)
+#define RB_GETBANDBORDERS       (WM_USER+34)
+#define RB_SHOWBAND             (WM_USER+35)
+#define RB_SETPALETTE           (WM_USER+37)
+#define RB_GETPALETTE           (WM_USER+38)
+#define RB_MOVEBAND             (WM_USER+39)
+#define RB_GETDROPTARGET        CCM_GETDROPTARGET
+#define RB_SETCOLORSCHEME       CCM_SETCOLORSCHEME
+#define RB_GETCOLORSCHEME       CCM_GETCOLORSCHEME
+#define RB_SETUNICODEFORMAT     CCM_SETUNICODEFORMAT
+#define RB_GETUNICODEFORMAT     CCM_GETUNICODEFORMAT
+
+#define RBN_FIRST               (0U-831U)
+#define RBN_LAST                (0U-859U)
+#define RBN_HEIGHTCHANGE        (RBN_FIRST-0)
+#define RBN_GETOBJECT           (RBN_FIRST-1)
+#define RBN_LAYOUTCHANGED       (RBN_FIRST-2)
+#define RBN_AUTOSIZE            (RBN_FIRST-3)
+#define RBN_BEGINDRAG           (RBN_FIRST-4)
+#define RBN_ENDDRAG             (RBN_FIRST-5)
+#define RBN_DELETINGBAND        (RBN_FIRST-6)
+#define RBN_DELETEDBAND         (RBN_FIRST-7)
+#define RBN_CHILDSIZE           (RBN_FIRST-8)
+
+typedef struct tagREBARINFO
+{
+    UINT     cbSize;
+    UINT     fMask;
+    HIMAGELIST himl;
+} REBARINFO, *LPREBARINFO;
+
+typedef struct tagREBARBANDINFOA
+{
+    UINT    cbSize;
+    UINT    fMask;
+    UINT    fStyle;
+    COLORREF  clrFore;
+    COLORREF  clrBack;
+    LPSTR     lpText;
+    UINT    cch;
+    INT     iImage;
+    HWND    hwndChild;
+    UINT    cxMinChild;
+    UINT    cyMinChild;
+    UINT    cx;
+    HBITMAP hbmBack;
+    UINT    wID;
+    UINT    cyChild;
+    UINT    cyMaxChild;
+    UINT    cyIntegral;
+    UINT    cxIdeal;
+    LPARAM    lParam;
+    UINT    cxHeader;
+} REBARBANDINFOA, *LPREBARBANDINFOA;
+
+typedef REBARBANDINFOA const *LPCREBARBANDINFOA;
+
+typedef struct tagREBARBANDINFOW
+{
+    UINT    cbSize;
+    UINT    fMask;
+    UINT    fStyle;
+    COLORREF  clrFore;
+    COLORREF  clrBack;
+    LPWSTR    lpText;
+    UINT    cch;
+    INT     iImage;
+    HWND    hwndChild;
+    UINT    cxMinChild;
+    UINT    cyMinChild;
+    UINT    cx;
+    HBITMAP hbmBack;
+    UINT    wID;
+    UINT    cyChild;
+    UINT    cyMaxChild;
+    UINT    cyIntegral;
+    UINT    cxIdeal;
+    LPARAM    lParam;
+    UINT    cxHeader;
+} REBARBANDINFOW, *LPREBARBANDINFOW;
+
+typedef REBARBANDINFOW const *LPCREBARBANDINFOW;
+
+#define REBARBANDINFO    WINELIB_NAME_AW(REBARBANDINFO)
+#define LPREBARBANDINFO  WINELIB_NAME_AW(LPREBARBANDINFO)
+#define LPCREBARBANDINFO WINELIB_NAME_AW(LPCREBARBANDINFO)
+
+#define REBARBANDINFO_V3_SIZEA CCSIZEOF_STRUCT(REBARBANDINFOA, wID)
+#define REBARBANDINFO_V3_SIZEW CCSIZEOF_STRUCT(REBARBANDINFOW, wID)
+#define REBARBANDINFO_V3_SIZE WINELIB_NAME_AW(REBARBANDINFO_V3_SIZE)
+
+typedef struct tagNMREBARCHILDSIZE
+{
+    NMHDR  hdr;
+    UINT uBand;
+    UINT wID;
+    RECT rcChild;
+    RECT rcBand;
+} NMREBARCHILDSIZE, *LPNMREBARCHILDSIZE;
+
+typedef struct tagNMREBAR
+{
+    NMHDR  hdr;
+    DWORD  dwMask;
+    UINT uBand;
+    UINT fStyle;
+    UINT wID;
+    LPARAM lParam;
+} NMREBAR, *LPNMREBAR;
+
+typedef struct tagNMRBAUTOSIZE
+{
+    NMHDR hdr;
+    BOOL fChanged;
+    RECT rcTarget;
+    RECT rcActual;
+} NMRBAUTOSIZE, *LPNMRBAUTOSIZE;
+
+typedef struct _RB_HITTESTINFO
+{
+    POINT pt;
+    UINT  flags;
+    INT   iBand;
+} RBHITTESTINFO, *LPRBHITTESTINFO;
+
+
+/* Trackbar control */
+
+#define TRACKBAR_CLASS16        "msctls_trackbar"
+#define TRACKBAR_CLASSA         "msctls_trackbar32"
+#if defined(__GNUC__)
+# define TRACKBAR_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+  't','r','a','c','k','b','a','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define TRACKBAR_CLASSW        L"msctls_trackbar32"
+#else
+static const WCHAR TRACKBAR_CLASSW[] = { 'm','s','c','t','l','s','_',
+  't','r','a','c','k','b','a','r','3','2',0 };
+#endif
+#define TRACKBAR_CLASS  WINELIB_NAME_AW(TRACKBAR_CLASS)
+
+#define TBS_AUTOTICKS           0x0001
+#define TBS_VERT                0x0002
+#define TBS_HORZ                0x0000
+#define TBS_TOP                 0x0004
+#define TBS_BOTTOM              0x0000
+#define TBS_LEFT                0x0004
+#define TBS_RIGHT               0x0000
+#define TBS_BOTH                0x0008
+#define TBS_NOTICKS             0x0010
+#define TBS_ENABLESELRANGE      0x0020
+#define TBS_FIXEDLENGTH         0x0040
+#define TBS_NOTHUMB             0x0080
+#define TBS_TOOLTIPS            0x0100
+#define TBS_REVERSED           0x0200
+#define TBS_DOWNISLEFT         0x0400
+
+#define TBTS_TOP                0
+#define TBTS_LEFT               1
+#define TBTS_BOTTOM             2
+#define TBTS_RIGHT              3
+
+#define TB_LINEUP               0
+#define TB_LINEDOWN             1
+#define TB_PAGEUP               2
+#define TB_PAGEDOWN             3
+#define TB_THUMBPOSITION        4
+#define TB_THUMBTRACK           5
+#define TB_TOP                  6
+#define TB_BOTTOM               7
+#define TB_ENDTRACK             8
+
+#define TBCD_TICS               0x0001
+#define TBCD_THUMB              0x0002
+#define TBCD_CHANNEL            0x0003
+
+#define TBM_GETPOS              (WM_USER)
+#define TBM_GETRANGEMIN         (WM_USER+1)
+#define TBM_GETRANGEMAX         (WM_USER+2)
+#define TBM_GETTIC              (WM_USER+3)
+#define TBM_SETTIC              (WM_USER+4)
+#define TBM_SETPOS              (WM_USER+5)
+#define TBM_SETRANGE            (WM_USER+6)
+#define TBM_SETRANGEMIN         (WM_USER+7)
+#define TBM_SETRANGEMAX         (WM_USER+8)
+#define TBM_CLEARTICS           (WM_USER+9)
+#define TBM_SETSEL              (WM_USER+10)
+#define TBM_SETSELSTART         (WM_USER+11)
+#define TBM_SETSELEND           (WM_USER+12)
+#define TBM_GETPTICS            (WM_USER+14)
+#define TBM_GETTICPOS           (WM_USER+15)
+#define TBM_GETNUMTICS          (WM_USER+16)
+#define TBM_GETSELSTART         (WM_USER+17)
+#define TBM_GETSELEND           (WM_USER+18)
+#define TBM_CLEARSEL            (WM_USER+19)
+#define TBM_SETTICFREQ          (WM_USER+20)
+#define TBM_SETPAGESIZE         (WM_USER+21)
+#define TBM_GETPAGESIZE         (WM_USER+22)
+#define TBM_SETLINESIZE         (WM_USER+23)
+#define TBM_GETLINESIZE         (WM_USER+24)
+#define TBM_GETTHUMBRECT        (WM_USER+25)
+#define TBM_GETCHANNELRECT      (WM_USER+26)
+#define TBM_SETTHUMBLENGTH      (WM_USER+27)
+#define TBM_GETTHUMBLENGTH      (WM_USER+28)
+#define TBM_SETTOOLTIPS         (WM_USER+29)
+#define TBM_GETTOOLTIPS         (WM_USER+30)
+#define TBM_SETTIPSIDE          (WM_USER+31)
+#define TBM_SETBUDDY            (WM_USER+32)
+#define TBM_GETBUDDY            (WM_USER+33)
+#define TBM_SETUNICODEFORMAT    CCM_SETUNICODEFORMAT
+#define TBM_GETUNICODEFORMAT    CCM_GETUNICODEFORMAT
+
+
+/* Pager control */
+
+#define WC_PAGESCROLLERA      "SysPager"
+#if defined(__GNUC__)
+# define WC_PAGESCROLLERW (const WCHAR []){ 'S','y','s','P','a','g','e','r',0 }
+#elif defined(_MSC_VER)
+# define WC_PAGESCROLLERW     L"SysPager"
+#else
+static const WCHAR WC_PAGESCROLLERW[] = { 'S','y','s','P','a','g','e','r',0 };
+#endif
+#define WC_PAGESCROLLER  WINELIB_NAME_AW(WC_PAGESCROLLER)
+
+#define PGS_VERT                0x00000000
+#define PGS_HORZ                0x00000001
+#define PGS_AUTOSCROLL          0x00000002
+#define PGS_DRAGNDROP           0x00000004
+
+#define PGF_INVISIBLE           0
+#define PGF_NORMAL              1
+#define PGF_GRAYED              2
+#define PGF_DEPRESSED           4
+#define PGF_HOT                 8
+
+#define PGB_TOPORLEFT           0
+#define PGB_BOTTOMORRIGHT       1
+
+/* only used with PGN_SCROLL */
+#define PGF_SCROLLUP            1
+#define PGF_SCROLLDOWN          2
+#define PGF_SCROLLLEFT          4
+#define PGF_SCROLLRIGHT         8
+
+#define PGK_SHIFT               1
+#define PGK_CONTROL             2
+#define PGK_MENU                4
+
+/* only used with PGN_CALCSIZE */
+#define PGF_CALCWIDTH           1
+#define PGF_CALCHEIGHT          2
+
+#define PGM_FIRST               0x1400
+#define PGM_SETCHILD            (PGM_FIRST+1)
+#define PGM_RECALCSIZE          (PGM_FIRST+2)
+#define PGM_FORWARDMOUSE        (PGM_FIRST+3)
+#define PGM_SETBKCOLOR          (PGM_FIRST+4)
+#define PGM_GETBKCOLOR          (PGM_FIRST+5)
+#define PGM_SETBORDER           (PGM_FIRST+6)
+#define PGM_GETBORDER           (PGM_FIRST+7)
+#define PGM_SETPOS              (PGM_FIRST+8)
+#define PGM_GETPOS              (PGM_FIRST+9)
+#define PGM_SETBUTTONSIZE       (PGM_FIRST+10)
+#define PGM_GETBUTTONSIZE       (PGM_FIRST+11)
+#define PGM_GETBUTTONSTATE      (PGM_FIRST+12)
+#define PGM_GETDROPTARGET       CCM_GETDROPTARGET
+
+#define PGN_FIRST               (0U-900U)
+#define PGN_LAST                (0U-950U)
+#define PGN_SCROLL              (PGN_FIRST-1)
+#define PGN_CALCSIZE            (PGN_FIRST-2)
+
+#include "pshpack1.h"
+
+typedef struct
+{
+    NMHDR hdr;
+    WORD  fwKeys;
+    RECT rcParent;
+    INT  iDir;
+    INT  iXpos;
+    INT  iYpos;
+    INT  iScroll;
+} NMPGSCROLL, *LPNMPGSCROLL;
+
+#include "poppack.h"
+
+typedef struct
+{
+    NMHDR hdr;
+    DWORD dwFlag;
+    INT iWidth;
+    INT iHeight;
+} NMPGCALCSIZE, *LPNMPGCALCSIZE;
+
+
+/* Treeview control */
+
+#define WC_TREEVIEWA          "SysTreeView32"
+#if defined(__GNUC__)
+# define WC_TREEVIEWW (const WCHAR []){ 'S','y','s', \
+  'T','r','e','e','V','i','e','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_TREEVIEWW         L"SysTreeView32"
+#else
+static const WCHAR WC_TREEVIEWW[] = { 'S','y','s',
+  'T','r','e','e','V','i','e','w','3','2',0 };
+#endif
+#define WC_TREEVIEW             WINELIB_NAME_AW(WC_TREEVIEW)
+
+#define TVSIL_NORMAL            0
+#define TVSIL_STATE             2
+
+#define TV_FIRST                0x1100
+#define TVM_INSERTITEMA       (TV_FIRST+0)
+#define TVM_INSERTITEMW       (TV_FIRST+50)
+#define TVM_INSERTITEM          WINELIB_NAME_AW(TVM_INSERTITEM)
+#define TVM_DELETEITEM          (TV_FIRST+1)
+#define TVM_EXPAND              (TV_FIRST+2)
+#define TVM_GETITEMRECT         (TV_FIRST+4)
+#define TVM_GETCOUNT            (TV_FIRST+5)
+#define TVM_GETINDENT           (TV_FIRST+6)
+#define TVM_SETINDENT           (TV_FIRST+7)
+#define TVM_GETIMAGELIST        (TV_FIRST+8)
+#define TVM_SETIMAGELIST        (TV_FIRST+9)
+#define TVM_GETNEXTITEM         (TV_FIRST+10)
+#define TVM_SELECTITEM          (TV_FIRST+11)
+#define TVM_GETITEMA          (TV_FIRST+12)
+#define TVM_GETITEMW          (TV_FIRST+62)
+#define TVM_GETITEM             WINELIB_NAME_AW(TVM_GETITEM)
+#define TVM_SETITEMA          (TV_FIRST+13)
+#define TVM_SETITEMW          (TV_FIRST+63)
+#define TVM_SETITEM             WINELIB_NAME_AW(TVM_SETITEM)
+#define TVM_EDITLABELA        (TV_FIRST+14)
+#define TVM_EDITLABELW        (TV_FIRST+65)
+#define TVM_EDITLABEL           WINELIB_NAME_AW(TVM_EDITLABEL)
+#define TVM_GETEDITCONTROL      (TV_FIRST+15)
+#define TVM_GETVISIBLECOUNT     (TV_FIRST+16)
+#define TVM_HITTEST             (TV_FIRST+17)
+#define TVM_CREATEDRAGIMAGE     (TV_FIRST+18)
+#define TVM_SORTCHILDREN        (TV_FIRST+19)
+#define TVM_ENSUREVISIBLE       (TV_FIRST+20)
+#define TVM_SORTCHILDRENCB      (TV_FIRST+21)
+#define TVM_ENDEDITLABELNOW     (TV_FIRST+22)
+#define TVM_GETISEARCHSTRINGA (TV_FIRST+23)
+#define TVM_GETISEARCHSTRINGW (TV_FIRST+64)
+#define TVM_GETISEARCHSTRING    WINELIB_NAME_AW(TVM_GETISEARCHSTRING)
+#define TVM_SETTOOLTIPS         (TV_FIRST+24)
+#define TVM_GETTOOLTIPS         (TV_FIRST+25)
+#define TVM_SETINSERTMARK       (TV_FIRST+26)
+#define TVM_SETITEMHEIGHT       (TV_FIRST+27)
+#define TVM_GETITEMHEIGHT       (TV_FIRST+28)
+#define TVM_SETBKCOLOR          (TV_FIRST+29)
+#define TVM_SETTEXTCOLOR        (TV_FIRST+30)
+#define TVM_GETBKCOLOR          (TV_FIRST+31)
+#define TVM_GETTEXTCOLOR        (TV_FIRST+32)
+#define TVM_SETSCROLLTIME       (TV_FIRST+33)
+#define TVM_GETSCROLLTIME       (TV_FIRST+34)
+#define TVM_UNKNOWN35           (TV_FIRST+35)
+#define TVM_UNKNOWN36           (TV_FIRST+36)
+#define TVM_SETINSERTMARKCOLOR  (TV_FIRST+37)
+#define TVM_GETINSERTMARKCOLOR  (TV_FIRST+38)
+#define TVM_GETITEMSTATE        (TV_FIRST+39)
+#define TVM_SETLINECOLOR        (TV_FIRST+40)
+#define TVM_GETLINECOLOR        (TV_FIRST+41)
+#define TVM_SETUNICODEFORMAT    CCM_SETUNICODEFORMAT
+#define TVM_GETUNICODEFORMAT    CCM_GETUNICODEFORMAT
+
+
+
+#define TVN_FIRST               (0U-400U)
+#define TVN_LAST                (0U-499U)
+
+#define TVN_SELCHANGINGA        (TVN_FIRST-1)
+#define TVN_SELCHANGINGW        (TVN_FIRST-50)
+#define TVN_SELCHANGING         WINELIB_NAME_AW(TVN_SELCHANGING)
+
+#define TVN_SELCHANGEDA         (TVN_FIRST-2)
+#define TVN_SELCHANGEDW         (TVN_FIRST-51)
+#define TVN_SELCHANGED          WINELIB_NAME_AW(TVN_SELCHANGED)
+
+#define TVN_GETDISPINFOA        (TVN_FIRST-3)
+#define TVN_GETDISPINFOW        (TVN_FIRST-52)
+#define TVN_GETDISPINFO         WINELIB_NAME_AW(TVN_GETDISPINFO)
+
+#define TVN_SETDISPINFOA        (TVN_FIRST-4)
+#define TVN_SETDISPINFOW        (TVN_FIRST-53)
+#define TVN_SETDISPINFO         WINELIB_NAME_AW(TVN_SETDISPINFO)
+
+#define TVN_ITEMEXPANDINGA      (TVN_FIRST-5)
+#define TVN_ITEMEXPANDINGW      (TVN_FIRST-54)
+#define TVN_ITEMEXPANDING       WINELIB_NAME_AW(TVN_ITEMEXPANDING)
+
+#define TVN_ITEMEXPANDEDA       (TVN_FIRST-6)
+#define TVN_ITEMEXPANDEDW       (TVN_FIRST-55)
+#define TVN_ITEMEXPANDED        WINELIB_NAME_AW(TVN_ITEMEXPANDED)
+
+#define TVN_BEGINDRAGA          (TVN_FIRST-7)
+#define TVN_BEGINDRAGW          (TVN_FIRST-56)
+#define TVN_BEGINDRAG           WINELIB_NAME_AW(TVN_BEGINDRAG)
+
+#define TVN_BEGINRDRAGA         (TVN_FIRST-8)
+#define TVN_BEGINRDRAGW         (TVN_FIRST-57)
+#define TVN_BEGINRDRAG          WINELIB_NAME_AW(TVN_BEGINRDRAG)
+
+#define TVN_DELETEITEMA         (TVN_FIRST-9)
+#define TVN_DELETEITEMW         (TVN_FIRST-58)
+#define TVN_DELETEITEM          WINELIB_NAME_AW(TVN_DELETEITEM)
+
+#define TVN_BEGINLABELEDITA     (TVN_FIRST-10)
+#define TVN_BEGINLABELEDITW     (TVN_FIRST-59)
+#define TVN_BEGINLABELEDIT      WINELIB_NAME_AW(TVN_BEGINLABELEDIT)
+
+#define TVN_ENDLABELEDITA       (TVN_FIRST-11)
+#define TVN_ENDLABELEDITW       (TVN_FIRST-60)
+#define TVN_ENDLABELEDIT        WINELIB_NAME_AW(TVN_ENDLABELEDIT)
+
+#define TVN_KEYDOWN             (TVN_FIRST-12)
+
+#define TVN_GETINFOTIPA         (TVN_FIRST-13)
+#define TVN_GETINFOTIPW         (TVN_FIRST-14)
+#define TVN_GETINFOTIP          WINELIB_NAME_AW(TVN_GETINFOTIP)
+
+#define TVN_SINGLEEXPAND        (TVN_FIRST-15)
+
+
+
+
+
+#define TVIF_TEXT             0x0001
+#define TVIF_IMAGE            0x0002
+#define TVIF_PARAM            0x0004
+#define TVIF_STATE            0x0008
+#define TVIF_HANDLE           0x0010
+#define TVIF_SELECTEDIMAGE    0x0020
+#define TVIF_CHILDREN         0x0040
+#define TVIF_INTEGRAL         0x0080
+#define TVIF_DI_SETITEM                  0x1000
+
+#define TVI_ROOT              ((HTREEITEM)0xffff0000)     /* -65536 */
+#define TVI_FIRST             ((HTREEITEM)0xffff0001)     /* -65535 */
+#define TVI_LAST              ((HTREEITEM)0xffff0002)     /* -65534 */
+#define TVI_SORT              ((HTREEITEM)0xffff0003)     /* -65533 */
+
+#define TVIS_FOCUSED          0x0001
+#define TVIS_SELECTED         0x0002
+#define TVIS_CUT              0x0004
+#define TVIS_DROPHILITED      0x0008
+#define TVIS_BOLD             0x0010
+#define TVIS_EXPANDED         0x0020
+#define TVIS_EXPANDEDONCE     0x0040
+#define TVIS_EXPANDPARTIAL    0x0080
+#define TVIS_OVERLAYMASK      0x0f00
+#define TVIS_STATEIMAGEMASK   0xf000
+#define TVIS_USERMASK         0xf000
+
+#define TVHT_NOWHERE          0x0001
+#define TVHT_ONITEMICON       0x0002
+#define TVHT_ONITEMLABEL      0x0004
+#define TVHT_ONITEMINDENT     0x0008
+#define TVHT_ONITEMBUTTON     0x0010
+#define TVHT_ONITEMRIGHT      0x0020
+#define TVHT_ONITEMSTATEICON  0x0040
+#define TVHT_ONITEM           0x0046
+#define TVHT_ABOVE            0x0100
+#define TVHT_BELOW            0x0200
+#define TVHT_TORIGHT          0x0400
+#define TVHT_TOLEFT           0x0800
+
+#define TVS_HASBUTTONS        0x0001
+#define TVS_HASLINES          0x0002
+#define TVS_LINESATROOT       0x0004
+#define TVS_EDITLABELS        0x0008
+#define TVS_DISABLEDRAGDROP   0x0010
+#define TVS_SHOWSELALWAYS     0x0020
+#define TVS_RTLREADING        0x0040
+#define TVS_NOTOOLTIPS        0x0080
+#define TVS_CHECKBOXES        0x0100
+#define TVS_TRACKSELECT       0x0200
+#define TVS_SINGLEEXPAND         0x0400
+#define TVS_INFOTIP              0x0800
+#define TVS_FULLROWSELECT        0x1000
+#define TVS_NOSCROLL             0x2000
+#define TVS_NONEVENHEIGHT        0x4000
+#define TVS_NOHSCROLL         0x8000
+
+#define TVS_SHAREDIMAGELISTS  0x0000
+#define TVS_PRIVATEIMAGELISTS 0x0400
+
+
+#define TVE_COLLAPSE          0x0001
+#define TVE_EXPAND            0x0002
+#define TVE_TOGGLE            0x0003
+#define TVE_EXPANDPARTIAL     0x4000
+#define TVE_COLLAPSERESET     0x8000
+
+#define TVGN_ROOT             0
+#define TVGN_NEXT             1
+#define TVGN_PREVIOUS         2
+#define TVGN_PARENT           3
+#define TVGN_CHILD            4
+#define TVGN_FIRSTVISIBLE     5
+#define TVGN_NEXTVISIBLE      6
+#define TVGN_PREVIOUSVISIBLE  7
+#define TVGN_DROPHILITE       8
+#define TVGN_CARET            9
+#define TVGN_LASTVISIBLE      10
+
+#define TVC_UNKNOWN           0x00
+#define TVC_BYMOUSE           0x01
+#define TVC_BYKEYBOARD        0x02
+
+
+typedef struct _TREEITEM *HTREEITEM;
+
+typedef struct {
+      UINT mask;
+      HTREEITEM hItem;
+      UINT state;
+      UINT stateMask;
+      LPSTR  pszText;
+      INT  cchTextMax;
+      INT  iImage;
+      INT  iSelectedImage;
+      INT  cChildren;
+      LPARAM lParam;
+} TVITEMA, *LPTVITEMA;
+
+typedef struct {
+      UINT mask;
+      HTREEITEM hItem;
+      UINT state;
+      UINT stateMask;
+      LPWSTR pszText;
+      INT cchTextMax;
+      INT iImage;
+      INT iSelectedImage;
+      INT cChildren;
+      LPARAM lParam;
+} TVITEMW, *LPTVITEMW;
+
+#define TV_ITEMA    TVITEMA
+#define TV_ITEMW    TVITEMW
+#define LPTV_ITEMA  LPTVITEMA
+#define LPTV_ITEMW  LPTVITEMW
+
+#define TVITEM      WINELIB_NAME_AW(TVITEM)
+#define LPTVITEM    WINELIB_NAME_AW(LPTVITEM)
+#define TV_ITEM     WINELIB_NAME_AW(TV_ITEM)
+#define LPTV_ITEM   WINELIB_NAME_AW(LPTV_ITEM)
+
+typedef struct {
+      UINT mask;
+      HTREEITEM hItem;
+      UINT state;
+      UINT stateMask;
+      LPSTR  pszText;
+      INT  cchTextMax;
+      INT  iImage;
+      INT  iSelectedImage;
+      INT  cChildren;
+      LPARAM lParam;
+      INT iIntegral;
+} TVITEMEXA, *LPTVITEMEXA;
+
+typedef struct {
+      UINT mask;
+      HTREEITEM hItem;
+      UINT state;
+      UINT stateMask;
+      LPWSTR pszText;
+      INT cchTextMax;
+      INT iImage;
+      INT iSelectedImage;
+      INT cChildren;
+      LPARAM lParam;
+      INT iIntegral;
+} TVITEMEXW, *LPTVITEMEXW;
+
+#define TVITEMEX   WINELIB_NAME_AW(TVITEMEX)
+#define LPTVITEMEX WINELIB_NAME_AW(LPTVITEMEX)
+
+typedef struct tagTVINSERTSTRUCTA {
+        HTREEITEM hParent;
+        HTREEITEM hInsertAfter;
+        union {
+           TVITEMEXA itemex;
+           TVITEMA   item;
+        } DUMMYUNIONNAME;
+} TVINSERTSTRUCTA, *LPTVINSERTSTRUCTA;
+
+typedef struct tagTVINSERTSTRUCTW {
+        HTREEITEM hParent;
+        HTREEITEM hInsertAfter;
+        union {
+           TVITEMEXW itemex;
+           TVITEMW   item;
+        } DUMMYUNIONNAME;
+} TVINSERTSTRUCTW, *LPTVINSERTSTRUCTW;
+
+#define TVINSERTSTRUCT    WINELIB_NAME_AW(TVINSERTSTRUCT)
+#define LPTVINSERTSTRUCT  WINELIB_NAME_AW(LPTVINSERTSTRUCT)
+
+#define TVINSERTSTRUCT_V1_SIZEA CCSIZEOF_STRUCT(TVINSERTSTRUCTA, item)
+#define TVINSERTSTRUCT_V1_SIZEW CCSIZEOF_STRUCT(TVINSERTSTRUCTW, item)
+#define TVINSERTSTRUCT_V1_SIZE    WINELIB_NAME_AW(TVINSERTSTRUCT_V1_SIZE)
+
+#define TV_INSERTSTRUCT    TVINSERTSTRUCT
+#define TV_INSERTSTRUCTA   TVINSERTSTRUCTA
+#define TV_INSERTSTRUCTW   TVINSERTSTRUCTW
+#define LPTV_INSERTSTRUCT  LPTVINSERTSTRUCT
+#define LPTV_INSERTSTRUCTA LPTVINSERTSTRUCTA
+#define LPTV_INSERTSTRUCTW LPTVINSERTSTRUCTW
+
+
+
+typedef struct tagNMTREEVIEWA {
+       NMHDR   hdr;
+       UINT    action;
+       TVITEMA itemOld;
+       TVITEMA itemNew;
+       POINT   ptDrag;
+} NMTREEVIEWA, *LPNMTREEVIEWA;
+
+typedef struct tagNMTREEVIEWW {
+       NMHDR   hdr;
+       UINT    action;
+       TVITEMW itemOld;
+       TVITEMW itemNew;
+       POINT   ptDrag;
+} NMTREEVIEWW, *LPNMTREEVIEWW;
+
+#define NMTREEVIEW     WINELIB_NAME_AW(NMTREEVIEW)
+#define NM_TREEVIEW    WINELIB_NAME_AW(NMTREEVIEW)
+#define LPNMTREEVIEW   WINELIB_NAME_AW(LPNMTREEVIEW)
+
+#define LPNM_TREEVIEW           LPNMTREEVIEW
+
+typedef struct tagTVDISPINFOA {
+       NMHDR   hdr;
+       TVITEMA item;
+} NMTVDISPINFOA, *LPNMTVDISPINFOA;
+
+typedef struct tagTVDISPINFOW {
+       NMHDR   hdr;
+       TVITEMW item;
+} NMTVDISPINFOW, *LPNMTVDISPINFOW;
+
+#define NMTVDISPINFO            WINELIB_NAME_AW(NMTVDISPINFO)
+#define LPNMTVDISPINFO          WINELIB_NAME_AW(LPNMTVDISPINFO)
+#define TV_DISPINFO             NMTVDISPINFO
+
+typedef INT (CALLBACK *PFNTVCOMPARE)(LPARAM, LPARAM, LPARAM);
+
+typedef struct tagTVSORTCB
+{
+       HTREEITEM hParent;
+       PFNTVCOMPARE lpfnCompare;
+       LPARAM lParam;
+} TVSORTCB, *LPTVSORTCB;
+
+#define TV_SORTCB TVSORTCB
+#define LPTV_SORTCB LPTVSORTCB
+
+typedef struct tagTVHITTESTINFO {
+        POINT pt;
+        UINT flags;
+        HTREEITEM hItem;
+} TVHITTESTINFO, *LPTVHITTESTINFO;
+
+#define TV_HITTESTINFO TVHITTESTINFO
+
+
+/* Custom Draw Treeview */
+
+#define NMTVCUSTOMDRAW_V3_SIZE CCSIZEOF_STRUCT(NMTVCUSTOMDRAW, clrTextBk)
+
+#define TVCDRF_NOIMAGES     0x00010000
+
+typedef struct tagNMTVCUSTOMDRAW
+{
+    NMCUSTOMDRAW nmcd;
+    COLORREF     clrText;
+    COLORREF     clrTextBk;
+    INT iLevel;                 /* IE>0x0400 */
+} NMTVCUSTOMDRAW, *LPNMTVCUSTOMDRAW;
+
+/* Treeview tooltips */
+
+typedef struct tagNMTVGETINFOTIPA
+{
+    NMHDR hdr;
+    LPSTR pszText;
+    INT cchTextMax;
+    HTREEITEM hItem;
+    LPARAM lParam;
+} NMTVGETINFOTIPA, *LPNMTVGETINFOTIPA;
+
+typedef struct tagNMTVGETINFOTIPW
+{
+    NMHDR hdr;
+    LPWSTR pszText;
+    INT cchTextMax;
+    HTREEITEM hItem;
+    LPARAM lParam;
+} NMTVGETINFOTIPW, *LPNMTVGETINFOTIPW;
+
+#define NMTVGETINFOTIP WINELIB_NAME_AW(NMTVGETINFOTIP)
+#define LPNMTVGETINFOTIP WINELIB_NAME_AW(LPNMTVGETINFOTIP)
+
+#include "pshpack1.h"
+typedef struct tagTVKEYDOWN
+{
+    NMHDR hdr;
+    WORD wVKey;
+    UINT flags;
+} NMTVKEYDOWN, *LPNMTVKEYDOWN;
+#include "poppack.h"
+
+#define TV_KEYDOWN      NMTVKEYDOWN
+
+#define TreeView_InsertItemA(hwnd, phdi) \
+  (HTREEITEM)SNDMSGA((hwnd), TVM_INSERTITEMA, 0, \
+                            (LPARAM)(LPTVINSERTSTRUCTA)(phdi))
+#define TreeView_InsertItemW(hwnd,phdi) \
+  (HTREEITEM)SNDMSGW((hwnd), TVM_INSERTITEMW, 0, \
+                            (LPARAM)(LPTVINSERTSTRUCTW)(phdi))
+#define TreeView_InsertItem WINELIB_NAME_AW(TreeView_InsertItem)
+
+#define TreeView_DeleteItem(hwnd, hItem) \
+  (BOOL)SNDMSGA((hwnd), TVM_DELETEITEM, 0, (LPARAM)(HTREEITEM)(hItem))
+#define TreeView_DeleteAllItems(hwnd) \
+  (BOOL)SNDMSGA((hwnd), TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT)
+#define TreeView_Expand(hwnd, hitem, code) \
+ (BOOL)SNDMSGA((hwnd), TVM_EXPAND, (WPARAM)code, \
+       (LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_GetItemRect(hwnd, hitem, prc, code) \
+ (*(HTREEITEM *)prc = (hitem), (BOOL)SNDMSGA((hwnd), \
+                       TVM_GETITEMRECT, (WPARAM)(code), (LPARAM)(RECT *)(prc)))
+
+#define TreeView_GetCount(hwnd) \
+    (UINT)SNDMSGA((hwnd), TVM_GETCOUNT, 0, 0)
+#define TreeView_GetIndent(hwnd) \
+    (UINT)SNDMSGA((hwnd), TVM_GETINDENT, 0, 0)
+#define TreeView_SetIndent(hwnd, indent) \
+    (BOOL)SNDMSGA((hwnd), TVM_SETINDENT, (WPARAM)indent, 0)
+
+#define TreeView_GetImageList(hwnd, iImage) \
+    (HIMAGELIST)SNDMSGA((hwnd), TVM_GETIMAGELIST, iImage, 0)
+
+#define TreeView_SetImageList(hwnd, himl, iImage) \
+    (HIMAGELIST)SNDMSGA((hwnd), TVM_SETIMAGELIST, iImage, \
+ (LPARAM)(UINT)(HIMAGELIST)(himl))
+
+#define TreeView_GetNextItem(hwnd, hitem, code) \
+    (HTREEITEM)SNDMSGA((hwnd), TVM_GETNEXTITEM, (WPARAM)code,\
+(LPARAM)(HTREEITEM) (hitem))
+
+#define TreeView_GetChild(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_CHILD)
+#define TreeView_GetNextSibling(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_NEXT)
+#define TreeView_GetPrevSibling(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_PREVIOUS)
+#define TreeView_GetParent(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_PARENT)
+#define TreeView_GetFirstVisible(hwnd)  \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_FIRSTVISIBLE)
+#define TreeView_GetLastVisible(hwnd)   \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_LASTVISIBLE)
+#define TreeView_GetNextVisible(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_NEXTVISIBLE)
+#define TreeView_GetPrevVisible(hwnd, hitem) \
+               TreeView_GetNextItem(hwnd, hitem , TVGN_PREVIOUSVISIBLE)
+#define TreeView_GetSelection(hwnd) \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_CARET)
+#define TreeView_GetDropHilight(hwnd) \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_DROPHILITE)
+#define TreeView_GetRoot(hwnd) \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_ROOT)
+#define TreeView_GetLastVisible(hwnd) \
+               TreeView_GetNextItem(hwnd, NULL, TVGN_LASTVISIBLE)
+
+
+#define TreeView_Select(hwnd, hitem, code) \
+ (UINT)SNDMSGA((hwnd), TVM_SELECTITEM, (WPARAM)code, \
+(LPARAM)(UINT)(hitem))
+
+
+#define TreeView_SelectItem(hwnd, hitem) \
+               TreeView_Select(hwnd, hitem, TVGN_CARET)
+#define TreeView_SelectDropTarget(hwnd, hitem) \
+               TreeView_Select(hwnd, hitem, TVGN_DROPHILITE)
+#define TreeView_SelectSetFirstVisible(hwnd, hitem) \
+               TreeView_Select(hwnd, hitem, TVGN_FIRSTVISIBLE)
+
+
+#define TreeView_GetItemA(hwnd, pitem) \
+ (BOOL)SNDMSGA((hwnd), TVM_GETITEMA, 0, (LPARAM) (TVITEMA *)(pitem))
+#define TreeView_GetItemW(hwnd, pitem) \
+ (BOOL)SNDMSGW((hwnd), TVM_GETITEMA, 0, (LPARAM) (TVITEMA *)(pitem))
+#define TreeView_GetItem WINELIB_NAME_AW(TreeView_GetItem)
+
+#define TreeView_SetItemA(hwnd, pitem) \
+ (BOOL)SNDMSGA((hwnd), TVM_SETITEMA, 0, (LPARAM)(const TVITEMA *)(pitem))
+#define TreeView_SetItemW(hwnd, pitem) \
+ (BOOL)SNDMSGW((hwnd), TVM_SETITEMA, 0, (LPARAM)(const TVITEMA *)(pitem))
+#define TreeView_SetItem WINELIB_NAME_AW(TreeView_SetItem)
+
+#define TreeView_EditLabel(hwnd, hitem) \
+    (HWND)SNDMSGA((hwnd), TVM_EDITLABEL, 0, (LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_GetEditControl(hwnd) \
+    (HWND)SNDMSGA((hwnd), TVM_GETEDITCONTROL, 0, 0)
+
+#define TreeView_GetVisibleCount(hwnd) \
+    (UINT)SNDMSGA((hwnd), TVM_GETVISIBLECOUNT, 0, 0)
+
+#define TreeView_HitTest(hwnd, lpht) \
+    (HTREEITEM)SNDMSGA((hwnd), TVM_HITTEST, 0,\
+(LPARAM)(LPTVHITTESTINFO)(lpht))
+
+#define TreeView_CreateDragImage(hwnd, hitem) \
+    (HIMAGELIST)SNDMSGA((hwnd), TVM_CREATEDRAGIMAGE, 0,\
+(LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_SortChildren(hwnd, hitem, recurse) \
+    (BOOL)SNDMSGA((hwnd), TVM_SORTCHILDREN, (WPARAM)recurse,\
+(LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_EnsureVisible(hwnd, hitem) \
+    (BOOL)SNDMSGA((hwnd), TVM_ENSUREVISIBLE, 0, (LPARAM)(UINT)(hitem))
+
+#define TreeView_SortChildrenCB(hwnd, psort, recurse) \
+    (BOOL)SNDMSGA((hwnd), TVM_SORTCHILDRENCB, (WPARAM)recurse, \
+    (LPARAM)(LPTV_SORTCB)(psort))
+
+#define TreeView_EndEditLabelNow(hwnd, fCancel) \
+    (BOOL)SNDMSGA((hwnd), TVM_ENDEDITLABELNOW, (WPARAM)fCancel, 0)
+
+#define TreeView_GetISearchString(hwnd, lpsz) \
+    (BOOL)SNDMSGA((hwnd), TVM_GETISEARCHSTRING, 0, \
+                                                       (LPARAM)(LPTSTR)lpsz)
+
+#define TreeView_SetToolTips(hwnd,  hwndTT) \
+    (HWND)SNDMSGA((hwnd), TVM_SETTOOLTIPS, (WPARAM)(hwndTT), 0)
+
+#define TreeView_GetToolTips(hwnd) \
+    (HWND)SNDMSGA((hwnd), TVM_GETTOOLTIPS, 0, 0)
+
+#define TreeView_SetItemHeight(hwnd,  iHeight) \
+    (INT)SNDMSGA((hwnd), TVM_SETITEMHEIGHT, (WPARAM)iHeight, 0)
+
+#define TreeView_GetItemHeight(hwnd) \
+    (INT)SNDMSGA((hwnd), TVM_GETITEMHEIGHT, 0, 0)
+
+#define TreeView_SetBkColor(hwnd, clr) \
+    (COLORREF)SNDMSGA((hwnd), TVM_SETBKCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_SetTextColor(hwnd, clr) \
+    (COLORREF)SNDMSGA((hwnd), TVM_SETTEXTCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_GetBkColor(hwnd) \
+    (COLORREF)SNDMSGA((hwnd), TVM_GETBKCOLOR, 0, 0)
+
+#define TreeView_GetTextColor(hwnd) \
+    (COLORREF)SNDMSGA((hwnd), TVM_GETTEXTCOLOR, 0, 0)
+
+#define TreeView_SetScrollTime(hwnd, uTime) \
+    (UINT)SNDMSGA((hwnd), TVM_SETSCROLLTIME, uTime, 0)
+
+#define TreeView_GetScrollTime(hwnd) \
+    (UINT)SNDMSGA((hwnd), TVM_GETSCROLLTIME, 0, 0)
+
+#define TreeView_SetInsertMark(hwnd, hItem, fAfter) \
+    (BOOL)SNDMSGA((hwnd), TVM_SETINSERTMARK, (WPARAM)(fAfter), \
+                       (LPARAM) (hItem))
+
+#define TreeView_SetInsertMarkColor(hwnd, clr) \
+    (COLORREF)SNDMSGA((hwnd), TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_GetInsertMarkColor(hwnd) \
+    (COLORREF)SNDMSGA((hwnd), TVM_GETINSERTMARKCOLOR, 0, 0)
+
+#define TreeView_GetItemState(hwndTV, hti, mask) \
+   (UINT)SNDMSGA((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti), (LPARAM)(mask))
+#define TreeView_GetCheckState(hwndTV, hti) \
+   ((((UINT)(SNDMSGA((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti),  \
+                     TVIS_STATEIMAGEMASK))) >> 12) -1)
+
+#define TreeView_SetLineColor(hwnd, clr) \
+    (COLORREF)SNDMSGA((hwnd), TVM_SETLINECOLOR, 0, (LPARAM)(clr))
+
+#define TreeView_GetLineColor(hwnd) \
+    (COLORREF)SNDMSGA((hwnd), TVM_GETLINECOLOR, 0, 0)
+
+#define TreeView_SetItemState(hwndTV, hti, data, _mask) \
+{ TVITEM _TVi; \
+  _TVi.mask = TVIF_STATE; \
+  _TVi.hItem = hti; \
+  _TVi.stateMask = _mask; \
+  _TVi.state = data; \
+  SNDMSGA((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_TVi); \
+}
+
+
+/* Listview control */
+
+#define WC_LISTVIEWA          "SysListView32"
+#if defined(__GNUC__)
+# define WC_LISTVIEWW (const WCHAR []){ 'S','y','s', \
+  'L','i','s','t','V','i','e','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_LISTVIEWW         L"SysListView32"
+#else
+static const WCHAR WC_LISTVIEWW[] = { 'S','y','s',
+  'L','i','s','t','V','i','e','w','3','2',0 };
+#endif
+#define WC_LISTVIEW  WINELIB_NAME_AW(WC_LISTVIEW)
+
+#define LVSCW_AUTOSIZE -1
+#define LVSCW_AUTOSIZE_USEHEADER -2
+
+#define LVS_ICON                0x0000
+#define LVS_REPORT              0x0001
+#define LVS_SMALLICON           0x0002
+#define LVS_LIST                0x0003
+#define LVS_TYPEMASK            0x0003
+#define LVS_SINGLESEL           0x0004
+#define LVS_SHOWSELALWAYS       0x0008
+#define LVS_SORTASCENDING       0x0010
+#define LVS_SORTDESCENDING      0x0020
+#define LVS_SHAREIMAGELISTS     0x0040
+#define LVS_NOLABELWRAP         0x0080
+#define LVS_AUTOARRANGE         0x0100
+#define LVS_EDITLABELS          0x0200
+#define LVS_OWNERDATA           0x1000
+#define LVS_NOSCROLL            0x2000
+#define LVS_TYPESTYLEMASK       0xfc00
+#define LVS_ALIGNTOP            0x0000
+#define LVS_ALIGNLEFT           0x0800
+#define LVS_ALIGNMASK           0x0c00
+#define LVS_OWNERDRAWFIXED      0x0400
+#define LVS_NOCOLUMNHEADER      0x4000
+#define LVS_NOSORTHEADER        0x8000
+
+#define LVS_EX_GRIDLINES        0x0001
+#define LVS_EX_SUBITEMIMAGES    0x0002
+#define LVS_EX_CHECKBOXES       0x0004
+#define LVS_EX_TRACKSELECT      0x0008
+#define LVS_EX_HEADERDRAGDROP   0x0010
+#define LVS_EX_FULLROWSELECT    0x0020
+#define LVS_EX_ONECLICKACTIVATE 0x0040
+#define LVS_EX_TWOCLICKACTIVATE 0x0080
+#define LVS_EX_FLATSB           0x0100
+#define LVS_EX_REGIONAL         0x0200
+#define LVS_EX_INFOTIP          0x0400
+#define LVS_EX_UNDERLINEHOT     0x0800
+#define LVS_EX_UNDERLINECOLD    0x1000
+#define LVS_EX_MULTIWORKAREAS   0x2000
+
+#define LVCF_FMT                0x0001
+#define LVCF_WIDTH              0x0002
+#define LVCF_TEXT               0x0004
+#define LVCF_SUBITEM            0x0008
+#define LVCF_IMAGE              0x0010
+#define LVCF_ORDER              0x0020
+
+#define LVCFMT_LEFT             0x0000
+#define LVCFMT_RIGHT            0x0001
+#define LVCFMT_CENTER           0x0002
+#define LVCFMT_JUSTIFYMASK      0x0003
+#define LVCFMT_IMAGE            0x0800
+#define LVCFMT_BITMAP_ON_RIGHT  0x1000
+#define LVCFMT_COL_HAS_IMAGES   0x8000
+
+#define LVSIL_NORMAL            0
+#define LVSIL_SMALL             1
+#define LVSIL_STATE             2
+
+/* following 2 flags only for LVS_OWNERDATA listviews */
+/* and only in report or list mode */
+#define LVSICF_NOINVALIDATEALL  0x0001
+#define LVSICF_NOSCROLL         0x0002
+
+
+#define LVFI_PARAM              0X0001
+#define LVFI_STRING             0X0002
+#define LVFI_PARTIAL            0X0008
+#define LVFI_WRAP               0X0020
+#define LVFI_NEARESTXY          0X0040
+
+#define LVIF_TEXT               0x0001
+#define LVIF_IMAGE              0x0002
+#define LVIF_PARAM              0x0004
+#define LVIF_STATE              0x0008
+#define LVIF_INDENT             0x0010
+#define LVIF_NORECOMPUTE        0x0800
+#define LVIF_DI_SETITEM         0x1000
+
+#define LVIR_BOUNDS             0x0000
+#define LVIR_LABEL              0x0002
+#define LVIR_ICON               0x0001
+#define LVIR_SELECTBOUNDS       0x0003
+
+#define LVIS_FOCUSED            0x0001
+#define LVIS_SELECTED           0x0002
+#define LVIS_CUT                0x0004
+#define LVIS_DROPHILITED        0x0008
+#define LVIS_ACTIVATING         0x0020
+
+#define LVIS_OVERLAYMASK        0x0F00
+#define LVIS_STATEIMAGEMASK     0xF000
+
+#define LVNI_ALL               0x0000
+#define LVNI_FOCUSED           0x0001
+#define LVNI_SELECTED          0x0002
+#define LVNI_CUT               0x0004
+#define LVNI_DROPHILITED       0x0008
+
+#define LVNI_ABOVE             0x0100
+#define LVNI_BELOW             0x0200
+#define LVNI_TOLEFT            0x0400
+#define LVNI_TORIGHT           0x0800
+
+#define LVHT_NOWHERE           0x0001
+#define LVHT_ONITEMICON                0x0002
+#define LVHT_ONITEMLABEL       0x0004
+#define LVHT_ONITEMSTATEICON   0x0008
+#define LVHT_ONITEM            (LVHT_ONITEMICON|LVHT_ONITEMLABEL|LVHT_ONITEMSTATEICON)
+
+#define LVHT_ABOVE             0x0008
+#define LVHT_BELOW             0x0010
+#define LVHT_TORIGHT           0x0020
+#define LVHT_TOLEFT            0x0040
+
+#define LVM_FIRST               0x1000
+#define LVM_GETBKCOLOR          (LVM_FIRST+0)
+#define LVM_SETBKCOLOR          (LVM_FIRST+1)
+#define LVM_GETIMAGELIST        (LVM_FIRST+2)
+#define LVM_SETIMAGELIST        (LVM_FIRST+3)
+#define LVM_GETITEMCOUNT        (LVM_FIRST+4)
+#define LVM_GETITEMA          (LVM_FIRST+5)
+#define LVM_GETITEMW          (LVM_FIRST+75)
+#define LVM_GETITEM             WINELIB_NAME_AW(LVM_GETITEM)
+#define LVM_SETITEMA          (LVM_FIRST+6)
+#define LVM_SETITEMW          (LVM_FIRST+76)
+#define LVM_SETITEM             WINELIB_NAME_AW(LVM_SETITEM)
+#define LVM_INSERTITEMA       (LVM_FIRST+7)
+#define LVM_INSERTITEMW       (LVM_FIRST+77)
+#define LVM_INSERTITEM          WINELIB_NAME_AW(LVM_INSERTITEM)
+#define LVM_DELETEITEM          (LVM_FIRST+8)
+#define LVM_DELETEALLITEMS      (LVM_FIRST+9)
+#define LVM_GETCALLBACKMASK     (LVM_FIRST+10)
+#define LVM_SETCALLBACKMASK     (LVM_FIRST+11)
+#define LVM_GETNEXTITEM         (LVM_FIRST+12)
+#define LVM_FINDITEMA         (LVM_FIRST+13)
+#define LVM_FINDITEMW         (LVM_FIRST+83)
+#define LVM_FINDITEM            WINELIB_NAME_AW(LVM_FINDITEM)
+#define LVM_GETITEMRECT         (LVM_FIRST+14)
+#define LVM_SETITEMPOSITION     (LVM_FIRST+15)
+#define LVM_GETITEMPOSITION     (LVM_FIRST+16)
+#define LVM_GETSTRINGWIDTHA   (LVM_FIRST+17)
+#define LVM_GETSTRINGWIDTHW   (LVM_FIRST+87)
+#define LVM_GETSTRINGWIDTH      WINELIB_NAME_AW(LVM_GETSTRINGWIDTH)
+#define LVM_HITTEST             (LVM_FIRST+18)
+#define LVM_ENSUREVISIBLE       (LVM_FIRST+19)
+#define LVM_SCROLL              (LVM_FIRST+20)
+#define LVM_REDRAWITEMS         (LVM_FIRST+21)
+#define LVM_ARRANGE             (LVM_FIRST+22)
+#define LVM_EDITLABELA        (LVM_FIRST+23)
+#define LVM_EDITLABELW        (LVM_FIRST+118)
+#define LVM_EDITLABEL           WINELIB_NAME_AW(LVM_EDITLABEL)
+#define LVM_GETEDITCONTROL      (LVM_FIRST+24)
+#define LVM_GETCOLUMNA        (LVM_FIRST+25)
+#define LVM_GETCOLUMNW        (LVM_FIRST+95)
+#define LVM_GETCOLUMN           WINELIB_NAME_AW(LVM_GETCOLUMN)
+#define LVM_SETCOLUMNA        (LVM_FIRST+26)
+#define LVM_SETCOLUMNW        (LVM_FIRST+96)
+#define LVM_SETCOLUMN           WINELIB_NAME_AW(LVM_SETCOLUMN)
+#define LVM_INSERTCOLUMNA     (LVM_FIRST+27)
+#define LVM_INSERTCOLUMNW     (LVM_FIRST+97)
+#define LVM_INSERTCOLUMN        WINELIB_NAME_AW(LVM_INSERTCOLUMN)
+#define LVM_DELETECOLUMN        (LVM_FIRST+28)
+#define LVM_GETCOLUMNWIDTH      (LVM_FIRST+29)
+#define LVM_SETCOLUMNWIDTH      (LVM_FIRST+30)
+#define LVM_GETHEADER           (LVM_FIRST+31)
+
+#define LVM_CREATEDRAGIMAGE     (LVM_FIRST+33)
+#define LVM_GETVIEWRECT         (LVM_FIRST+34)
+#define LVM_GETTEXTCOLOR        (LVM_FIRST+35)
+#define LVM_SETTEXTCOLOR        (LVM_FIRST+36)
+#define LVM_GETTEXTBKCOLOR      (LVM_FIRST+37)
+#define LVM_SETTEXTBKCOLOR      (LVM_FIRST+38)
+#define LVM_GETTOPINDEX         (LVM_FIRST+39)
+#define LVM_GETCOUNTPERPAGE     (LVM_FIRST+40)
+#define LVM_GETORIGIN           (LVM_FIRST+41)
+#define LVM_UPDATE              (LVM_FIRST+42)
+#define LVM_SETITEMSTATE        (LVM_FIRST+43)
+#define LVM_GETITEMSTATE        (LVM_FIRST+44)
+#define LVM_GETITEMTEXTA      (LVM_FIRST+45)
+#define LVM_GETITEMTEXTW      (LVM_FIRST+115)
+#define LVM_GETITEMTEXT         WINELIB_NAME_AW(LVM_GETITEMTEXT)
+#define LVM_SETITEMTEXTA      (LVM_FIRST+46)
+#define LVM_SETITEMTEXTW      (LVM_FIRST+116)
+#define LVM_SETITEMTEXT         WINELIB_NAME_AW(LVM_SETITEMTEXT)
+#define LVM_SETITEMCOUNT        (LVM_FIRST+47)
+#define LVM_SORTITEMS           (LVM_FIRST+48)
+#define LVM_SETITEMPOSITION32   (LVM_FIRST+49)
+#define LVM_GETSELECTEDCOUNT    (LVM_FIRST+50)
+#define LVM_GETITEMSPACING      (LVM_FIRST+51)
+#define LVM_GETISEARCHSTRINGA (LVM_FIRST+52)
+#define LVM_GETISEARCHSTRINGW (LVM_FIRST+117)
+#define LVM_GETISEARCHSTRING    WINELIB_NAME_AW(LVM_GETISEARCHSTRING)
+#define LVM_SETICONSPACING      (LVM_FIRST+53)
+#define LVM_SETEXTENDEDLISTVIEWSTYLE (LVM_FIRST+54)
+#define LVM_GETEXTENDEDLISTVIEWSTYLE (LVM_FIRST+55)
+#define LVM_GETSUBITEMRECT      (LVM_FIRST+56)
+#define LVM_SUBITEMHITTEST      (LVM_FIRST+57)
+#define LVM_SETCOLUMNORDERARRAY (LVM_FIRST+58)
+#define LVM_GETCOLUMNORDERARRAY (LVM_FIRST+59)
+#define LVM_SETHOTITEM          (LVM_FIRST+60)
+#define LVM_GETHOTITEM          (LVM_FIRST+61)
+#define LVM_SETHOTCURSOR        (LVM_FIRST+62)
+#define LVM_GETHOTCURSOR        (LVM_FIRST+63)
+#define LVM_APPROXIMATEVIEWRECT (LVM_FIRST+64)
+#define LVM_SETWORKAREAS        (LVM_FIRST+65)
+#define LVM_GETSELECTIONMARK    (LVM_FIRST+66)
+#define LVM_SETSELECTIONMARK    (LVM_FIRST+67)
+#define LVM_SETBKIMAGEA       (LVM_FIRST+68)
+#define LVM_SETBKIMAGEW       (LVM_FIRST+138)
+#define LVM_SETBKIMAGE          WINELIB_NAME_AW(LVM_SETBKIMAGE)
+#define LVM_GETBKIMAGEA       (LVM_FIRST+69)
+#define LVM_GETBKIMAGEW       (LVM_FIRST+139)
+#define LVM_GETBKIMAGE          WINELIB_NAME_AW(LVM_GETBKIMAGE)
+#define LVM_GETWORKAREAS        (LVM_FIRST+70)
+#define LVM_SETHOVERTIME        (LVM_FIRST+71)
+#define LVM_GETHOVERTIME        (LVM_FIRST+72)
+#define LVM_GETNUMBEROFWORKAREAS (LVM_FIRST+73)
+#define LVM_SETTOOLTIPS         (LVM_FIRST+74)
+#define LVM_GETTOOLTIPS         (LVM_FIRST+78)
+#define LVM_GETUNICODEFORMAT    (CCM_GETUNICODEFORMAT)
+#define LVM_SETUNICODEFORMAT    (CCM_SETUNICODEFORMAT)
+
+#define LVN_FIRST               (0U-100U)
+#define LVN_LAST                (0U-199U)
+#define LVN_ITEMCHANGING        (LVN_FIRST-0)
+#define LVN_ITEMCHANGED         (LVN_FIRST-1)
+#define LVN_INSERTITEM          (LVN_FIRST-2)
+#define LVN_DELETEITEM          (LVN_FIRST-3)
+#define LVN_DELETEALLITEMS      (LVN_FIRST-4)
+#define LVN_BEGINLABELEDITA   (LVN_FIRST-5)
+#define LVN_BEGINLABELEDITW   (LVN_FIRST-75)
+#define LVN_BEGINLABELEDIT WINELIB_NAME_AW(LVN_BEGINLABELEDIT)
+#define LVN_ENDLABELEDITA     (LVN_FIRST-6)
+#define LVN_ENDLABELEDITW     (LVN_FIRST-76)
+#define LVN_ENDLABELEDIT WINELIB_NAME_AW(LVN_ENDLABELEDIT)
+#define LVN_COLUMNCLICK         (LVN_FIRST-8)
+#define LVN_BEGINDRAG           (LVN_FIRST-9)
+#define LVN_BEGINRDRAG          (LVN_FIRST-11)
+#define LVN_ODCACHEHINT         (LVN_FIRST-13)
+#define LVN_ITEMACTIVATE        (LVN_FIRST-14)
+#define LVN_ODSTATECHANGED      (LVN_FIRST-15)
+#define LVN_HOTTRACK            (LVN_FIRST-21)
+#define LVN_ODFINDITEMA         (LVN_FIRST-52)
+#define LVN_ODFINDITEMW         (LVN_FIRST-79)
+#define LVN_ODFINDITEM WINELIB_NAME_AW(LVN_ODFINDITEM)
+#define LVN_GETDISPINFOA      (LVN_FIRST-50)
+#define LVN_GETDISPINFOW      (LVN_FIRST-77)
+#define LVN_GETDISPINFO WINELIB_NAME_AW(LVN_GETDISPINFO)
+#define LVN_SETDISPINFOA      (LVN_FIRST-51)
+#define LVN_SETDISPINFOW      (LVN_FIRST-78)
+#define LVN_SETDISPINFO WINELIB_NAME_AW(LVN_SETDISPINFO)
+#define LVN_KEYDOWN             (LVN_FIRST-55)
+#define LVN_MARQUEEBEGIN        (LVN_FIRST-56)
+#define LVN_GETINFOTIPA         (LVN_FIRST-57)
+#define LVN_GETINFOTIPW         (LVN_FIRST-58)
+#define LVN_GETINFOTIP WINELIB_NAME_AW(LVN_GETINFOTIP)
+
+#define LVA_ALIGNLEFT           0x0000
+#define LVA_DEFAULT             0x0001
+#define LVA_ALIGNTOP            0x0002
+#define LVA_SNAPTOGRID          0x0005
+
+typedef struct tagLVITEMA
+{
+    UINT mask;
+    INT  iItem;
+    INT  iSubItem;
+    UINT state;
+    UINT stateMask;
+    LPSTR  pszText;
+    INT  cchTextMax;
+    INT  iImage;
+    LPARAM lParam;
+    INT  iIndent;      /* (_WIN32_IE >= 0x0300) */
+    int iGroupId;       /* (_WIN32_IE >= 0x560) */
+    UINT cColumns;      /* (_WIN32_IE >= 0x560) */
+    PUINT puColumns;   /* (_WIN32_IE >= 0x560) */
+} LVITEMA, *LPLVITEMA;
+
+typedef struct tagLVITEMW
+{
+    UINT mask;
+    INT  iItem;
+    INT  iSubItem;
+    UINT state;
+    UINT stateMask;
+    LPWSTR pszText;
+    INT  cchTextMax;
+    INT  iImage;
+    LPARAM lParam;
+    INT  iIndent;      /* (_WIN32_IE >= 0x0300) */
+    int iGroupId;       /* (_WIN32_IE >= 0x560) */
+    UINT cColumns;      /* (_WIN32_IE >= 0x560) */
+    PUINT puColumns;   /* (_WIN32_IE >= 0x560) */
+} LVITEMW, *LPLVITEMW;
+
+#define LVITEM   WINELIB_NAME_AW(LVITEM)
+#define LPLVITEM WINELIB_NAME_AW(LPLVITEM)
+
+#define LVITEM_V1_SIZEA CCSIZEOF_STRUCT(LVITEMA, lParam)
+#define LVITEM_V1_SIZEW CCSIZEOF_STRUCT(LVITEMW, lParam)
+#define LVITEM_V1_SIZE WINELIB_NAME_AW(LVITEM_V1_SIZE)
+
+#define LV_ITEM LVITEM
+
+typedef struct LVSETINFOTIPA
+{
+    UINT cbSize;
+    DWORD dwFlags;
+    LPSTR pszText;
+    int iItem;
+    int iSubItem;
+} LVSETINFOTIPA, *PLVSETINFOTIPA;
+
+typedef struct LVSETINFOTIPW
+{
+    UINT cbSize;
+    DWORD dwFlags;
+    LPWSTR pszText;
+    int iItem;
+    int iSubItem;
+} LVSETINFOTIPW, *PLVSETINFOTIPW;
+
+#define LVSETINFOTIP WINELIB_NAME_AW(LVSETINFOTIP)
+#define PLVSETINFOTIP WINELIB_NAME_AW(PLVSETINFOTIP)
+
+/* ListView background image structs and constants
+   For _WIN32_IE version 0x400 and later. */
+
+typedef struct tagLVBKIMAGEA
+{
+    ULONG ulFlags;
+    HBITMAP hbm;
+    LPSTR pszImage;
+    UINT cchImageMax;
+    int xOffsetPercent;
+    int yOffsetPercent;
+} LVBKIMAGEA, *LPLVBKIMAGEA;
+
+typedef struct tagLVBKIMAGEW
+{
+    ULONG ulFlags;
+    HBITMAP hbm;
+    LPWSTR pszImage;
+    UINT cchImageMax;
+    int xOffsetPercent;
+    int yOffsetPercent;
+} LVBKIMAGEW, *LPLVBKIMAGEW;
+
+#define LVBKIMAGE WINELIB_NAME_AW(LVBKIMAGE)
+#define LPLVBKIMAGE WINELIB_NAME_AW(LPLVBKIMAGE)
+
+#define LVBKIF_SOURCE_NONE      0x00000000
+#define LVBKIF_SOURCE_HBITMAP   0x00000001
+#define LVBKIF_SOURCE_URL       0x00000002
+#define LVBKIF_SOURCE_MASK      0x00000003
+#define LVBKIF_STYLE_NORMAL     0x00000000
+#define LVBKIF_STYLE_TILE       0x00000010
+#define LVBKIF_STYLE_MASK       0x00000010
+
+#define ListView_SetBkImage(hwnd, plvbki) \
+    (BOOL)SNDMSG((hwnd), LVM_SETBKIMAGE, 0, (LPARAM)plvbki)
+
+#define ListView_GetBkImage(hwnd, plvbki) \
+    (BOOL)SNDMSG((hwnd), LVM_GETBKIMAGE, 0, (LPARAM)plvbki)
+
+typedef struct tagLVCOLUMNA
+{
+    UINT mask;
+    INT  fmt;
+    INT  cx;
+    LPSTR  pszText;
+    INT  cchTextMax;
+    INT  iSubItem;
+    INT  iImage;  /* (_WIN32_IE >= 0x0300) */
+    INT  iOrder;  /* (_WIN32_IE >= 0x0300) */
+} LVCOLUMNA, *LPLVCOLUMNA;
+
+typedef struct tagLVCOLUMNW
+{
+    UINT mask;
+    INT  fmt;
+    INT  cx;
+    LPWSTR pszText;
+    INT  cchTextMax;
+    INT  iSubItem;
+    INT  iImage;       /* (_WIN32_IE >= 0x0300) */
+    INT  iOrder;       /* (_WIN32_IE >= 0x0300) */
+} LVCOLUMNW, *LPLVCOLUMNW;
+
+#define LVCOLUMN   WINELIB_NAME_AW(LVCOLUMN)
+#define LPLVCOLUMN WINELIB_NAME_AW(LPLVCOLUMN)
+
+#define LVCOLUMN_V1_SIZEA CCSIZEOF_STRUCT(LVCOLUMNA, iSubItem)
+#define LVCOLUMN_V1_SIZEW CCSIZEOF_STRUCT(LVCOLUMNW, iSubItem)
+#define LVCOLUMN_V1_SIZE WINELIB_NAME_AW(LVCOLUMN_V1_SIZE)
+
+#define LV_COLUMN       LVCOLUMN
+
+
+typedef struct tagNMLISTVIEW
+{
+    NMHDR hdr;
+    INT iItem;
+    INT iSubItem;
+    UINT uNewState;
+    UINT uOldState;
+    UINT uChanged;
+    POINT ptAction;
+    LPARAM  lParam;
+} NMLISTVIEW, *LPNMLISTVIEW;
+
+#define NM_LISTVIEW     NMLISTVIEW
+#define LPNM_LISTVIEW   LPNMLISTVIEW
+
+typedef struct tagNMITEMACTIVATE
+{
+    NMHDR hdr;
+    int iItem;
+    int iSubItem;
+    UINT uNewState;
+    UINT uOldState;
+    UINT uChanged;
+    POINT ptAction;
+    LPARAM lParam;
+    UINT uKeyFlags;
+} NMITEMACTIVATE, *LPNMITEMACTIVATE;
+
+typedef struct tagLVDISPINFOA
+{
+    NMHDR hdr;
+    LVITEMA item;
+} NMLVDISPINFOA, *LPNMLVDISPINFOA;
+
+typedef struct tagLVDISPINFOW
+{
+    NMHDR hdr;
+    LVITEMW item;
+} NMLVDISPINFOW, *LPNMLVDISPINFOW;
+
+#define NMLVDISPINFO   WINELIB_NAME_AW(NMLVDISPINFO)
+#define LPNMLVDISPINFO WINELIB_NAME_AW(LPNMLVDISPINFO)
+
+#define LV_DISPINFO     NMLVDISPINFO
+
+#include "pshpack1.h"
+typedef struct tagLVKEYDOWN
+{
+  NMHDR hdr;
+  WORD  wVKey;
+  UINT flags;
+} NMLVKEYDOWN, *LPNMLVKEYDOWN;
+#include "poppack.h"
+
+#define LV_KEYDOWN     NMLVKEYDOWN
+
+typedef struct tagNMLVGETINFOTIPA
+{
+    NMHDR hdr;
+    DWORD dwFlags;
+    LPSTR pszText;
+    int cchTextMax;
+    int iItem;
+    int iSubItem;
+    LPARAM lParam;
+} NMLVGETINFOTIPA, *LPNMLVGETINFOTIPA;
+
+typedef struct tagNMLVGETINFOTIPW
+{
+    NMHDR hdr;
+    DWORD dwFlags;
+    LPWSTR pszText;
+    int cchTextMax;
+    int iItem;
+    int iSubItem;
+    LPARAM lParam;
+} NMLVGETINFOTIPW, *LPNMLVGETINFOTIPW;
+
+#define NMLVGETINFOTIP WINELIB_NAME_AW(NMLVGETINFOTIP)
+#define LPNMLVGETINFOTIP WINELIB_NAME_AW(LPNMLVGETINFOTIP)
+
+typedef struct tagLVHITTESTINFO
+{
+    POINT pt;
+    UINT  flags;
+    INT   iItem;
+    INT   iSubItem;
+} LVHITTESTINFO, *LPLVHITTESTINFO;
+
+#define LV_HITTESTINFO LVHITTESTINFO
+#define _LV_HITTESTINFO tagLVHITTESTINFO
+#define LVHITTESTINFO_V1_SIZE CCSIZEOF_STRUCT(LVHITTESTINFO,iItem)
+
+typedef struct tagLVFINDINFOA
+{
+       UINT flags;
+       LPCSTR psz;
+       LPARAM lParam;
+       POINT pt;
+       UINT vkDirection;
+} LVFINDINFOA, *LPLVFINDINFOA;
+
+typedef struct tagLVFINDINFOW
+{
+       UINT flags;
+       LPCWSTR psz;
+       LPARAM lParam;
+       POINT pt;
+       UINT vkDirection;
+} LVFINDINFOW, *LPLVFINDINFOW;
+
+#define LVFINDINFO WINELIB_NAME_AW(LVFINDINFO)
+#define LPLVFINDINFO WINELIB_NAME_AW(LPLVFINDINFO)
+
+/* Groups relates structures */
+
+typedef struct LVGROUPA
+{
+       UINT cbSize;
+       UINT mask;
+       LPSTR pszHeader;
+       int cchHeader;
+       int iGroupId;
+       UINT stateMask;
+       UINT state;
+       UINT uAlign;
+} LVGROUPA, *PLVGROUPA;
+
+typedef struct LVGROUPW
+{
+       UINT cbSize;
+       UINT mask;
+       LPWSTR pszHeader;
+       int cchHeader;
+       int iGroupId;
+       UINT stateMask;
+       UINT state;
+       UINT uAlign;
+} LVGROUPW, *PLVGROUPW;
+
+#define LVGROUP WINELIB_NAME_AW(LVGROUP)
+#define PLVGROUP WINELIB_NAME_AW(PLVGROUP)
+
+typedef struct LVGROUPMETRICS
+{
+       UINT cbSize;
+       UINT mask;
+       UINT Left;
+       UINT Top;
+       UINT Right;
+       UINT Bottom;
+       COLORREF crLeft;
+       COLORREF crTop;
+       COLORREF crRight;
+       COLORREF crBottom;
+       COLORREF crRightHeader;
+       COLORREF crFooter;
+} LVGROUPMETRICS, *PLVGROUPMETRICS;
+
+typedef INT (*PFNLVGROUPCOMPARE)(INT, INT, VOID*);
+
+typedef struct LVINSERTGROUPSORTEDA
+{
+       PFNLVGROUPCOMPARE pfnGroupCompare;
+       LPVOID *pvData;
+       LVGROUPA lvGroup;
+} LVINSERTGROUPSORTEDA, *PLVINSERTGROUPSORTEDA;
+
+typedef struct LVINSERTGROUPSORTEDW
+{
+       PFNLVGROUPCOMPARE pfnGroupCompare;
+       LPVOID *pvData;
+       LVGROUPW lvGroup;
+} LVINSERTGROUPSORTEDW, *PLVINSERTGROUPSORTEDW;
+
+#define LVINSERTGROUPSORTED WINELIB_NAME_AW(LVINSERTGROUPSORTED)
+#define PLVINSERTGROUPSORTED WINELIB_NAME_AW(PLVINSERTGROUPSORTED)
+
+/* Tile related structures */
+
+typedef struct LVTILEINFO 
+{
+       UINT cbSize;
+       int iItem;
+       UINT cColumns;
+       PUINT puColumns;
+} LVTILEINFO, *PLVTILEINFO;
+
+typedef struct LVTILEVIEWINFO
+{
+       UINT cbSize;
+       DWORD dwMask;
+       DWORD dwFlags;
+       SIZE sizeTile;
+       int cLines;
+       RECT rcLabelMargin;
+} LVTILEVIEWINFO, *PLVTILEVIEWINFO;
+
+typedef struct LVINSERTMARK
+{
+       UINT cbSize;
+       DWORD dwFlags;
+       int iItem;
+       DWORD dwReserved;
+} LVINSERTMARK, *PLVINSERTMARK;
+
+typedef struct tagTCHITTESTINFO
+{
+       POINT pt;
+       UINT flags;
+} TCHITTESTINFO, *LPTCHITTESTINFO;
+
+#define TC_HITTESTINFO TCHITTESTINFO
+
+typedef INT (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM);
+
+#define NMLVCUSTOMDRAW_V3_SIZE CCSIZEOF_STRUCT(NMLCUSTOMDRW, clrTextBk)
+
+typedef struct tagNMLVCUSTOMDRAW
+{
+    NMCUSTOMDRAW nmcd;
+    COLORREF clrText;
+    COLORREF clrTextBk;
+    int iSubItem;      /* (_WIN32_IE >= 0x0400) */
+    DWORD dwItemType;  /* (_WIN32_IE >= 0x560) */
+    COLORREF clrFace;   /* (_WIN32_IE >= 0x560) */
+    int iIconEffect;   /* (_WIN32_IE >= 0x560) */
+    int iIconPhase;    /* (_WIN32_IE >= 0x560) */
+    int iPartId;       /* (_WIN32_IE >= 0x560) */
+    int iStateId;      /* (_WIN32_IE >= 0x560) */
+    RECT rcText;       /* (_WIN32_IE >= 0x560) */
+    UINT uAlign;       /* (_WIN32_IE >= 0x560) */
+} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;
+
+typedef struct tagNMLVCACHEHINT
+{
+       NMHDR   hdr;
+       INT     iFrom;
+       INT     iTo;
+} NMLVCACHEHINT, *LPNMLVCACHEHINT;
+
+#define LPNM_CACHEHINT LPNMLVCACHEHINT
+#define PNM_CACHEHINT  LPNMLVCACHEHINT
+#define NM_CACHEHINT   NMLVCACHEHINT
+
+typedef struct tagNMLVFINDITEMA
+{
+    NMHDR hdr;
+    int iStart;
+    LVFINDINFOA lvfi;
+} NMLVFINDITEMA, *LPNMLVFINDITEMA;
+
+typedef struct tagNMLVFINDITEMW
+{
+    NMHDR hdr;
+    int iStart;
+    LVFINDINFOW lvfi;
+} NMLVFINDITEMW, *LPNMLVFINDITEMW;
+
+#define NMLVFINDITEM   WINELIB_NAME_AW(NMLVFINDITEM)
+#define LPNMLVFINDITEM WINELIB_NAME_AW(LPNMLVFINDITEM)
+#define NM_FINDITEM    NMLVFINDITEM
+#define LPNM_FINDITEM  LPNMLVFINDITEM
+#define PNM_FINDITEM   LPNMLVFINDITEM
+
+typedef struct tagNMLVODSTATECHANGE
+{
+    NMHDR hdr;
+    int iFrom;
+    int iTo;
+    UINT uNewState;
+    UINT uOldState;
+} NMLVODSTATECHANGE, *LPNMLVODSTATECHANGE;
+
+#define PNM_ODSTATECHANGE LPNMLVODSTATECHANGE
+#define LPNM_ODSTATECHANGE LPNMLVODSTATECHANGE
+#define NM_ODSTATECHANGE NMLVODSTATECHANGE
+
+typedef struct NMLVSCROLL
+{
+    NMHDR hdr;
+    int dx;
+    int dy;
+} NMLVSCROLL, *LPNMLVSCROLL;
+
+#define ListView_SetTextBkColor(hwnd,clrBk) \
+    (BOOL)SNDMSGA((hwnd),LVM_SETTEXTBKCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_SetTextColor(hwnd,clrBk) \
+    (BOOL)SNDMSGA((hwnd),LVM_SETTEXTCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_DeleteColumn(hwnd,col)\
+    (LRESULT)SNDMSGA((hwnd),LVM_DELETECOLUMN,0,(LPARAM)(INT)(col))
+#define ListView_GetColumnA(hwnd,x,col)\
+    (LRESULT)SNDMSGA((hwnd),LVM_GETCOLUMNA,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNA)(col))
+#define ListView_GetColumnW(hwnd,x,col)\
+    (LRESULT)SNDMSGW((hwnd),LVM_GETCOLUMNW,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNW)(col))
+#define ListView_GetColumn WINELIB_NAME_AW(ListView_GetColumn)
+#define ListView_SetColumnA(hwnd,x,col)\
+    (LRESULT)SNDMSGA((hwnd),LVM_SETCOLUMNA,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNA)(col))
+#define ListView_SetColumnW(hwnd,x,col)\
+    (LRESULT)SNDMSGW((hwnd),LVM_SETCOLUMNW,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNW)(col))
+#define ListView_SetColumn WINELIB_NAME_AW(ListView_SetColumn)
+
+
+#define ListView_GetNextItem(hwnd,nItem,flags) \
+    (INT)SNDMSGA((hwnd),LVM_GETNEXTITEM,(WPARAM)(INT)(nItem),(LPARAM)(MAKELPARAM(flags,0)))
+#define ListView_FindItemA(hwnd,nItem,plvfi) \
+    (INT)SNDMSGA((hwnd),LVM_FINDITEMA,(WPARAM)(INT)(nItem),(LPARAM)(LVFINDINFOA*)(plvfi))
+#define ListView_FindItemW(hwnd,nItem,plvfi) \
+    (INT)SNDMSGW((hwnd),LVM_FINDITEMW,(WPARAM)(INT)(nItem),(LPARAM)(LVFINDINFOW*)(plvfi))
+#define ListView_FindItem WINELIB_NAME_AW(ListView_FindItem)
+
+#define ListView_Arrange(hwnd,code) \
+    (INT)SNDMSGA((hwnd),LVM_ARRANGE,(WPARAM)(INT)(code),0L)
+#define ListView_GetItemPosition(hwnd,i,ppt) \
+    (INT)SNDMSGA((hwnd),LVM_GETITEMPOSITION,(WPARAM)(INT)(i),(LPARAM)(LPPOINT)(ppt))
+#define ListView_GetItemRect(hwnd,i,prc,code) \
+       (BOOL)SNDMSGA((hwnd), LVM_GETITEMRECT, (WPARAM)(int)(i), \
+       ((prc) ? (((RECT*)(prc))->left = (code),(LPARAM)(RECT \
+       *)(prc)) : (LPARAM)(RECT*)NULL))
+#define ListView_SetItemA(hwnd,pitem) \
+    (INT)SNDMSGA((hwnd),LVM_SETITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
+#define ListView_SetItemW(hwnd,pitem) \
+    (INT)SNDMSGW((hwnd),LVM_SETITEMW,0,(LPARAM)(const LVITEMW *)(pitem))
+#define ListView_SetItem WINELIB_NAME_AW(ListView_SetItem)
+#define ListView_SetItemState(hwnd,i,pitem) \
+    (BOOL)SNDMSGA((hwnd),LVM_SETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(LPLVITEMA)(pitem))
+#define ListView_GetItemState(hwnd,i,mask) \
+    (BOOL)SNDMSGA((hwnd),LVM_GETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(UINT)(mask))
+#define ListView_GetCountPerPage(hwnd) \
+    (BOOL)SNDMSGW((hwnd),LVM_GETCOUNTPERPAGE,0,0L)
+#define ListView_GetImageList(hwnd,iImageList) \
+    (HIMAGELIST)SNDMSGA((hwnd),LVM_GETIMAGELIST,(WPARAM)(INT)(iImageList),0L)
+#define ListView_GetStringWidthA(hwnd,pstr) \
+    (INT)SNDMSGA((hwnd),LVM_GETSTRINGWIDTHA,0,(LPARAM)(LPCSTR)(pstr))
+#define ListView_GetStringWidthW(hwnd,pstr) \
+    (INT)SNDMSGW((hwnd),LVM_GETSTRINGWIDTHW,0,(LPARAM)(LPCWSTR)(pstr))
+#define ListView_GetStringWidth WINELIB_NAME_AW(ListView_GetStringWidth)
+#define ListView_GetTopIndex(hwnd) \
+    (BOOL)SNDMSGA((hwnd),LVM_GETTOPINDEX,0,0L)
+#define ListView_Scroll(hwnd,dx,dy) \
+    (BOOL)SNDMSGA((hwnd),LVM_SCROLL,(WPARAM)(INT)(dx),(LPARAM)(INT)(dy))
+#define ListView_EnsureVisible(hwnd,i,fPartialOk) \
+    (BOOL)SNDMSGA((hwnd),LVM_ENSUREVISIBLE,(WPARAM)(INT)i,(LPARAM)(BOOL)fPartialOk)
+#define ListView_SetBkColor(hwnd,clrBk) \
+    (BOOL)SNDMSGA((hwnd),LVM_SETBKCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_SetImageList(hwnd,himl,iImageList) \
+    (HIMAGELIST)(UINT)SNDMSGA((hwnd),LVM_SETIMAGELIST,(WPARAM)(iImageList),(LPARAM)(UINT)(HIMAGELIST)(himl))
+#define ListView_GetItemCount(hwnd) \
+    (INT)SNDMSGA((hwnd),LVM_GETITEMCOUNT,0,0L)
+
+#define ListView_GetItemA(hwnd,pitem) \
+    (BOOL)SNDMSGA((hwnd),LVM_GETITEMA,0,(LPARAM)(LVITEMA *)(pitem))
+#define ListView_GetItemW(hwnd,pitem) \
+    (BOOL)SNDMSGW((hwnd),LVM_GETITEMW,0,(LPARAM)(LVITEMW *)(pitem))
+#define ListView_GetItem WINELIB_NAME_AW(ListView_GetItem)
+
+#define ListView_HitTest(hwnd,pinfo) \
+    (INT)SNDMSGA((hwnd),LVM_HITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo))
+
+#define ListView_InsertItemA(hwnd,pitem) \
+    (INT)SNDMSGA((hwnd),LVM_INSERTITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
+#define ListView_InsertItemW(hwnd,pitem) \
+    (INT)SNDMSGW((hwnd),LVM_INSERTITEMW,0,(LPARAM)(const LVITEMW *)(pitem))
+#define ListView_InsertItem WINELIB_NAME_AW(ListView_InsertItem)
+
+#define ListView_DeleteAllItems(hwnd) \
+    (BOOL)SNDMSGA((hwnd),LVM_DELETEALLITEMS,0,0L)
+
+#define ListView_InsertColumnA(hwnd,iCol,pcol) \
+    (INT)SNDMSGA((hwnd),LVM_INSERTCOLUMNA,(WPARAM)(INT)(iCol),(LPARAM)(const LVCOLUMNA *)(pcol))
+#define ListView_InsertColumnW(hwnd,iCol,pcol) \
+    (INT)SNDMSGW((hwnd),LVM_INSERTCOLUMNW,(WPARAM)(INT)(iCol),(LPARAM)(const LVCOLUMNW *)(pcol))
+#define ListView_InsertColumn WINELIB_NAME_AW(ListView_InsertColumn)
+
+#define ListView_SortItems(hwndLV,_pfnCompare,_lPrm) \
+    (BOOL)SNDMSGA((hwndLV),LVM_SORTITEMS,(WPARAM)(LPARAM)_lPrm,(LPARAM)(PFNLVCOMPARE)_pfnCompare)
+#define ListView_SetItemPosition(hwndLV, i, x, y) \
+    (BOOL)SNDMSGA((hwndLV),LVM_SETITEMPOSITION,(WPARAM)(INT)(i),MAKELPARAM((x),(y)))
+#define ListView_GetSelectedCount(hwndLV) \
+    (UINT)SNDMSGA((hwndLV),LVM_GETSELECTEDCOUNT,0,0L)
+
+#define ListView_EditLabelA(hwndLV, i) \
+    (HWND)SNDMSGA((hwndLV),LVM_EDITLABELA,(WPARAM)(int)(i), 0L)
+#define ListView_EditLabelW(hwndLV, i) \
+    (HWND)SNDMSGW((hwndLV),LVM_EDITLABELW,(WPARAM)(int)(i), 0L)
+#define ListView_EditLabel WINELIB_NAME_AW(ListView_EditLabel)
+
+#define ListView_SetItemTextA(hwndLV, i, _iSubItem, _pszText) \
+{ LVITEMA _LVi; _LVi.iSubItem = _iSubItem; _LVi.pszText = _pszText;\
+  SNDMSGA(hwndLV, LVM_SETITEMTEXTA, (WPARAM)i, (LPARAM) (LVITEMA*)&_LVi);}
+#define ListView_SetItemTextW(hwndLV, i, _iSubItem, _pszText) \
+{ LVITEMW _LVi; _LVi.iSubItem = _iSubItem; _LVi.pszText = _pszText;\
+  SNDMSGW(hwndLV, LVM_SETITEMTEXTW, (WPARAM)i, (LPARAM) (LVITEMW*)& _LVi);}
+#define ListView_SetItemText WINELIB_NAME_AW(ListView_SetItemText)
+
+#define ListView_DeleteItem(hwndLV, i) \
+    (BOOL)SNDMSGA(hwndLV, LVM_DELETEITEM, (WPARAM)(int)(i), 0L)
+#define ListView_Update(hwndLV, i) \
+    (BOOL)SNDMSGA((hwndLV), LVM_UPDATE, (WPARAM)(i), 0L)
+#define ListView_GetColumnOrderArray(hwndLV, iCount, pi) \
+    (BOOL)SNDMSGA((hwndLV), LVM_GETCOLUMNORDERARRAY, (WPARAM)iCount, (LPARAM)(LPINT)pi)
+#define ListView_GetExtendedListViewStyle(hwndLV) \
+    (DWORD)SNDMSGA((hwndLV), LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L)
+#define ListView_GetHotCursor(hwndLV) \
+    (HCURSOR)SNDMSGA((hwndLV), LVM_GETHOTCURSOR, 0, 0L)
+#define ListView_GetHotItem(hwndLV) \
+    (int)SNDMSGA((hwndLV), LVM_GETHOTITEM, 0, 0L)
+#define ListView_GetItemSpacing(hwndLV, fSmall) \
+    (DWORD)SNDMSGA((hwndLV), LVM_GETITEMSPACING, (WPARAM)fSmall, 0L)
+#define ListView_GetSubItemRect(hwndLV, iItem, iSubItem, code, prc) \
+    (BOOL)SNDMSGA((hwndLV), LVM_GETSUBITEMRECT, (WPARAM)(int)(iItem), \
+                       ((prc) ? (((LPRECT)(prc))->top = iSubItem), (((LPRECT)(prc))->left = code):0), (LPARAM)prc)
+#define ListView_GetToolTips(hwndLV) \
+    (HWND)SNDMSGA((hwndLV), LVM_GETTOOLTIPS, 0, 0L)
+#define ListView_SetColumnOrderArray(hwndLV, iCount, pi) \
+    (BOOL)SNDMSGA((hwndLV), LVM_SETCOLUMNORDERARRAY, (WPARAM)iCount, (LPARAM)(LPINT)pi)
+#define ListView_SetExtendedListViewStyle(hwndLV, dw) \
+    (DWORD)SNDMSGA((hwndLV), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM)dw)
+#define ListView_SetExtendedListViewStyleEx(hwndLV, dwMask, dw) \
+    (DWORD)SNDMSGA((hwndLV), LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)dwMask, (LPARAM)dw)
+#define ListView_SetHotCursor(hwndLV, hcur) \
+    (HCURSOR)SNDMSGA((hwndLV), LVM_SETHOTCURSOR, 0, (LPARAM)hcur)
+#define ListView_SetHotItem(hwndLV, i) \
+    (int)SNDMSGA((hwndLV), LVM_SETHOTITEM, (WPARAM)i, 0L)
+#define ListView_SetIconSpacing(hwndLV, cx, cy) \
+    (DWORD)SNDMSGA((hwndLV), LVM_SETICONSPACING, 0, MAKELONG(cx,cy))
+#define ListView_SetToolTips(hwndLV, hwndNewHwnd) \
+    (HWND)SNDMSGA((hwndLV), LVM_SETTOOLTIPS, (WPARAM)hwndNewHwnd, 0L)
+#define ListView_SubItemHitTest(hwndLV, plvhti) \
+    (int)SNDMSGA((hwndLV), LVM_SUBITEMHITTEST, 0, (LPARAM)(LPLVHITTESTINFO)(plvhti))
+
+
+/* Tab Control */
+
+#define WC_TABCONTROL16        "SysTabControl"
+#define WC_TABCONTROLA         "SysTabControl32"
+#if defined(__GNUC__)
+# define WC_TABCONTROLW (const WCHAR []){ 'S','y','s', \
+  'T','a','b','C','o','n','t','r','o','l','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_TABCONTROLW         L"SysTabControl32"
+#else
+static const WCHAR WC_TABCONTROLW[] = { 'S','y','s',
+  'T','a','b','C','o','n','t','r','o','l','3','2',0 };
+#endif
+#define WC_TABCONTROL          WINELIB_NAME_AW(WC_TABCONTROL)
+
+/* tab control styles */
+#define TCS_SCROLLOPPOSITE      0x0001   /* assumes multiline tab */
+#define TCS_BOTTOM              0x0002
+#define TCS_RIGHT               0x0002
+#define TCS_MULTISELECT         0x0004  /* allow multi-select in button mode */
+#define TCS_FLATBUTTONS         0x0008
+#define TCS_FORCEICONLEFT       0x0010
+#define TCS_FORCELABELLEFT      0x0020
+#define TCS_HOTTRACK            0x0040
+#define TCS_VERTICAL            0x0080
+#define TCS_TABS                0x0000
+#define TCS_BUTTONS             0x0100
+#define TCS_SINGLELINE          0x0000
+#define TCS_MULTILINE           0x0200
+#define TCS_RIGHTJUSTIFY        0x0000
+#define TCS_FIXEDWIDTH          0x0400
+#define TCS_RAGGEDRIGHT         0x0800
+#define TCS_FOCUSONBUTTONDOWN   0x1000
+#define TCS_OWNERDRAWFIXED      0x2000
+#define TCS_TOOLTIPS            0x4000
+#define TCS_FOCUSNEVER          0x8000
+#define TCS_EX_FLATSEPARATORS   0x00000001  /* to be used with */
+#define TCS_EX_REGISTERDROP     0x00000002  /* TCM_SETEXTENDEDSTYLE */
+
+
+#define TCM_FIRST              0x1300
+
+#define TCM_GETIMAGELIST        (TCM_FIRST + 2)
+#define TCM_SETIMAGELIST        (TCM_FIRST + 3)
+#define TCM_GETITEMCOUNT       (TCM_FIRST + 4)
+#define TCM_GETITEM                            WINELIB_NAME_AW(TCM_GETITEM)
+#define TCM_GETITEMA                   (TCM_FIRST + 5)
+#define TCM_GETITEMW                   (TCM_FIRST + 60)
+#define TCM_SETITEMA                   (TCM_FIRST + 6)
+#define TCM_SETITEMW                   (TCM_FIRST + 61)
+#define TCM_SETITEM                            WINELIB_NAME_AW(TCM_SETITEM)
+#define TCM_INSERTITEMA                (TCM_FIRST + 7)
+#define TCM_INSERTITEMW                (TCM_FIRST + 62)
+#define TCM_INSERTITEM                 WINELIB_NAME_AW(TCM_INSERTITEM)
+#define TCM_DELETEITEM          (TCM_FIRST + 8)
+#define TCM_DELETEALLITEMS      (TCM_FIRST + 9)
+#define TCM_GETITEMRECT         (TCM_FIRST + 10)
+#define TCM_GETCURSEL          (TCM_FIRST + 11)
+#define TCM_SETCURSEL           (TCM_FIRST + 12)
+#define TCM_HITTEST             (TCM_FIRST + 13)
+#define TCM_SETITEMEXTRA       (TCM_FIRST + 14)
+#define TCM_ADJUSTRECT          (TCM_FIRST + 40)
+#define TCM_SETITEMSIZE         (TCM_FIRST + 41)
+#define TCM_REMOVEIMAGE         (TCM_FIRST + 42)
+#define TCM_SETPADDING          (TCM_FIRST + 43)
+#define TCM_GETROWCOUNT         (TCM_FIRST + 44)
+#define TCM_GETTOOLTIPS         (TCM_FIRST + 45)
+#define TCM_SETTOOLTIPS         (TCM_FIRST + 46)
+#define TCM_GETCURFOCUS         (TCM_FIRST + 47)
+#define TCM_SETCURFOCUS         (TCM_FIRST + 48)
+#define TCM_SETMINTABWIDTH     (TCM_FIRST + 49)
+#define TCM_DESELECTALL         (TCM_FIRST + 50)
+#define TCM_HIGHLIGHTITEM              (TCM_FIRST + 51)
+#define TCM_SETEXTENDEDSTYLE   (TCM_FIRST + 52)
+#define TCM_GETEXTENDEDSTYLE   (TCM_FIRST + 53)
+#define TCM_SETUNICODEFORMAT   CCM_SETUNICODEFORMAT
+#define TCM_GETUNICODEFORMAT   CCM_GETUNICODEFORMAT
+
+
+#define TCIF_TEXT              0x0001
+#define TCIF_IMAGE             0x0002
+#define TCIF_RTLREADING                0x0004
+#define TCIF_PARAM             0x0008
+#define TCIF_STATE             0x0010
+
+#define TCIS_BUTTONPRESSED      0x0001
+#define TCIS_HIGHLIGHTED 0x0002
+
+/* TabCtrl Macros */
+#define TabCtrl_GetImageList(hwnd) \
+    (HIMAGELIST)SNDMSGA((hwnd), TCM_GETIMAGELIST, 0, 0L)
+#define TabCtrl_SetImageList(hwnd, himl) \
+    (HIMAGELIST)SNDMSGA((hwnd), TCM_SETIMAGELIST, 0, (LPARAM)(UINT)(HIMAGELIST)(himl))
+#define TabCtrl_GetItemCount(hwnd) \
+    (int)SNDMSGA((hwnd), TCM_GETITEMCOUNT, 0, 0L)
+#define TabCtrl_GetItemA(hwnd, iItem, pitem) \
+    (BOOL)SNDMSGA((hwnd), TCM_GETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_GetItemW(hwnd, iItem, pitem) \
+    (BOOL)SNDMSGW((hwnd), TCM_GETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_GetItem WINELIB_NAME_AW(TabCtrl_GetItem)
+#define TabCtrl_SetItemA(hwnd, iItem, pitem) \
+    (BOOL)SNDMSGA((hwnd), TCM_SETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_SetItemW(hwnd, iItem, pitem) \
+    (BOOL)SNDMSGW((hwnd), TCM_SETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_SetItem WINELIB_NAME_AW(TabCtrl_GetItem)
+#define TabCtrl_InsertItemA(hwnd, iItem, pitem)   \
+    (int)SNDMSGA((hwnd), TCM_INSERTITEM, (WPARAM)(int)iItem, (LPARAM)(const TC_ITEM *)(pitem))
+#define TabCtrl_InsertItemW(hwnd, iItem, pitem)   \
+    (int)SNDMSGW((hwnd), TCM_INSERTITEM, (WPARAM)(int)iItem, (LPARAM)(const TC_ITEM *)(pitem))
+#define TabCtrl_InsertItem WINELIB_NAME_AW(TabCtrl_InsertItem)
+#define TabCtrl_DeleteItem(hwnd, i) \
+    (BOOL)SNDMSGA((hwnd), TCM_DELETEITEM, (WPARAM)(int)(i), 0L)
+#define TabCtrl_DeleteAllItems(hwnd) \
+    (BOOL)SNDMSGA((hwnd), TCM_DELETEALLITEMS, 0, 0L)
+#define TabCtrl_GetItemRect(hwnd, i, prc) \
+    (BOOL)SNDMSGA((hwnd), TCM_GETITEMRECT, (WPARAM)(int)(i), (LPARAM)(RECT *)(prc))
+#define TabCtrl_GetCurSel(hwnd) \
+    (int)SNDMSGA((hwnd), TCM_GETCURSEL, 0, 0)
+#define TabCtrl_SetCurSel(hwnd, i) \
+    (int)SNDMSGA((hwnd), TCM_SETCURSEL, (WPARAM)i, 0)
+#define TabCtrl_HitTest(hwndTC, pinfo) \
+    (int)SNDMSGA((hwndTC), TCM_HITTEST, 0, (LPARAM)(TC_HITTESTINFO *)(pinfo))
+#define TabCtrl_SetItemExtra(hwndTC, cb) \
+    (BOOL)SNDMSGA((hwndTC), TCM_SETITEMEXTRA, (WPARAM)(cb), 0L)
+#define TabCtrl_AdjustRect(hwnd, bLarger, prc) \
+    (int)SNDMSGA(hwnd, TCM_ADJUSTRECT, (WPARAM)(BOOL)bLarger, (LPARAM)(RECT *)prc)
+#define TabCtrl_SetItemSize(hwnd, x, y) \
+    (DWORD)SNDMSGA((hwnd), TCM_SETITEMSIZE, 0, MAKELPARAM(x,y))
+#define TabCtrl_RemoveImage(hwnd, i) \
+    (void)SNDMSGA((hwnd), TCM_REMOVEIMAGE, i, 0L)
+#define TabCtrl_SetPadding(hwnd,  cx, cy) \
+    (void)SNDMSGA((hwnd), TCM_SETPADDING, 0, MAKELPARAM(cx, cy))
+#define TabCtrl_GetRowCount(hwnd) \
+    (int)SNDMSGA((hwnd), TCM_GETROWCOUNT, 0, 0L)
+#define TabCtrl_GetToolTips(hwnd) \
+    (HWND)SNDMSGA((hwnd), TCM_GETTOOLTIPS, 0, 0L)
+#define TabCtrl_SetToolTips(hwnd, hwndTT) \
+    (void)SNDMSGA((hwnd), TCM_SETTOOLTIPS, (WPARAM)hwndTT, 0L)
+#define TabCtrl_GetCurFocus(hwnd) \
+    (int)SNDMSGA((hwnd), TCM_GETCURFOCUS, 0, 0)
+#define TabCtrl_SetCurFocus(hwnd, i) \
+    SNDMSGA((hwnd),TCM_SETCURFOCUS, i, 0)
+#define TabCtrl_SetMinTabWidth(hwnd, x) \
+    (int)SNDMSGA((hwnd), TCM_SETMINTABWIDTH, 0, x)
+#define TabCtrl_DeselectAll(hwnd, fExcludeFocus)\
+    (void)SNDMSGA((hwnd), TCM_DESELECTALL, fExcludeFocus, 0)
+
+
+/* constants for TCHITTESTINFO */
+
+#define TCHT_NOWHERE      0x01
+#define TCHT_ONITEMICON   0x02
+#define TCHT_ONITEMLABEL  0x04
+#define TCHT_ONITEM       (TCHT_ONITEMICON | TCHT_ONITEMLABEL)
+
+
+typedef struct tagTCITEMA {
+    UINT mask;
+    UINT dwState;
+    UINT dwStateMask;
+    LPSTR  pszText;
+    INT  cchTextMax;
+    INT  iImage;
+    LPARAM lParam;
+} TCITEMA, *LPTCITEMA;
+
+typedef struct tagTCITEMW
+{
+    UINT mask;
+    DWORD  dwState;
+    DWORD  dwStateMask;
+    LPWSTR pszText;
+    INT  cchTextMax;
+    INT  iImage;
+    LPARAM lParam;
+} TCITEMW, *LPTCITEMW;
+
+#define TCITEM   WINELIB_NAME_AW(TCITEM)
+#define LPTCITEM WINELIB_NAME_AW(LPTCITEM)
+#define TC_ITEM  TCITEM
+
+#define TCN_FIRST               (0U-550U)
+#define TCN_LAST                (0U-580U)
+#define TCN_KEYDOWN             (TCN_FIRST - 0)
+#define TCN_SELCHANGE          (TCN_FIRST - 1)
+#define TCN_SELCHANGING         (TCN_FIRST - 2)
+#define TCN_GETOBJECT      (TCN_FIRST - 3)
+
+#include "pshpack1.h"
+typedef struct tagTCKEYDOWN
+{
+    NMHDR hdr;
+    WORD wVKey;
+    UINT flags;
+} NMTCKEYDOWN;
+#include "poppack.h"
+
+#define TC_KEYDOWN              NMTCKEYDOWN
+
+/* ComboBoxEx control */
+
+#define WC_COMBOBOXEXA        "ComboBoxEx32"
+#if defined(__GNUC__)
+# define WC_COMBOBOXEXW (const WCHAR []){ 'C','o','m','b','o', \
+  'B','o','x','E','x','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_COMBOBOXEXW       L"ComboBoxEx32"
+#else
+static const WCHAR WC_COMBOBOXEXW[] = { 'C','o','m','b','o',
+  'B','o','x','E','x','3','2',0 };
+#endif
+#define WC_COMBOBOXEX           WINELIB_NAME_AW(WC_COMBOBOXEX)
+
+#define CBEIF_TEXT              0x00000001
+#define CBEIF_IMAGE             0x00000002
+#define CBEIF_SELECTEDIMAGE     0x00000004
+#define CBEIF_OVERLAY           0x00000008
+#define CBEIF_INDENT            0x00000010
+#define CBEIF_LPARAM            0x00000020
+#define CBEIF_DI_SETITEM        0x10000000
+
+#define CBEM_INSERTITEMA      (WM_USER+1)
+#define CBEM_INSERTITEMW      (WM_USER+11)
+#define CBEM_INSERTITEM         WINELIB_NAME_AW(CBEM_INSERTITEM)
+#define CBEM_SETIMAGELIST       (WM_USER+2)
+#define CBEM_GETIMAGELIST       (WM_USER+3)
+#define CBEM_GETITEMA         (WM_USER+4)
+#define CBEM_GETITEMW         (WM_USER+13)
+#define CBEM_GETITEM            WINELIB_NAME_AW(CBEM_GETITEM)
+#define CBEM_SETITEMA         (WM_USER+5)
+#define CBEM_SETITEMW         (WM_USER+12)
+#define CBEM_SETITEM            WINELIB_NAME_AW(CBEM_SETITEM)
+#define CBEM_DELETEITEM         CB_DELETESTRING
+#define CBEM_GETCOMBOCONTROL    (WM_USER+6)
+#define CBEM_GETEDITCONTROL     (WM_USER+7)
+#define CBEM_SETEXSTYLE         (WM_USER+8)
+#define CBEM_GETEXSTYLE         (WM_USER+9)
+#define CBEM_GETEXTENDEDSTYLE   (WM_USER+9)
+#define CBEM_SETEXTENDEDSTYLE   (WM_USER+14)
+#define CBEM_SETUNICODEFORMAT   CCM_SETUNICODEFORMAT
+#define CBEM_GETUNICODEFORMAT   CCM_GETUNICODEFORMAT
+#define CBEM_HASEDITCHANGED     (WM_USER+10)
+
+#define CBEIF_TEXT              0x00000001
+#define CBEIF_IMAGE             0x00000002
+#define CBEIF_SELECTEDIMAGE     0x00000004
+#define CBEIF_OVERLAY           0x00000008
+#define CBEIF_INDENT            0x00000010
+#define CBEIF_LPARAM            0x00000020
+#define CBEIF_DI_SETITEM        0x10000000
+
+#define CBEN_FIRST              (0U-800U)
+#define CBEN_LAST               (0U-830U)
+
+#define CBEN_GETDISPINFOA       (CBEN_FIRST - 0)
+#define CBEN_GETDISPINFOW       (CBEN_FIRST - 7)
+#define CBEN_GETDISPINFO WINELIB_NAME_AW(CBEN_GETDISPINFO)
+#define CBEN_INSERTITEM         (CBEN_FIRST - 1)
+#define CBEN_DELETEITEM         (CBEN_FIRST - 2)
+#define CBEN_BEGINEDIT          (CBEN_FIRST - 4)
+#define CBEN_ENDEDITA           (CBEN_FIRST - 5)
+#define CBEN_ENDEDITW           (CBEN_FIRST - 6)
+#define CBEN_ENDEDIT WINELIB_NAME_AW(CBEN_ENDEDIT)
+#define CBEN_DRAGBEGINA         (CBEN_FIRST - 8)
+#define CBEN_DRAGBEGINW         (CBEN_FIRST - 9)
+#define CBEN_DRAGBEGIN WINELIB_NAME_AW(CBEN_DRAGBEGIN)
+
+#define CBES_EX_NOEDITIMAGE          0x00000001
+#define CBES_EX_NOEDITIMAGEINDENT    0x00000002
+#define CBES_EX_PATHWORDBREAKPROC    0x00000004
+#define CBES_EX_NOSIZELIMIT          0x00000008
+#define CBES_EX_CASESENSITIVE        0x00000010
+
+
+typedef struct tagCOMBOBOXEXITEMA
+{
+    UINT mask;
+    int iItem;
+    LPSTR pszText;
+    int cchTextMax;
+    int iImage;
+    int iSelectedImage;
+    int iOverlay;
+    int iIndent;
+    LPARAM lParam;
+} COMBOBOXEXITEMA, *PCOMBOBOXEXITEMA;
+typedef COMBOBOXEXITEMA const *PCCOMBOEXITEMA; /* Yes, there's a BOX missing */
+
+typedef struct tagCOMBOBOXEXITEMW
+{
+    UINT mask;
+    int iItem;
+    LPWSTR pszText;
+    int cchTextMax;
+    int iImage;
+    int iSelectedImage;
+    int iOverlay;
+    int iIndent;
+    LPARAM lParam;
+} COMBOBOXEXITEMW, *PCOMBOBOXEXITEMW;
+typedef COMBOBOXEXITEMW const *PCCOMBOEXITEMW; /* Yes, there's a BOX missing */
+
+#define COMBOBOXEXITEM WINELIB_NAME_AW(COMBOBOXEXITEM)
+#define PCOMBOBOXEXITEM WINELIB_NAME_AW(PCOMBOBOXEXITEM)
+#define PCCOMBOBOXEXITEM WINELIB_NAME_AW(PCCOMBOEXITEM) /* Yes, there's a BOX missing */
+
+#define CBENF_KILLFOCUS               1
+#define CBENF_RETURN                  2
+#define CBENF_ESCAPE                  3
+#define CBENF_DROPDOWN                4
+
+#define CBEMAXSTRLEN 260
+
+typedef struct tagNMCBEENDEDITW
+{
+    NMHDR hdr;
+    BOOL fChanged;
+    int iNewSelection;
+    WCHAR szText[CBEMAXSTRLEN];
+    int iWhy;
+} NMCBEENDEDITW, *LPNMCBEENDEDITW, *PNMCBEENDEDITW;
+
+typedef struct tagNMCBEENDEDITA
+{
+    NMHDR hdr;
+    BOOL fChanged;
+    int iNewSelection;
+    char szText[CBEMAXSTRLEN];
+    int iWhy;
+} NMCBEENDEDITA, *LPNMCBEENDEDITA, *PNMCBEENDEDITA;
+
+#define NMCBEENDEDIT WINELIB_NAME_AW(NMCBEENDEDIT)
+#define LPNMCBEENDEDIT WINELIB_NAME_AW(LPNMCBEENDEDIT)
+#define PNMCBEENDEDIT WINELIB_NAME_AW(PNMCBEENDEDIT)
+
+typedef struct
+{
+    NMHDR hdr;
+    COMBOBOXEXITEMA ceItem;
+} NMCOMBOBOXEXA, *PNMCOMBOBOXEXA;
+
+typedef struct
+{
+    NMHDR hdr;
+    COMBOBOXEXITEMW ceItem;
+} NMCOMBOBOXEXW, *PNMCOMBOBOXEXW;
+
+#define NMCOMBOBOXEX WINELIB_NAME_AW(NMCOMBOBOXEX)
+#define PNMCOMBOBOXEX WINELIB_NAME_AW(PNMCOMBOBOXEX)
+
+typedef struct
+{
+    NMHDR hdr;
+    int iItemid;
+    char szText[CBEMAXSTRLEN];
+} NMCBEDRAGBEGINA, *PNMCBEDRAGBEGINA, *LPNMCBEDRAGBEGINA;
+
+typedef struct
+{
+    NMHDR hdr;
+    int iItemid;
+    WCHAR szText[CBEMAXSTRLEN];
+} NMCBEDRAGBEGINW, *PNMCBEDRAGBEGINW, *LPNMCBEDRAGBEGINW;
+
+#define NMCBEDRAGBEGIN WINELIB_NAME_AW(NMCBEDRAGBEGIN)
+#define PNMCBEDRAGBEGIN WINELIB_NAME_AW(PNMCBEDRAGBEGIN)
+#define LPNMCBEDRAGBEGIN WINELIB_NAME_AW(LPNMCBEDRAGBEGIN)
+
+
+/* Hotkey control */
+
+#define HOTKEY_CLASS16          "msctls_hotkey"
+#define HOTKEY_CLASSA           "msctls_hotkey32"
+#if defined(__GNUC__)
+# define HOTKEY_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+  'h','o','t','k','e','y','3','2',0 }
+#elif defined(_MSC_VER)
+# define HOTKEY_CLASSW          L"msctls_hotkey32"
+#else
+static const WCHAR HOTKEY_CLASSW[] = { 'm','s','c','t','l','s','_',
+  'h','o','t','k','e','y','3','2',0 };
+#endif
+#define HOTKEY_CLASS            WINELIB_NAME_AW(HOTKEY_CLASS)
+
+#define HOTKEYF_SHIFT           0x01
+#define HOTKEYF_CONTROL         0x02
+#define HOTKEYF_ALT             0x04
+#define HOTKEYF_EXT             0x08
+
+#define HKCOMB_NONE             0x0001
+#define HKCOMB_S                0x0002
+#define HKCOMB_C                0x0004
+#define HKCOMB_A                0x0008
+#define HKCOMB_SC               0x0010
+#define HKCOMB_SA               0x0020
+#define HKCOMB_CA               0x0040
+#define HKCOMB_SCA              0x0080
+
+#define HKM_SETHOTKEY           (WM_USER+1)
+#define HKM_GETHOTKEY           (WM_USER+2)
+#define HKM_SETRULES            (WM_USER+3)
+
+
+/* animate control */
+
+#define ANIMATE_CLASSA        "SysAnimate32"
+#if defined(__GNUC__)
+# define ANIMATE_CLASSW (const WCHAR []){ 'S','y','s', \
+  'A','n','i','m','a','t','e','3','2',0 }
+#elif defined(_MSC_VER)
+# define ANIMATE_CLASSW       L"SysAnimate32"
+#else
+static const WCHAR ANIMATE_CLASSW[] = { 'S','y','s',
+  'A','n','i','m','a','t','e','3','2',0 };
+#endif
+#define ANIMATE_CLASS           WINELIB_NAME_AW(ANIMATE_CLASS)
+
+#define ACS_CENTER              0x0001
+#define ACS_TRANSPARENT         0x0002
+#define ACS_AUTOPLAY            0x0004
+#define ACS_TIMER               0x0008  /* no threads, just timers */
+
+#define ACM_OPENA             (WM_USER+100)
+#define ACM_OPENW             (WM_USER+103)
+#define ACM_OPEN                WINELIB_NAME_AW(ACM_OPEN)
+#define ACM_PLAY                (WM_USER+101)
+#define ACM_STOP                (WM_USER+102)
+
+#define ACN_START               1
+#define ACN_STOP                2
+
+#define Animate_CreateA(hwndP,id,dwStyle,hInstance) \
+    CreateWindowA(ANIMATE_CLASSA,NULL,dwStyle,0,0,0,0,hwndP,(HMENU)(id),hInstance,NULL)
+#define Animate_CreateW(hwndP,id,dwStyle,hInstance) \
+    CreateWindowW(ANIMATE_CLASSW,NULL,dwStyle,0,0,0,0,hwndP,(HMENU)(id),hInstance,NULL)
+#define Animate_Create WINELIB_NAME_AW(Animate_Create)
+#define Animate_OpenA(hwnd,szName) \
+    (BOOL)SNDMSGA(hwnd,ACM_OPENA,0,(LPARAM)(LPSTR)(szName))
+#define Animate_OpenW(hwnd,szName) \
+    (BOOL)SNDMSGW(hwnd,ACM_OPENW,0,(LPARAM)(LPWSTR)(szName))
+#define Animate_Open WINELIB_NAME_AW(Animate_Open)
+#define Animate_OpenExA(hwnd,hInst,szName) \
+    (BOOL)SNDMSGA(hwnd,ACM_OPENA,(WPARAM)hInst,(LPARAM)(LPSTR)(szName))
+#define Animate_OpenExW(hwnd,hInst,szName) \
+    (BOOL)SNDMSGW(hwnd,ACM_OPENW,(WPARAM)hInst,(LPARAM)(LPWSTR)(szName))
+#define Animate_OpenEx WINELIB_NAME_AW(Animate_OpenEx)
+#define Animate_Play(hwnd,from,to,rep) \
+    (BOOL)SNDMSGA(hwnd,ACM_PLAY,(WPARAM)(UINT)(rep),(LPARAM)MAKELONG(from,to))
+#define Animate_Stop(hwnd) \
+    (BOOL)SNDMSGA(hwnd,ACM_STOP,0,0)
+#define Animate_Close(hwnd) \
+    (BOOL)SNDMSGA(hwnd,ACM_OPENA,0,0)
+#define Animate_Seek(hwnd,frame) \
+    (BOOL)SNDMSGA(hwnd,ACM_PLAY,1,(LPARAM)MAKELONG(frame,frame))
+
+
+/**************************************************************************
+ * IP Address control
+ */
+
+#define WC_IPADDRESSA          "SysIPAddress32"
+#if defined(__GNUC__)
+# define WC_IPADDRESSW (const WCHAR []){ 'S','y','s', \
+  'I','P','A','d','d','r','e','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_IPADDRESSW          L"SysIPAddress32"
+#else
+static const WCHAR WC_IPADDRESSW[] = { 'S','y','s',
+  'I','P','A','d','d','r','e','s','s','3','2',0 };
+#endif
+#define WC_IPADDRESS           WINELIB_NAME_AW(WC_IPADDRESS)
+
+#define IPM_CLEARADDRESS       (WM_USER+100)
+#define IPM_SETADDRESS         (WM_USER+101)
+#define IPM_GETADDRESS         (WM_USER+102)
+#define IPM_SETRANGE           (WM_USER+103)
+#define IPM_SETFOCUS           (WM_USER+104)
+#define IPM_ISBLANK            (WM_USER+105)
+
+#define IPN_FIRST               (0U-860U)
+#define IPN_LAST                (0U-879U)
+#define IPN_FIELDCHANGED    (IPN_FIRST-0)
+
+typedef struct tagNMIPADDRESS
+{
+    NMHDR hdr;
+    INT iField;
+    INT iValue;
+} NMIPADDRESS, *LPNMIPADDRESS;
+
+#define MAKEIPRANGE(low,high) \
+    ((LPARAM)(WORD)(((BYTE)(high)<<8)+(BYTE)(low)))
+#define MAKEIPADDRESS(b1,b2,b3,b4) \
+    ((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
+
+#define FIRST_IPADDRESS(x)     (((x)>>24)&0xff)
+#define SECOND_IPADDRESS(x)    (((x)>>16)&0xff)
+#define THIRD_IPADDRESS(x)     (((x)>>8)&0xff)
+#define FOURTH_IPADDRESS(x)    ((x)&0xff)
+
+
+/**************************************************************************
+ * Native Font control
+ */
+
+#define WC_NATIVEFONTCTLA      "NativeFontCtl"
+#if defined(__GNUC__)
+# define WC_NATIVEFONTCTLW (const WCHAR []){ 'N','a','t','i','v','e', \
+  'F','o','n','t','C','t','l',0 }
+#elif defined(_MSC_VER)
+# define WC_NATIVEFONTCTLW      L"NativeFontCtl"
+#else
+static const WCHAR WC_NATIVEFONTCTLW[] = { 'N','a','t','i','v','e',
+  'F','o','n','t','C','t','l',0 };
+#endif
+#define WC_NATIVEFONTCTL       WINELIB_NAME_AW(WC_NATIVEFONTCTL)
+
+#define NFS_EDIT               0x0001
+#define NFS_STATIC             0x0002
+#define NFS_LISTCOMBO          0x0004
+#define NFS_BUTTON             0x0008
+#define NFS_ALL                        0x0010
+
+
+/**************************************************************************
+ * Month calendar control
+ *
+ */
+
+#define MONTHCAL_CLASSA        "SysMonthCal32"
+#if defined(__GNUC__)
+# define MONTHCAL_CLASSW (const WCHAR []){ 'S','y','s', \
+  'M','o','n','t','h','C','a','l','3','2',0 }
+#elif defined(_MSC_VER)
+# define MONTHCAL_CLASSW L"SysMonthCal32"
+#else
+static const WCHAR MONTHCAL_CLASSW[] = { 'S','y','s',
+  'M','o','n','t','h','C','a','l','3','2',0 };
+#endif
+#define MONTHCAL_CLASS         WINELIB_NAME_AW(MONTHCAL_CLASS)
+
+#define MCM_FIRST             0x1000
+#define MCN_FIRST             (0U-750U)
+#define MCN_LAST              (0U-759U)
+
+
+#define MCM_GETCURSEL         (MCM_FIRST + 1)
+#define MCM_SETCURSEL         (MCM_FIRST + 2)
+#define MCM_GETMAXSELCOUNT    (MCM_FIRST + 3)
+#define MCM_SETMAXSELCOUNT    (MCM_FIRST + 4)
+#define MCM_GETSELRANGE       (MCM_FIRST + 5)
+#define MCM_SETSELRANGE       (MCM_FIRST + 6)
+#define MCM_GETMONTHRANGE     (MCM_FIRST + 7)
+#define MCM_SETDAYSTATE       (MCM_FIRST + 8)
+#define MCM_GETMINREQRECT     (MCM_FIRST + 9)
+#define MCM_SETCOLOR          (MCM_FIRST + 10)
+#define MCM_GETCOLOR          (MCM_FIRST + 11)
+#define MCM_SETTODAY          (MCM_FIRST + 12)
+#define MCM_GETTODAY          (MCM_FIRST + 13)
+#define MCM_HITTEST           (MCM_FIRST + 14)
+#define MCM_SETFIRSTDAYOFWEEK (MCM_FIRST + 15)
+#define MCM_GETFIRSTDAYOFWEEK (MCM_FIRST + 16)
+#define MCM_GETRANGE          (MCM_FIRST + 17)
+#define MCM_SETRANGE          (MCM_FIRST + 18)
+#define MCM_GETMONTHDELTA     (MCM_FIRST + 19)
+#define MCM_SETMONTHDELTA     (MCM_FIRST + 20)
+#define MCM_GETMAXTODAYWIDTH  (MCM_FIRST + 21)
+#define MCM_GETUNICODEFORMAT   CCM_GETUNICODEFORMAT
+#define MCM_SETUNICODEFORMAT   CCM_SETUNICODEFORMAT
+
+
+/* Notifications */
+
+#define MCN_SELCHANGE         (MCN_FIRST + 1)
+#define MCN_GETDAYSTATE       (MCN_FIRST + 3)
+#define MCN_SELECT            (MCN_FIRST + 4)
+
+#define MCSC_BACKGROUND   0
+#define MCSC_TEXT         1
+#define MCSC_TITLEBK      2
+#define MCSC_TITLETEXT    3
+#define MCSC_MONTHBK      4
+#define MCSC_TRAILINGTEXT 5
+
+#define MCS_DAYSTATE           0x0001
+#define MCS_MULTISELECT        0x0002
+#define MCS_WEEKNUMBERS        0x0004
+#define MCS_NOTODAY            0x0010
+#define MCS_NOTODAYCIRCLE      0x0008
+
+#define MCHT_TITLE             0x00010000
+#define MCHT_CALENDAR          0x00020000
+#define MCHT_TODAYLINK         0x00030000
+
+#define MCHT_NEXT              0x01000000
+#define MCHT_PREV              0x02000000
+#define MCHT_NOWHERE           0x00000000
+#define MCHT_TITLEBK           (MCHT_TITLE)
+#define MCHT_TITLEMONTH        (MCHT_TITLE | 0x0001)
+#define MCHT_TITLEYEAR         (MCHT_TITLE | 0x0002)
+#define MCHT_TITLEBTNNEXT      (MCHT_TITLE | MCHT_NEXT | 0x0003)
+#define MCHT_TITLEBTNPREV      (MCHT_TITLE | MCHT_PREV | 0x0003)
+
+#define MCHT_CALENDARBK        (MCHT_CALENDAR)
+#define MCHT_CALENDARDATE      (MCHT_CALENDAR | 0x0001)
+#define MCHT_CALENDARDATENEXT  (MCHT_CALENDARDATE | MCHT_NEXT)
+#define MCHT_CALENDARDATEPREV  (MCHT_CALENDARDATE | MCHT_PREV)
+#define MCHT_CALENDARDAY       (MCHT_CALENDAR | 0x0002)
+#define MCHT_CALENDARWEEKNUM   (MCHT_CALENDAR | 0x0003)
+
+
+
+#define GMR_VISIBLE     0
+#define GMR_DAYSTATE    1
+
+
+/*  Month calendar's structures */
+
+
+typedef struct {
+        UINT cbSize;
+        POINT pt;
+        UINT uHit;
+        SYSTEMTIME st;
+} MCHITTESTINFO, *PMCHITTESTINFO;
+
+typedef struct tagNMSELCHANGE
+{
+    NMHDR           nmhdr;
+    SYSTEMTIME      stSelStart;
+    SYSTEMTIME      stSelEnd;
+} NMSELCHANGE, *LPNMSELCHANGE;
+
+typedef NMSELCHANGE NMSELECT, *LPNMSELECT;
+typedef DWORD MONTHDAYSTATE, *LPMONTHDAYSTATE;
+
+typedef struct tagNMDAYSTATE
+{
+    NMHDR           nmhdr;
+    SYSTEMTIME      stStart;
+    int             cDayState;
+    LPMONTHDAYSTATE prgDayState;
+} NMDAYSTATE, *LPNMDAYSTATE;
+
+
+/* macros */
+
+#define MonthCal_GetCurSel(hmc, pst) \
+               (BOOL)SNDMSGA(hmc, MCM_GETCURSEL, 0, (LPARAM)(pst))
+#define MonthCal_SetCurSel(hmc, pst)  \
+               (BOOL)SNDMSGA(hmc, MCM_SETCURSEL, 0, (LPARAM)(pst))
+#define MonthCal_GetMaxSelCount(hmc) \
+               (DWORD)SNDMSGA(hmc, MCM_GETMAXSELCOUNT, 0, 0L)
+#define MonthCal_SetMaxSelCount(hmc, n) \
+               (BOOL)SNDMSGA(hmc, MCM_SETMAXSELCOUNT, (WPARAM)(n), 0L)
+#define MonthCal_GetSelRange(hmc, rgst) \
+               SNDMSGA(hmc, MCM_GETSELRANGE, 0, (LPARAM) (rgst))
+#define MonthCal_SetSelRange(hmc, rgst) \
+               SNDMSGA(hmc, MCM_SETSELRANGE, 0, (LPARAM) (rgst))
+#define MonthCal_GetMonthRange(hmc, gmr, rgst) \
+               (DWORD)SNDMSGA(hmc, MCM_GETMONTHRANGE, (WPARAM)(gmr), (LPARAM)(rgst))
+#define MonthCal_SetDayState(hmc, cbds, rgds) \
+               SNDMSGA(hmc, MCM_SETDAYSTATE, (WPARAM)(cbds), (LPARAM)(rgds))
+#define MonthCal_GetMinReqRect(hmc, prc) \
+               SNDMSGA(hmc, MCM_GETMINREQRECT, 0, (LPARAM)(prc))
+#define MonthCal_SetColor(hmc, iColor, clr)\
+        SNDMSGA(hmc, MCM_SETCOLOR, iColor, clr)
+#define MonthCal_GetColor(hmc, iColor) \
+               SNDMSGA(hmc, MCM_SETCOLOR, iColor, 0)
+#define MonthCal_GetToday(hmc, pst)\
+               (BOOL)SNDMSGA(hmc, MCM_GETTODAY, 0, (LPARAM)pst)
+#define MonthCal_SetToday(hmc, pst)\
+               SNDMSGA(hmc, MCM_SETTODAY, 0, (LPARAM)pst)
+#define MonthCal_HitTest(hmc, pinfo) \
+        SNDMSGA(hmc, MCM_HITTEST, 0, (LPARAM)(PMCHITTESTINFO)pinfo)
+#define MonthCal_SetFirstDayOfWeek(hmc, iDay) \
+        SNDMSGA(hmc, MCM_SETFIRSTDAYOFWEEK, 0, iDay)
+#define MonthCal_GetFirstDayOfWeek(hmc) \
+        (DWORD)SNDMSGA(hmc, MCM_GETFIRSTDAYOFWEEK, 0, 0)
+#define MonthCal_GetRange(hmc, rgst) \
+        (DWORD)SNDMSGA(hmc, MCM_GETRANGE, 0, (LPARAM)(rgst))
+#define MonthCal_SetRange(hmc, gd, rgst) \
+        (BOOL)SNDMSGA(hmc, MCM_SETRANGE, (WPARAM)(gd), (LPARAM)(rgst))
+#define MonthCal_GetMonthDelta(hmc) \
+        (int)SNDMSGA(hmc, MCM_GETMONTHDELTA, 0, 0)
+#define MonthCal_SetMonthDelta(hmc, n) \
+        (int)SNDMSGA(hmc, MCM_SETMONTHDELTA, n, 0)
+#define MonthCal_GetMaxTodayWidth(hmc) \
+        (DWORD)SNDMSGA(hmc, MCM_GETMAXTODAYWIDTH, 0, 0)
+#define MonthCal_SetUnicodeFormat(hwnd, fUnicode)  \
+        (BOOL)SNDMSGA((hwnd), MCM_SETUNICODEFORMAT, (WPARAM)(fUnicode), 0)
+#define MonthCal_GetUnicodeFormat(hwnd)  \
+        (BOOL)SNDMSGA((hwnd), MCM_GETUNICODEFORMAT, 0, 0)
+
+
+/**************************************************************************
+ * Date and time picker control
+ */
+
+#define DATETIMEPICK_CLASSA    "SysDateTimePick32"
+#if defined(__GNUC__)
+# define DATETIMEPICK_CLASSW (const WCHAR []){ 'S','y','s', \
+  'D','a','t','e','T','i','m','e','P','i','c','k','3','2',0 }
+#elif defined(_MSC_VER)
+# define DATETIMEPICK_CLASSW    L"SysDateTimePick32"
+#else
+static const WCHAR DATETIMEPICK_CLASSW[] = { 'S','y','s',
+  'D','a','t','e','T','i','m','e','P','i','c','k','3','2',0 };
+#endif
+#define DATETIMEPICK_CLASS     WINELIB_NAME_AW(DATETIMEPICK_CLASS)
+
+#define DTM_FIRST        0x1000
+#define DTN_FIRST       (0U-760U)
+#define DTN_LAST        (0U-799U)
+
+
+#define DTM_GETSYSTEMTIME      (DTM_FIRST+1)
+#define DTM_SETSYSTEMTIME      (DTM_FIRST+2)
+#define DTM_GETRANGE           (DTM_FIRST+3)
+#define DTM_SETRANGE           (DTM_FIRST+4)
+#define DTM_SETFORMATA     (DTM_FIRST+5)
+#define DTM_SETFORMATW     (DTM_FIRST + 50)
+#define DTM_SETFORMAT          WINELIB_NAME_AW(DTM_SETFORMAT)
+#define DTM_SETMCCOLOR         (DTM_FIRST+6)
+#define DTM_GETMCCOLOR         (DTM_FIRST+7)
+#define DTM_GETMONTHCAL                (DTM_FIRST+8)
+#define DTM_SETMCFONT          (DTM_FIRST+9)
+#define DTM_GETMCFONT          (DTM_FIRST+10)
+
+
+/* Datetime Notifications */
+
+#define DTN_DATETIMECHANGE  (DTN_FIRST + 1)
+#define DTN_USERSTRINGA     (DTN_FIRST + 2)
+#define DTN_WMKEYDOWNA      (DTN_FIRST + 3)
+#define DTN_FORMATA         (DTN_FIRST + 4)
+#define DTN_FORMATQUERYA    (DTN_FIRST + 5)
+#define DTN_DROPDOWN        (DTN_FIRST + 6)
+#define DTN_CLOSEUP         (DTN_FIRST + 7)
+#define DTN_USERSTRINGW     (DTN_FIRST + 15)
+#define DTN_WMKEYDOWNW      (DTN_FIRST + 16)
+#define DTN_FORMATW         (DTN_FIRST + 17)
+#define DTN_FORMATQUERYW    (DTN_FIRST + 18)
+
+#define DTN_USERSTRING      WINELIB_NAME_AW(DTN_USERSTRING)
+#define DTN_WMKEYDOWN       WINELIB_NAME_AW(DTN_WMKEYDOWN)
+#define DTN_FORMAT          WINELIB_NAME_AW(DTN_FORMAT)
+#define DTN_FORMATQUERY     WINELIB_NAME_AW(DTN_FORMATQUERY)
+
+#define DTS_SHORTDATEFORMAT 0x0000
+#define DTS_UPDOWN          0x0001
+#define DTS_SHOWNONE        0x0002
+#define DTS_LONGDATEFORMAT  0x0004
+#define DTS_TIMEFORMAT      0x0009
+#define DTS_APPCANPARSE     0x0010
+#define DTS_RIGHTALIGN      0x0020
+
+typedef struct tagNMDATETIMECHANGE
+{
+    NMHDR       nmhdr;
+    DWORD       dwFlags;
+    SYSTEMTIME  st;
+} NMDATETIMECHANGE, *LPNMDATETIMECHANGE;
+
+typedef struct tagNMDATETIMESTRINGA
+{
+    NMHDR      nmhdr;
+    LPCSTR     pszUserString;
+    SYSTEMTIME st;
+    DWORD      dwFlags;
+} NMDATETIMESTRINGA, *LPNMDATETIMESTRINGA;
+
+typedef struct tagNMDATETIMESTRINGW
+{
+    NMHDR      nmhdr;
+    LPCWSTR    pszUserString;
+    SYSTEMTIME st;
+    DWORD      dwFlags;
+} NMDATETIMESTRINGW, *LPNMDATETIMESTRINGW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMESTRING)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMESTRING)
+
+typedef struct tagNMDATETIMEWMKEYDOWNA
+{
+    NMHDR      nmhdr;
+    int        nVirtKey;
+    LPCSTR     pszFormat;
+    SYSTEMTIME st;
+} NMDATETIMEWMKEYDOWNA, *LPNMDATETIMEWMKEYDOWNA;
+
+typedef struct tagNMDATETIMEWMKEYDOWNW
+{
+    NMHDR      nmhdr;
+    int        nVirtKey;
+    LPCWSTR    pszFormat;
+    SYSTEMTIME st;
+} NMDATETIMEWMKEYDOWNW, *LPNMDATETIMEWMKEYDOWNW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEWMKEYDOWN)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEWMKEYDOWN)
+
+typedef struct tagNMDATETIMEFORMATA
+{
+    NMHDR nmhdr;
+    LPCSTR  pszFormat;
+    SYSTEMTIME st;
+    LPCSTR pszDisplay;
+    CHAR szDisplay[64];
+} NMDATETIMEFORMATA, *LPNMDATETIMEFORMATA;
+
+
+typedef struct tagNMDATETIMEFORMATW
+{
+    NMHDR nmhdr;
+    LPCWSTR pszFormat;
+    SYSTEMTIME st;
+    LPCWSTR pszDisplay;
+    WCHAR szDisplay[64];
+} NMDATETIMEFORMATW, *LPNMDATETIMEFORMATW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEFORMAT)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEFORMAT)
+
+typedef struct tagNMDATETIMEFORMATQUERYA
+{
+    NMHDR nmhdr;
+    LPCSTR pszFormat;
+    SIZE szMax;
+} NMDATETIMEFORMATQUERYA, *LPNMDATETIMEFORMATQUERYA;
+
+typedef struct tagNMDATETIMEFORMATQUERYW
+{
+    NMHDR nmhdr;
+    LPCWSTR pszFormat;
+    SIZE szMax;
+} NMDATETIMEFORMATQUERYW, *LPNMDATETIMEFORMATQUERYW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEFORMATQUERY)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEFORMATQUERY)
+
+
+
+#define GDT_ERROR    -1
+#define GDT_VALID    0
+#define GDT_NONE     1
+
+#define GDTR_MIN     0x0001
+#define GDTR_MAX     0x0002
+
+
+#define DateTime_GetSystemtime(hdp, pst)   \
+  (DWORD)SNDMSGA (hdp, DTM_GETSYSTEMTIME , 0, (LPARAM)(pst))
+#define DateTime_SetSystemtime(hdp, gd, pst)   \
+  (BOOL)SNDMSGA (hdp, DTM_SETSYSTEMTIME, (LPARAM)(gd), (LPARAM)(pst))
+#define DateTime_GetRange(hdp, rgst)  \
+  (DWORD)SNDMSGA (hdp, DTM_GETRANGE, 0, (LPARAM)(rgst))
+#define DateTime_SetRange(hdp, gd, rgst) \
+   (BOOL)SNDMSGA (hdp, DTM_SETRANGE, (WPARAM)(gd), (LPARAM)(rgst))
+#define DateTime_SetFormat WINELIB_NAME_AW(DateTime_SetFormat)
+#define DateTime_SetFormatA(hdp, sz)  \
+  (BOOL)SNDMSGA (hdp, DTM_SETFORMAT, 0, (LPARAM)(sz))
+#define DateTime_SetFormatW(hdp, sz)  \
+  (BOOL)SNDMSGW (hdp, DTM_SETFORMAT, 0, (LPARAM)(sz))
+#define DateTime_GetMonthCalColor(hdp, iColor) \
+  SNDMSGA (hdp, DTM_GETMCCOLOR, iColor, 0)
+#define DateTime_GetMonthCal(hdp)  \
+  (HWND) SNDMSGA (hdp, DTM_GETMONTHCAL, 0, 0)
+#define DateTime_SetMonthCalFont(hdp, hfont, fRedraw) \
+  SNDMSGA (hdp, DTM_SETMCFONT, (WPARAM)hfont, (LPARAM)fRedraw)
+#define DateTime_GetMonthCalFont(hdp) \
+  SNDMSGA (hdp, DTM_GETMCFONT, 0, 0)
+
+
+
+
+
+
+/**************************************************************************
+ *  UNDOCUMENTED functions
+ */
+
+/* private heap memory functions */
+
+LPVOID WINAPI COMCTL32_Alloc (DWORD);
+LPVOID WINAPI COMCTL32_ReAlloc (LPVOID, DWORD);
+BOOL WINAPI COMCTL32_Free (LPVOID);
+DWORD  WINAPI COMCTL32_GetSize (LPVOID);
+
+LPWSTR WINAPI COMCTL32_StrChrW (LPCWSTR, WORD);
+
+
+INT  WINAPI Str_GetPtrA (LPCSTR, LPSTR, INT);
+BOOL WINAPI Str_SetPtrA (LPSTR *, LPCSTR);
+INT  WINAPI Str_GetPtrW (LPCWSTR, LPWSTR, INT);
+BOOL WINAPI Str_SetPtrW (LPWSTR *, LPCWSTR);
+#define Str_GetPtr WINELIB_NAME_AW(Str_GetPtr)
+#define Str_SetPtr WINELIB_NAME_AW(Str_SetPtr)
+
+
+/* Dynamic Storage Array */
+
+typedef struct _DSA
+{
+    INT  nItemCount;
+    LPVOID pData;
+    INT  nMaxCount;
+    INT  nItemSize;
+    INT  nGrow;
+} DSA, *HDSA;
+
+HDSA   WINAPI DSA_Create (INT, INT);
+BOOL WINAPI DSA_DeleteAllItems (const HDSA);
+INT  WINAPI DSA_DeleteItem (const HDSA, INT);
+BOOL WINAPI DSA_Destroy (const HDSA);
+BOOL WINAPI DSA_GetItem (const HDSA, INT, LPVOID);
+LPVOID WINAPI DSA_GetItemPtr (const HDSA, INT);
+INT  WINAPI DSA_InsertItem (const HDSA, INT, LPVOID);
+BOOL WINAPI DSA_SetItem (const HDSA, INT, LPVOID);
+
+typedef INT (CALLBACK *DSAENUMPROC)(LPVOID, DWORD);
+VOID   WINAPI DSA_EnumCallback (const HDSA, DSAENUMPROC, LPARAM);
+BOOL WINAPI DSA_DestroyCallback (const HDSA, DSAENUMPROC, LPARAM);
+
+
+/* Dynamic Pointer Array */
+
+typedef struct _DPA
+{
+    INT    nItemCount;
+    LPVOID   *ptrs;
+    HANDLE hHeap;
+    INT    nGrow;
+    INT    nMaxCount;
+} DPA, *HDPA;
+
+HDPA   WINAPI DPA_Create (INT);
+HDPA   WINAPI DPA_CreateEx (INT, HANDLE);
+BOOL WINAPI DPA_Destroy (const HDPA);
+HDPA   WINAPI DPA_Clone (const HDPA, const HDPA);
+LPVOID WINAPI DPA_GetPtr (const HDPA, INT);
+INT  WINAPI DPA_GetPtrIndex (const HDPA, LPVOID);
+BOOL WINAPI DPA_Grow (const HDPA, INT);
+BOOL WINAPI DPA_SetPtr (const HDPA, INT, LPVOID);
+INT  WINAPI DPA_InsertPtr (const HDPA, INT, LPVOID);
+LPVOID WINAPI DPA_DeletePtr (const HDPA, INT);
+BOOL WINAPI DPA_DeleteAllPtrs (const HDPA);
+
+typedef INT (CALLBACK *PFNDPACOMPARE)(LPVOID, LPVOID, LPARAM);
+BOOL WINAPI DPA_Sort (const HDPA, PFNDPACOMPARE, LPARAM);
+
+#define DPAS_SORTED             0x0001
+#define DPAS_INSERTBEFORE       0x0002
+#define DPAS_INSERTAFTER        0x0004
+
+INT  WINAPI DPA_Search (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
+
+#define DPAM_NOSORT             0x0001
+#define DPAM_INSERT             0x0004
+#define DPAM_DELETE             0x0008
+
+typedef PVOID (CALLBACK *PFNDPAMERGE)(DWORD,PVOID,PVOID,LPARAM);
+BOOL WINAPI DPA_Merge (const HDPA, const HDPA, DWORD, PFNDPACOMPARE, PFNDPAMERGE, LPARAM);
+
+typedef INT (CALLBACK *DPAENUMPROC)(LPVOID, DWORD);
+VOID   WINAPI DPA_EnumCallback (const HDPA, DPAENUMPROC, LPARAM);
+BOOL WINAPI DPA_DestroyCallback (const HDPA, DPAENUMPROC, LPARAM);
+
+
+#define DPA_GetPtrCount(hdpa)  (*(INT*)(hdpa))
+#define DPA_GetPtrPtr(hdpa)    (*((LPVOID**)((BYTE*)(hdpa)+sizeof(INT))))
+#define DPA_FastGetPtr(hdpa,i) (DPA_GetPtrPtr(hdpa)[i])
+
+
+/* notification helper functions */
+
+LRESULT WINAPI COMCTL32_SendNotify (HWND, HWND, UINT, LPNMHDR);
+
+/* type and functionality of last parameter is still unknown */
+LRESULT WINAPI COMCTL32_SendNotifyEx (HWND, HWND, UINT, LPNMHDR, DWORD);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __WINE_COMMCTRL_H */
diff --git a/lib/advapi32/misc/.cvsignore b/lib/advapi32/misc/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/advapi32/reg/.cvsignore b/lib/advapi32/reg/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/advapi32/sec/.cvsignore b/lib/advapi32/sec/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/advapi32/service/.cvsignore b/lib/advapi32/service/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/advapi32/token/.cvsignore b/lib/advapi32/token/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/crtdll/ctype/ctype.c b/lib/crtdll/ctype/ctype.c
new file mode 100644 (file)
index 0000000..5861d6d
--- /dev/null
@@ -0,0 +1,264 @@
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/ctype.h>
+
+unsigned short _ctype[] = {
+       0,                      /* <EOF>, 0xFFFF */
+       _CONTROL,               /* CTRL+@, 0x00 */
+       _CONTROL,               /* CTRL+A, 0x01 */
+       _CONTROL,               /* CTRL+B, 0x02 */
+       _CONTROL,               /* CTRL+C, 0x03 */
+       _CONTROL,               /* CTRL+D, 0x04 */
+       _CONTROL,               /* CTRL+E, 0x05 */
+       _CONTROL,               /* CTRL+F, 0x06 */
+       _CONTROL,               /* CTRL+G, 0x07 */
+       _CONTROL,               /* CTRL+H, 0x08 */
+       _CONTROL | _SPACE,      /* CTRL+I, 0x09 */
+       _CONTROL | _SPACE,      /* CTRL+J, 0x0a */
+       _CONTROL | _SPACE,      /* CTRL+K, 0x0b */
+       _CONTROL | _SPACE,      /* CTRL+L, 0x0c */
+       _CONTROL | _SPACE,      /* CTRL+M, 0x0d */
+       _CONTROL,               /* CTRL+N, 0x0e */
+       _CONTROL,               /* CTRL+O, 0x0f */
+       _CONTROL,               /* CTRL+P, 0x10 */
+       _CONTROL,               /* CTRL+Q, 0x11 */
+       _CONTROL,               /* CTRL+R, 0x12 */
+       _CONTROL,               /* CTRL+S, 0x13 */
+       _CONTROL,               /* CTRL+T, 0x14 */
+       _CONTROL,               /* CTRL+U, 0x15 */
+       _CONTROL,               /* CTRL+V, 0x16 */
+       _CONTROL,               /* CTRL+W, 0x17 */
+       _CONTROL,               /* CTRL+X, 0x18 */
+       _CONTROL,               /* CTRL+Y, 0x19 */
+       _CONTROL,               /* CTRL+Z, 0x1a */
+       _CONTROL,               /* CTRL+[, 0x1b */
+       _CONTROL,               /* CTRL+\, 0x1c */
+       _CONTROL,               /* CTRL+], 0x1d */
+       _CONTROL,               /* CTRL+^, 0x1e */
+       _CONTROL,               /* CTRL+_, 0x1f */
+       _SPACE | _BLANK,        /* ` ', 0x20 */
+       _PUNCT,                 /* `!', 0x21 */
+       _PUNCT,                 /* 0x22 */
+       _PUNCT,                 /* `#', 0x23 */
+       _PUNCT,                 /* `$', 0x24 */
+       _PUNCT,                 /* `%', 0x25 */
+       _PUNCT,                 /* `&', 0x26 */
+       _PUNCT,                 /* 0x27 */
+       _PUNCT,                 /* `(', 0x28 */
+       _PUNCT,                 /* `)', 0x29 */
+       _PUNCT,                 /* `*', 0x2a */
+       _PUNCT,                 /* `+', 0x2b */
+       _PUNCT,                 /* `,', 0x2c */
+       _PUNCT,                 /* `-', 0x2d */
+       _PUNCT,                 /* `.', 0x2e */
+       _PUNCT,                 /* `/', 0x2f */
+       _DIGIT | _HEX,          /* `0', 0x30 */
+       _DIGIT | _HEX,          /* `1', 0x31 */
+       _DIGIT | _HEX,          /* `2', 0x32 */
+       _DIGIT | _HEX,          /* `3', 0x33 */
+       _DIGIT | _HEX,          /* `4', 0x34 */
+       _DIGIT | _HEX,          /* `5', 0x35 */
+       _DIGIT | _HEX,          /* `6', 0x36 */
+       _DIGIT | _HEX,          /* `7', 0x37 */
+       _DIGIT | _HEX,          /* `8', 0x38 */
+       _DIGIT | _HEX,          /* `9', 0x39 */
+       _PUNCT,                 /* `:', 0x3a */
+       _PUNCT,                 /* `;', 0x3b */
+       _PUNCT,                 /* `<', 0x3c */
+       _PUNCT,                 /* `=', 0x3d */
+       _PUNCT,                 /* `>', 0x3e */
+       _PUNCT,                 /* `?', 0x3f */
+       _PUNCT,                 /* `@', 0x40 */
+       _UPPER | _HEX,          /* `A', 0x41 */
+       _UPPER | _HEX,          /* `B', 0x42 */
+       _UPPER | _HEX,          /* `C', 0x43 */
+       _UPPER | _HEX,          /* `D', 0x44 */
+       _UPPER | _HEX,          /* `E', 0x45 */
+       _UPPER | _HEX,          /* `F', 0x46 */
+       _UPPER,                 /* `G', 0x47 */
+       _UPPER,                 /* `H', 0x48 */
+       _UPPER,                 /* `I', 0x49 */
+       _UPPER,                 /* `J', 0x4a */
+       _UPPER,                 /* `K', 0x4b */
+       _UPPER,                 /* `L', 0x4c */
+       _UPPER,                 /* `M', 0x4d */
+       _UPPER,                 /* `N', 0x4e */
+       _UPPER,                 /* `O', 0x4f */
+       _UPPER,                 /* `P', 0x50 */
+       _UPPER,                 /* `Q', 0x51 */
+       _UPPER,                 /* `R', 0x52 */
+       _UPPER,                 /* `S', 0x53 */
+       _UPPER,                 /* `T', 0x54 */
+       _UPPER,                 /* `U', 0x55 */
+       _UPPER,                 /* `V', 0x56 */
+       _UPPER,                 /* `W', 0x57 */
+       _UPPER,                 /* `X', 0x58 */
+       _UPPER,                 /* `Y', 0x59 */
+       _UPPER,                 /* `Z', 0x5a */
+       _PUNCT,                 /* `[', 0x5b */
+       _PUNCT,                 /* 0x5c */
+       _PUNCT,                 /* `]', 0x5d */
+       _PUNCT,                 /* `^', 0x5e */
+       _PUNCT,                 /* `_', 0x5f */
+       _PUNCT,                 /* 0x60 */
+       _LOWER | _HEX,          /* `a', 0x61 */
+       _LOWER | _HEX,          /* `b', 0x62 */
+       _LOWER | _HEX,          /* `c', 0x63 */
+       _LOWER | _HEX,          /* `d', 0x64 */
+       _LOWER | _HEX,          /* `e', 0x65 */
+       _LOWER | _HEX,          /* `f', 0x66 */
+       _LOWER,                 /* `g', 0x67 */
+       _LOWER,                 /* `h', 0x68 */
+       _LOWER,                 /* `i', 0x69 */
+       _LOWER,                 /* `j', 0x6a */
+       _LOWER,                 /* `k', 0x6b */
+       _LOWER,                 /* `l', 0x6c */
+       _LOWER,                 /* `m', 0x6d */
+       _LOWER,                 /* `n', 0x6e */
+       _LOWER,                 /* `o', 0x6f */
+       _LOWER,                 /* `p', 0x70 */
+       _LOWER,                 /* `q', 0x71 */
+       _LOWER,                 /* `r', 0x72 */
+       _LOWER,                 /* `s', 0x73 */
+       _LOWER,                 /* `t', 0x74 */
+       _LOWER,                 /* `u', 0x75 */
+       _LOWER,                 /* `v', 0x76 */
+       _LOWER,                 /* `w', 0x77 */
+       _LOWER,                 /* `x', 0x78 */
+       _LOWER,                 /* `y', 0x79 */
+       _LOWER,                 /* `z', 0x7a */
+       _PUNCT,                 /* `{', 0x7b */
+       _PUNCT,                 /* `|', 0x7c */
+       _PUNCT,                 /* `}', 0x7d */
+       _PUNCT,                 /* `~', 0x7e */
+       _CONTROL,               /* 0x7f */
+       0,                      /* 0x80 */
+       0,                      /* 0x81 */
+       0,                      /* 0x82 */
+       0,                      /* 0x83 */
+       0,                      /* 0x84 */
+       0,                      /* 0x85 */
+       0,                      /* 0x86 */
+       0,                      /* 0x87 */
+       0,                      /* 0x88 */
+       0,                      /* 0x89 */
+       0,                      /* 0x8a */
+       0,                      /* 0x8b */
+       0,                      /* 0x8c */
+       0,                      /* 0x8d */
+       0,                      /* 0x8e */
+       0,                      /* 0x8f */
+       0,                      /* 0x90 */
+       0,                      /* 0x91 */
+       0,                      /* 0x92 */
+       0,                      /* 0x93 */
+       0,                      /* 0x94 */
+       0,                      /* 0x95 */
+       0,                      /* 0x96 */
+       0,                      /* 0x97 */
+       0,                      /* 0x98 */
+       0,                      /* 0x99 */
+       0,                      /* 0x9a */
+       0,                      /* 0x9b */
+       0,                      /* 0x9c */
+       0,                      /* 0x9d */
+       0,                      /* 0x9e */
+       0,                      /* 0x9f */
+       0,                      /* 0xa0 */
+       0,                      /* 0xa1 */
+       0,                      /* 0xa2 */
+       0,                      /* 0xa3 */
+       0,                      /* 0xa4 */
+       0,                      /* 0xa5 */
+       0,                      /* 0xa6 */
+       0,                      /* 0xa7 */
+       0,                      /* 0xa8 */
+       0,                      /* 0xa9 */
+       0,                      /* 0xaa */
+       0,                      /* 0xab */
+       0,                      /* 0xac */
+       0,                      /* 0xad */
+       0,                      /* 0xae */
+       0,                      /* 0xaf */
+       0,                      /* 0xb0 */
+       0,                      /* 0xb1 */
+       0,                      /* 0xb2 */
+       0,                      /* 0xb3 */
+       0,                      /* 0xb4 */
+       0,                      /* 0xb5 */
+       0,                      /* 0xb6 */
+       0,                      /* 0xb7 */
+       0,                      /* 0xb8 */
+       0,                      /* 0xb9 */
+       0,                      /* 0xba */
+       0,                      /* 0xbb */
+       0,                      /* 0xbc */
+       0,                      /* 0xbd */
+       0,                      /* 0xbe */
+       0,                      /* 0xbf */
+       0,                      /* 0xc0 */
+       0,                      /* 0xc1 */
+       0,                      /* 0xc2 */
+       0,                      /* 0xc3 */
+       0,                      /* 0xc4 */
+       0,                      /* 0xc5 */
+       0,                      /* 0xc6 */
+       0,                      /* 0xc7 */
+       0,                      /* 0xc8 */
+       0,                      /* 0xc9 */
+       0,                      /* 0xca */
+       0,                      /* 0xcb */
+       0,                      /* 0xcc */
+       0,                      /* 0xcd */
+       0,                      /* 0xce */
+       0,                      /* 0xcf */
+       0,                      /* 0xd0 */
+       0,                      /* 0xd1 */
+       0,                      /* 0xd2 */
+       0,                      /* 0xd3 */
+       0,                      /* 0xd4 */
+       0,                      /* 0xd5 */
+       0,                      /* 0xd6 */
+       0,                      /* 0xd7 */
+       0,                      /* 0xd8 */
+       0,                      /* 0xd9 */
+       0,                      /* 0xda */
+       0,                      /* 0xdb */
+       0,                      /* 0xdc */
+       0,                      /* 0xdd */
+       0,                      /* 0xde */
+       0,                      /* 0xdf */
+       0,                      /* 0xe0 */
+       0,                      /* 0xe1 */
+       0,                      /* 0xe2 */
+       0,                      /* 0xe3 */
+       0,                      /* 0xe4 */
+       0,                      /* 0xe5 */
+       0,                      /* 0xe6 */
+       0,                      /* 0xe7 */
+       0,                      /* 0xe8 */
+       0,                      /* 0xe9 */
+       0,                      /* 0xea */
+       0,                      /* 0xeb */
+       0,                      /* 0xec */
+       0,                      /* 0xed */
+       0,                      /* 0xee */
+       0,                      /* 0xef */
+       0,                      /* 0xf0 */
+       0,                      /* 0xf1 */
+       0,                      /* 0xf2 */
+       0,                      /* 0xf3 */
+       0,                      /* 0xf4 */
+       0,                      /* 0xf5 */
+       0,                      /* 0xf6 */
+       0,                      /* 0xf7 */
+       0,                      /* 0xf8 */
+       0,                      /* 0xf9 */
+       0,                      /* 0xfa */
+       0,                      /* 0xfb */
+       0,                      /* 0xfc */
+       0,                      /* 0xfd */
+       0,                      /* 0xfe */
+       0                       /* 0xff */
+};
+
+/* EOF */
diff --git a/lib/crtdll/misc/assert.c b/lib/crtdll/misc/assert.c
new file mode 100644 (file)
index 0000000..0469371
--- /dev/null
@@ -0,0 +1,13 @@
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/assert.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/signal.h>
+
+
+void _assert(const char* msg, const char* file, int line)
+{
+    /* Assertion failed at foo.c line 45: x<y */
+    fprintf(stderr, "Assertion failed at %s line %d: %s\n", file, line, msg);
+    raise(SIGABRT);
+}
diff --git a/lib/crtdll/misc/debug.c b/lib/crtdll/misc/debug.c
new file mode 100644 (file)
index 0000000..16b94a5
--- /dev/null
@@ -0,0 +1,19 @@
+#include <windows.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+void debug_printf(char* fmt, ...)
+{
+   va_list args;
+   char buffer[255];
+   HANDLE OutputHandle;
+   
+   AllocConsole();
+   OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+   va_start(args,fmt);
+   vsprintf(buffer,fmt,args);
+   WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
+   va_end(args);
+}
diff --git a/lib/crtdll/stdio/fgetws.c b/lib/crtdll/stdio/fgetws.c
new file mode 100644 (file)
index 0000000..282b8fc
--- /dev/null
@@ -0,0 +1,63 @@
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+//wchar_t* fgetws(wchar_t* wcaBuffer, int nBufferSize, FILE* fileRead);
+//char* fgets(char *s, int n, FILE *f);
+//int _getw(FILE *stream);
+/*
+// Read a word (int) from STREAM.
+int _getw(FILE *stream)
+{
+  int w;
+
+  // Is there a better way?
+  if (fread( &w, sizeof(w), 1, stream) != 1)
+    return(EOF);
+  return(w);
+}
+
+//getc can be a macro
+#undef getc
+
+int getc(FILE *fp)
+{
+    int c = -1;
+// check for invalid stream
+       if ( !__validfp (fp) ) {
+               __set_errno(EINVAL);
+               return EOF;
+       }
+// check for read access on stream
+       if ( !OPEN4READING(fp) ) {
+               __set_errno(EINVAL);
+               return -1;
+       }
+       if(fp->_cnt > 0) {
+               fp->_cnt--;
+               c =  (int)*fp->_ptr++;
+       } 
+       else {
+               c =  _filbuf(fp);
+       }
+       return c;
+}
+ */
+
+wchar_t* fgetws(wchar_t* s, int n, FILE* f)
+{
+  int c = 0;
+  wchar_t* cs;
+
+  cs = s;
+  while (--n > 0 && (c = _getw(f)) != EOF) {
+    *cs++ = c;
+    if (c == L'\n')
+      break;
+  }
+  if (c == EOF && cs == s) {
+    return NULL;
+  }
+  *cs++ = L'\0';
+  return s;
+}
diff --git a/lib/crtdll/stdio/fputws.c b/lib/crtdll/stdio/fputws.c
new file mode 100644 (file)
index 0000000..399ac41
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+#include <msvcrt/string.h>
+
+//int fputws(const wchar_t* wsOutput, FILE* fileWrite)
+//int fputs(const char *s, FILE *f)
+
+int
+fputws(const wchar_t* s, FILE* f)
+{
+  int r = 0;
+  int c;
+  int unbuffered;
+  wchar_t localbuf[BUFSIZ];
+
+  unbuffered = f->_flag & _IONBF;
+  if (unbuffered)
+  {
+    f->_flag &= ~_IONBF;
+    f->_ptr = f->_base = localbuf;
+    f->_bufsiz = BUFSIZ;
+  }
+
+  while ((c = *s++))
+    r = putwc(c, f);
+
+  if (unbuffered)
+  {
+    fflush(f);
+    f->_flag |= _IONBF;
+    f->_base = NULL;
+    f->_bufsiz = 0;
+    f->_cnt = 0;
+  }
+  return(r);
+}
diff --git a/lib/crtdll/stdlib/alloca.c b/lib/crtdll/stdlib/alloca.c
new file mode 100644 (file)
index 0000000..cfbcc91
--- /dev/null
@@ -0,0 +1,68 @@
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+
+
+#undef alloca
+void *alloca(size_t s)
+{
+       register unsigned int as = s;
+
+// alloca(0) should not return the stack pointer
+       if ( s == 0 )
+               return NULL;
+
+       
+       if ( (s & 0xfffffffc)  != 0 )
+               as += 4;
+               
+       as &= 0xfffffffc;
+       
+       __asm__ __volatile__(
+       "mov %0, %%edx          \n"
+//     "popl %%ebp             \n"
+       "leave                  \n"
+       "popl  %%ecx            \n"
+        "subl  %%edx, %%esp    \n"
+        "movl  %%esp, %%eax    \n"
+        "addl  $20, %%eax        \n"//4 bytes + 16 bytes = arguments
+        "push  %%ecx           \n"
+        "ret                   \n"
+        :
+        :"g" ( as)
+        );
+        
+       
+        return NULL;
+}
+
+void *_alloca(size_t s)
+{
+       register unsigned int as = s;
+
+// alloca(0) should not return the stack pointer
+       if ( s == 0 )
+               return NULL;
+
+       
+       if ( (s & 0xfffffffc)  != 0 )
+               as += 4;
+               
+       as &= 0xfffffffc;
+       
+       __asm__ __volatile__(
+       "mov %0, %%edx          \n"
+//     "popl %%ebp             \n"
+       "leave                  \n"
+       "popl  %%ecx            \n"
+        "subl  %%edx, %%esp    \n"
+        "movl  %%esp, %%eax    \n"
+        "addl  $20, %%eax        \n"//4 bytes + 16 bytes = arguments
+        "push  %%ecx           \n"
+        "ret                   \n"
+        :
+        :"g" ( as)
+        );
+        
+       
+        return NULL;
+}
diff --git a/lib/crtdll/time/tz_vars.c b/lib/crtdll/time/tz_vars.c
new file mode 100644 (file)
index 0000000..3ccf177
--- /dev/null
@@ -0,0 +1,21 @@
+#include <msvcrt/string.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/stdlib.h>
+
+
+int _daylight_dll;
+int _timezone_dll;
+
+
+void _set_daylight_export(int value)
+{
+    _daylight_dll =  value;
+}
+
+void _set_timezone_export(int value)
+{
+    _timezone_dll =  value;
+}
+
+
+
diff --git a/lib/gdi32/main/.cvsignore b/lib/gdi32/main/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/gdi32/objects/.cvsignore b/lib/gdi32/objects/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/kernel32/MSG00409.bin b/lib/kernel32/MSG00409.bin
new file mode 100644 (file)
index 0000000..5ca7b78
Binary files /dev/null and b/lib/kernel32/MSG00409.bin differ
diff --git a/lib/kernel32/errcodes.rc b/lib/kernel32/errcodes.rc
new file mode 100644 (file)
index 0000000..482dc4f
--- /dev/null
@@ -0,0 +1,7 @@
+/* This file is generated with wmc version 1.0.0 (12-Jun-2000). Do not edit! */
+/* Source : kernel32.mc */
+/* Cmdline: wmc -H ../../include/reactos/errcodes.h -o errcodes.rc kernel32.mc */
+/* Date   : Tue Dec 10 02:07:21 2002 */
+
+LANGUAGE 0x9, 0x1
+1 MESSAGETABLE "MSG00409.bin"
diff --git a/lib/kernel32/errormsg.mak b/lib/kernel32/errormsg.mak
new file mode 100644 (file)
index 0000000..8981ebe
--- /dev/null
@@ -0,0 +1,18 @@
+# $Id$
+
+PATH_TO_TOP = ../..
+
+#TARGET_TYPE = dynlink
+
+TARGETNAME = kernel32
+
+errcodes.rc: $(TARGETNAME).mc
+       $(MC) \
+               -H $(PATH_TO_TOP)/include/reactos/errcodes.h \
+               -o errcodes.rc \
+               $(TARGETNAME).mc
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
diff --git a/lib/kernel32/k32.h b/lib/kernel32/k32.h
new file mode 100755 (executable)
index 0000000..018d32a
--- /dev/null
@@ -0,0 +1,26 @@
+#define NTOS_MODE_USER
+#include <ntos.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <limits.h>
+#include <wchar.h>
+#include <string.h>
+#include <assert.h>
+#include <ddk/ntddk.h>
+#include <ddk/ntddbeep.h>
+#include <ddk/ntddser.h>
+#include <windows.h>
+#include <kernel32/proc.h>
+#include <kernel32/thread.h>
+#include <kernel32/error.h>
+#include <ntdll/base.h>
+#include <ntdll/rtl.h>
+#include <ntdll/dbg.h>
+#include <ntdll/csr.h>
+#include <ntdll/ldr.h>
+#include <napi/i386/segment.h>
+#include <napi/teb.h>
+#include <napi/npipe.h>
+#include <ntos/minmax.h>
+#include <csrss/csrss.h>
+#include <reactos/buildno.h>
diff --git a/lib/kernel32/kernel32.mc b/lib/kernel32/kernel32.mc
new file mode 100644 (file)
index 0000000..68ea166
--- /dev/null
@@ -0,0 +1,5358 @@
+;
+; kernel32.mc MESSAGE resources for kernel32.dll
+;
+
+MessageIdTypedef=ULONG
+
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+               Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+               Warning=0x2:STATUS_SEVERITY_WARNING
+               Error=0x3:STATUS_SEVERITY_ERROR
+              )
+
+FacilityNames=(System=0x0:FACILITY_SYSTEM
+               Runtime=0x2:FACILITY_RUNTIME
+               Stubs=0x3:FACILITY_STUBS
+               Io=0x4:FACILITY_IO_ERROR_CODE
+              )
+
+LanguageNames=(English=0x409:MSG00409)
+
+;
+; message definitions
+;
+
+MessageId=0x00
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUCCESS
+Language=English
+ERROR_SUCCESS - The operation completed successfully.\r
+.
+
+MessageId=0x01
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FUNCTION
+Language=English
+ERROR_INVALID_FUNCTION - Incorrect function.\r
+.
+
+MessageId=0x02
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_NOT_FOUND
+Language=English
+ERROR_FILE_NOT_FOUND - The system cannot find the file specified.\r
+.
+
+MessageId=0x03
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PATH_NOT_FOUND
+Language=English
+ERROR_PATH_NOT_FOUND - The system cannot find the path specified.\r
+.
+
+MessageId=0x04
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_OPEN_FILES
+Language=English
+ERROR_TOO_MANY_OPEN_FILES - The system cannot open the file.\r
+.
+
+MessageId=0x05
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCESS_DENIED
+Language=English
+ERROR_ACCESS_DENIED - Access is denied.\r
+.
+
+MessageId=0x06
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HANDLE
+Language=English
+ERROR_INVALID_HANDLE - The handle is invalid.\r
+.
+
+MessageId=0x07
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ARENA_TRASHED
+Language=English
+ERROR_ARENA_TRASHED - The storage control blocks were destroyed.\r
+.
+
+MessageId=0x08
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_MEMORY
+Language=English
+ERROR_NOT_ENOUGH_MEMORY - Not enough storage is available to process this command.\r
+.
+
+MessageId=0x09
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_BLOCK
+Language=English
+ERROR_INVALID_BLOCK - The storage control block address is invalid.\r
+.
+
+MessageId=0x0A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_ENVIRONMENT
+Language=English
+ERROR_BAD_ENVIRONMENT - The environment is incorrect.\r
+.
+
+MessageId=0x0B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_FORMAT
+Language=English
+ERROR_BAD_FORMAT - An attempt was made to load a program with an incorrect format.\r
+.
+
+MessageId=0x0C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCESS
+Language=English
+ERROR_INVALID_ACCESS - The access code is invalid.\r
+.
+
+MessageId=0x0D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DATA
+Language=English
+ERROR_INVALID_DATA - The data is invalid.\r
+.
+
+MessageId=0x0E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUTOFMEMORY
+Language=English
+ERROR_OUTOFMEMORY - Not enough storage is available to complete this operation.\r
+.
+
+MessageId=0x0F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DRIVE
+Language=English
+ERROR_INVALID_DRIVE - The system cannot find the drive specified.\r
+.
+
+MessageId=0x10
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CURRENT_DIRECTORY
+Language=English
+ERROR_CURRENT_DIRECTORY - The directory cannot be removed.\r
+.
+
+MessageId=0x11
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SAME_DEVICE
+Language=English
+ERROR_NOT_SAME_DEVICE - The system cannot move the file to a different disk drive.\r
+.
+
+MessageId=0x12
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_FILES
+Language=English
+ERROR_NO_MORE_FILES - There are no more files.\r
+.
+
+MessageId=0x13
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRITE_PROTECT
+Language=English
+ERROR_WRITE_PROTECT - The media is write protected.\r
+.
+
+MessageId=0x14
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_UNIT
+Language=English
+ERROR_BAD_UNIT - The system cannot find the device specified.\r
+.
+
+MessageId=0x15
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_READY
+Language=English
+ERROR_NOT_READY - The device is not ready.\r
+.
+
+MessageId=0x16
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_COMMAND
+Language=English
+ERROR_BAD_COMMAND - The device does not recognize the command.\r
+.
+
+MessageId=0x17
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CRC
+Language=English
+ERROR_CRC - Data error (cyclic redundancy check).\r
+.
+
+MessageId=0x18
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_LENGTH
+Language=English
+ERROR_BAD_LENGTH - The program issued a command but the command length is incorrect.\r
+.
+
+MessageId=0x19
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEEK
+Language=English
+ERROR_SEEK - The drive cannot locate a specific area or track on the disk.\r
+.
+
+MessageId=0x1A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_DOS_DISK
+Language=English
+ERROR_NOT_DOS_DISK - The specified disk or diskette cannot be accessed.\r
+.
+
+MessageId=0x1B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SECTOR_NOT_FOUND
+Language=English
+ERROR_SECTOR_NOT_FOUND - The drive cannot find the sector requested.\r
+.
+
+MessageId=0x1C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUT_OF_PAPER
+Language=English
+ERROR_OUT_OF_PAPER - The printer is out of paper.\r
+.
+
+MessageId=0x1D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRITE_FAULT
+Language=English
+ERROR_WRITE_FAULT - The system cannot write to the specified device.\r
+.
+
+MessageId=0x1E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_READ_FAULT
+Language=English
+ERROR_READ_FAULT - The system cannot read from the specified device.\r
+.
+
+MessageId=0x1F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GEN_FAILURE
+Language=English
+ERROR_GEN_FAILURE - A device attached to the system is not functioning.\r
+.
+
+MessageId=0x20
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_VIOLATION
+Language=English
+ERROR_SHARING_VIOLATION - The process cannot access the file because it is being used by another process.\r
+.
+
+MessageId=0x21
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCK_VIOLATION
+Language=English
+ERROR_LOCK_VIOLATION - The process cannot access the file because another process has locked a portion of the file.\r
+.
+
+MessageId=0x22
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRONG_DISK
+Language=English
+ERROR_WRONG_DISK
+.
+
+MessageId=0x24
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_BUFFER_EXCEEDED
+Language=English
+ERROR_SHARING_BUFFER_EXCEEDED
+.
+
+MessageId=0x26
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HANDLE_EOF
+Language=English
+ERROR_HANDLE_EOF - Too many files opened for sharing.\r
+.
+
+MessageId=0x27
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HANDLE_DISK_FULL
+Language=English
+ERROR_HANDLE_DISK_FULL
+.
+
+MessageId=0x32
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SUPPORTED
+Language=English
+ERROR_NOT_SUPPORTED - Reached the end of the file.\r
+.
+
+MessageId=0x33
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REM_NOT_LIST
+Language=English
+ERROR_REM_NOT_LIST - The disk is full.\r
+.
+
+MessageId=0x34
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUP_NAME
+Language=English
+ERROR_DUP_NAME
+.
+
+MessageId=0x35
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NETPATH
+Language=English
+ERROR_BAD_NETPATH
+.
+
+MessageId=0x36
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_BUSY
+Language=English
+ERROR_NETWORK_BUSY
+.
+
+MessageId=0x37
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEV_NOT_EXIST
+Language=English
+ERROR_DEV_NOT_EXIST
+.
+
+MessageId=0x38
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_CMDS
+Language=English
+ERROR_TOO_MANY_CMDS
+.
+
+MessageId=0x39
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADAP_HDW_ERR
+Language=English
+ERROR_ADAP_HDW_ERR
+.
+
+MessageId=0x3A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NET_RESP
+Language=English
+ERROR_BAD_NET_RESP
+.
+
+MessageId=0x3B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNEXP_NET_ERR
+Language=English
+ERROR_UNEXP_NET_ERR
+.
+
+MessageId=0x3C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_REM_ADAP
+Language=English
+ERROR_BAD_REM_ADAP
+.
+
+MessageId=0x3D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTQ_FULL
+Language=English
+ERROR_PRINTQ_FULL
+.
+
+MessageId=0x3E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SPOOL_SPACE
+Language=English
+ERROR_NO_SPOOL_SPACE - The network request is not supported.\r
+.
+
+MessageId=0x3F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_CANCELLED
+Language=English
+ERROR_PRINT_CANCELLED - The remote computer is not available.\r
+.
+
+MessageId=0x40
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETNAME_DELETED
+Language=English
+ERROR_NETNAME_DELETED - A duplicate name exists on the network.\r
+.
+
+MessageId=0x41
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_ACCESS_DENIED
+Language=English
+ERROR_NETWORK_ACCESS_DENIED - The network path was not found.\r
+.
+
+MessageId=0x42
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DEV_TYPE
+Language=English
+ERROR_BAD_DEV_TYPE - The network is busy.\r
+.
+
+MessageId=0x43
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NET_NAME
+Language=English
+ERROR_BAD_NET_NAME - The specified network resource or device is no longer available.\r
+.
+
+MessageId=0x44
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_NAMES
+Language=English
+ERROR_TOO_MANY_NAMES - The network BIOS command limit has been reached.\r
+.
+
+MessageId=0x45
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SESS
+Language=English
+ERROR_TOO_MANY_SESS - A network adapter hardware error occurred.\r
+.
+
+MessageId=0x46
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_PAUSED
+Language=English
+ERROR_SHARING_PAUSED - The specified server cannot perform the requested operation.\r
+.
+
+MessageId=0x47
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REQ_NOT_ACCEP
+Language=English
+ERROR_REQ_NOT_ACCEP - An unexpected network error occurred.\r
+.
+
+MessageId=0x48
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REDIR_PAUSED
+Language=English
+ERROR_REDIR_PAUSED - The remote adapter is not compatible.\r
+.
+
+MessageId=0x50
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_EXISTS
+Language=English
+ERROR_FILE_EXISTS - The printer queue is full.\r
+.
+
+MessageId=0x52
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_MAKE
+Language=English
+ERROR_CANNOT_MAKE - Space to store the file waiting to be printed is not available on the server.\r
+.
+
+MessageId=0x53
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FAIL_I24
+Language=English
+ERROR_FAIL_I24 - Your file waiting to be printed was deleted.\r
+.
+
+MessageId=0x54
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUT_OF_STRUCTURES
+Language=English
+ERROR_OUT_OF_STRUCTURES - The specified network name is no longer available.\r
+.
+
+MessageId=0x55
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_ASSIGNED
+Language=English
+ERROR_ALREADY_ASSIGNED - Network access is denied.\r
+.
+
+MessageId=0x56
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PASSWORD
+Language=English
+ERROR_INVALID_PASSWORD - The network resource type is not correct.\r
+.
+
+MessageId=0x57
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PARAMETER
+Language=English
+ERROR_INVALID_PARAMETER - The network name cannot be found.\r
+.
+
+MessageId=0x58
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NET_WRITE_FAULT
+Language=English
+ERROR_NET_WRITE_FAULT - The name limit for the local computer network adapter card was exceeded.\r
+.
+
+MessageId=0x59
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_PROC_SLOTS
+Language=English
+ERROR_NO_PROC_SLOTS - The network BIOS session limit was exceeded.\r
+.
+
+MessageId=0x64
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SEMAPHORES
+Language=English
+ERROR_TOO_MANY_SEMAPHORES - The remote server has been paused or is in the process of being started.\r
+.
+
+MessageId=0x65
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXCL_SEM_ALREADY_OWNED
+Language=English
+ERROR_EXCL_SEM_ALREADY_OWNED - No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.\r
+.
+
+MessageId=0x66
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_IS_SET
+Language=English
+ERROR_SEM_IS_SET - The specified printer or disk device has been paused.\r
+.
+
+MessageId=0x67
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SEM_REQUESTS
+Language=English
+ERROR_TOO_MANY_SEM_REQUESTS
+.
+
+MessageId=0x68
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_AT_INTERRUPT_TIME
+Language=English
+ERROR_INVALID_AT_INTERRUPT_TIME
+.
+
+MessageId=0x69
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_OWNER_DIED
+Language=English
+ERROR_SEM_OWNER_DIED
+.
+
+MessageId=0x6A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_USER_LIMIT
+Language=English
+ERROR_SEM_USER_LIMIT
+.
+
+MessageId=0x6B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_CHANGE
+Language=English
+ERROR_DISK_CHANGE
+.
+
+MessageId=0x6C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DRIVE_LOCKED
+Language=English
+ERROR_DRIVE_LOCKED
+.
+
+MessageId=0x6D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BROKEN_PIPE
+Language=English
+ERROR_BROKEN_PIPE
+.
+
+MessageId=0x6E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPEN_FAILED
+Language=English
+ERROR_OPEN_FAILED - The file exists.\r
+.
+
+MessageId=0x6F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUFFER_OVERFLOW
+Language=English
+ERROR_BUFFER_OVERFLOW
+.
+
+MessageId=0x70
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_FULL
+Language=English
+ERROR_DISK_FULL - The directory or file cannot be created.\r
+.
+
+MessageId=0x71
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_SEARCH_HANDLES
+Language=English
+ERROR_NO_MORE_SEARCH_HANDLES - Fail on INT 24.\r
+.
+
+MessageId=0x72
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_TARGET_HANDLE
+Language=English
+ERROR_INVALID_TARGET_HANDLE - Storage to process this request is not available.\r
+.
+
+MessageId=0x75
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_CATEGORY
+Language=English
+ERROR_INVALID_CATEGORY - The local device name is already in use.\r
+.
+
+MessageId=0x76
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_VERIFY_SWITCH
+Language=English
+ERROR_INVALID_VERIFY_SWITCH - The specified network password is not correct.\r
+.
+
+MessageId=0x77
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DRIVER_LEVEL
+Language=English
+ERROR_BAD_DRIVER_LEVEL - The parameter is incorrect.\r
+.
+
+MessageId=0x78
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CALL_NOT_IMPLEMENTED
+Language=English
+ERROR_CALL_NOT_IMPLEMENTED - A write fault occurred on the network.\r
+.
+
+MessageId=0x79
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_TIMEOUT
+Language=English
+ERROR_SEM_TIMEOUT - The system cannot start another process at this time.\r
+.
+
+MessageId=0x7A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INSUFFICIENT_BUFFER
+Language=English
+ERROR_INSUFFICIENT_BUFFER
+.
+
+MessageId=0x7B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_NAME
+Language=English
+ERROR_INVALID_NAME
+.
+
+MessageId=0x7C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LEVEL
+Language=English
+ERROR_INVALID_LEVEL
+.
+
+MessageId=0x7D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_VOLUME_LABEL
+Language=English
+ERROR_NO_VOLUME_LABEL
+.
+
+MessageId=0x7E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MOD_NOT_FOUND
+Language=English
+ERROR_MOD_NOT_FOUND
+.
+
+MessageId=0x7F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROC_NOT_FOUND
+Language=English
+ERROR_PROC_NOT_FOUND
+.
+
+MessageId=0x80
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WAIT_NO_CHILDREN
+Language=English
+ERROR_WAIT_NO_CHILDREN
+.
+
+MessageId=0x81
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_NOT_COMPLETE
+Language=English
+ERROR_CHILD_NOT_COMPLETE
+.
+
+MessageId=0x82
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIRECT_ACCESS_HANDLE
+Language=English
+ERROR_DIRECT_ACCESS_HANDLE
+.
+
+MessageId=0x83
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NEGATIVE_SEEK
+Language=English
+ERROR_NEGATIVE_SEEK
+.
+
+MessageId=0x84
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEEK_ON_DEVICE
+Language=English
+ERROR_SEEK_ON_DEVICE - Cannot create another system semaphore.\r
+.
+
+MessageId=0x85
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOIN_TARGET
+Language=English
+ERROR_IS_JOIN_TARGET - The exclusive semaphore is owned by another process.\r
+.
+
+MessageId=0x86
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOINED
+Language=English
+ERROR_IS_JOINED - The semaphore is set and cannot be closed.\r
+.
+
+MessageId=0x87
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBSTED
+Language=English
+ERROR_IS_SUBSTED - The semaphore cannot be set again.\r
+.
+
+MessageId=0x88
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_JOINED
+Language=English
+ERROR_NOT_JOINED - Cannot request exclusive semaphores at interrupt time.\r
+.
+
+MessageId=0x89
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SUBSTED
+Language=English
+ERROR_NOT_SUBSTED - The previous ownership of this semaphore has ended.\r
+.
+
+MessageId=0x8A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOIN_TO_JOIN
+Language=English
+ERROR_JOIN_TO_JOIN
+.
+
+MessageId=0x8B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUBST_TO_SUBST
+Language=English
+ERROR_SUBST_TO_SUBST - The program stopped because an alternate diskette was not inserted.\r
+.
+
+MessageId=0x8C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOIN_TO_SUBST
+Language=English
+ERROR_JOIN_TO_SUBST - The disk is in use or locked by\r
+another process.\r
+.
+
+MessageId=0x8D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUBST_TO_JOIN
+Language=English
+ERROR_SUBST_TO_JOIN - The pipe has been ended.\r
+.
+
+MessageId=0x8E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUSY_DRIVE
+Language=English
+ERROR_BUSY_DRIVE - The system cannot open the\r
+device or file specified.\r
+.
+
+MessageId=0x8F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SAME_DRIVE
+Language=English
+ERROR_SAME_DRIVE - The file name is too long.\r
+.
+
+MessageId=0x90
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIR_NOT_ROOT
+Language=English
+ERROR_DIR_NOT_ROOT - There is not enough space on the disk.\r
+.
+
+MessageId=0x91
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIR_NOT_EMPTY
+Language=English
+ERROR_DIR_NOT_EMPTY - No more internal file identifiers available.\r
+.
+
+MessageId=0x92
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBST_PATH
+Language=English
+ERROR_IS_SUBST_PATH - The target internal file identifier is incorrect.\r
+.
+
+MessageId=0x93
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOIN_PATH
+Language=English
+ERROR_IS_JOIN_PATH
+.
+
+MessageId=0x94
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PATH_BUSY
+Language=English
+ERROR_PATH_BUSY
+.
+
+MessageId=0x95
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBST_TARGET
+Language=English
+ERROR_IS_SUBST_TARGET - The IOCTL call made by the application program is not correct.\r
+.
+
+MessageId=0x96
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SYSTEM_TRACE
+Language=English
+ERROR_SYSTEM_TRACE - The verify-on-write switch parameter value is not correct.\r
+.
+
+MessageId=0x97
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EVENT_COUNT
+Language=English
+ERROR_INVALID_EVENT_COUNT - The system does not support the command requested.\r
+.
+
+MessageId=0x98
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_MUXWAITERS
+Language=English
+ERROR_TOO_MANY_MUXWAITERS - This function is not supported on this system.\r
+.
+
+MessageId=0x99
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LIST_FORMAT
+Language=English
+ERROR_INVALID_LIST_FORMAT - The semaphore timeout period has expired.\r
+.
+
+MessageId=0x9A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LABEL_TOO_LONG
+Language=English
+ERROR_LABEL_TOO_LONG - The data area passed to a system call is too small.\r
+.
+
+MessageId=0x9B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_TCBS
+Language=English
+ERROR_TOO_MANY_TCBS - The filename, directory name, or volume label syntax is incorrect.\r
+.
+
+MessageId=0x9C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SIGNAL_REFUSED
+Language=English
+ERROR_SIGNAL_REFUSED - The system call level is not correct.\r
+.
+
+MessageId=0x9D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISCARDED
+Language=English
+ERROR_DISCARDED - The disk has no volume label.\r
+.
+
+MessageId=0x9E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOCKED
+Language=English
+ERROR_NOT_LOCKED - The specified module could not be found.\r
+.
+
+MessageId=0x9F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_THREADID_ADDR
+Language=English
+ERROR_BAD_THREADID_ADDR - The specified procedure could not be found.\r
+.
+
+MessageId=0xA0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_ARGUMENTS
+Language=English
+ERROR_BAD_ARGUMENTS - There are no child processes to wait for.\r
+.
+
+MessageId=0xA1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PATHNAME
+Language=English
+ERROR_BAD_PATHNAME
+.
+
+MessageId=0xA2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SIGNAL_PENDING
+Language=English
+ERROR_SIGNAL_PENDING - Attempt to use a file handle to an open disk partition for an operation other than raw disk I/O.\r
+.
+
+MessageId=0xA4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MAX_THRDS_REACHED
+Language=English
+ERROR_MAX_THRDS_REACHED - An attempt was made to move the file pointer before the beginning of the file.\r
+.
+
+MessageId=0xA7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCK_FAILED
+Language=English
+ERROR_LOCK_FAILED - The file pointer cannot be set on the specified device or file.\r
+.
+
+MessageId=0xAA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUSY
+Language=English
+ERROR_BUSY - A JOIN or SUBST command cannot be used for a drive that contains previously joined drives.\r
+.
+
+MessageId=0xAD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANCEL_VIOLATION
+Language=English
+ERROR_CANCEL_VIOLATION - An attempt was made to use a JOIN or SUBST command on a drive that has already been joined.\r
+.
+
+MessageId=0xAE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
+Language=English
+ERROR_ATOMIC_LOCKS_NOT_SUPPORTED - An attempt was made to use a JOIN or SUBST command on a drive that has already been substituted.\r
+.
+
+MessageId=0xB4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEGMENT_NUMBER
+Language=English
+ERROR_INVALID_SEGMENT_NUMBER - The system tried to delete the JOIN of a drive that is not joined.\r
+.
+
+MessageId=0xB6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ORDINAL
+Language=English
+ERROR_INVALID_ORDINAL - The system tried to delete the substitution of a drive that is not substituted.\r
+.
+
+MessageId=0xB7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_EXISTS
+Language=English
+ERROR_ALREADY_EXISTS - The system tried to join a drive to a directory on a joined drive.\r
+.
+
+MessageId=0xBA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FLAG_NUMBER
+Language=English
+ERROR_INVALID_FLAG_NUMBER - The system tried to substitute a drive to a directory on a substituted drive.\r
+.
+
+MessageId=0xBB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_NOT_FOUND
+Language=English
+ERROR_SEM_NOT_FOUND - The system tried to join a drive to a directory on a substituted drive.\r
+.
+
+MessageId=0xBC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_STARTING_CODESEG
+Language=English
+ERROR_INVALID_STARTING_CODESEG - The system tried to SUBST a drive to a directory on a joined drive.\r
+.
+
+MessageId=0xBD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_STACKSEG
+Language=English
+ERROR_INVALID_STACKSEG - The system cannot perform a JOIN or SUBST at this time.\r
+.
+
+MessageId=0xBE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MODULETYPE
+Language=English
+ERROR_INVALID_MODULETYPE - The system cannot join or substitute a drive to or for a directory on the same drive.\r
+.
+
+MessageId=0xBF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EXE_SIGNATURE
+Language=English
+ERROR_INVALID_EXE_SIGNATURE - The directory is not a subdirectory of the root directory.\r
+.
+
+MessageId=0xC0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXE_MARKED_INVALID
+Language=English
+ERROR_EXE_MARKED_INVALID - The directory is not empty.\r
+.
+
+MessageId=0xC1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_EXE_FORMAT
+Language=English
+ERROR_BAD_EXE_FORMAT - The path specified is being used in a substitute.\r
+.
+
+MessageId=0xC2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ITERATED_DATA_EXCEEDS_64k
+Language=English
+ERROR_ITERATED_DATA_EXCEEDS_64k - Not enough resources are available to process this command.\r
+.
+
+MessageId=0xC3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MINALLOCSIZE
+Language=English
+ERROR_INVALID_MINALLOCSIZE - The path specified cannot be used at this time.\r
+.
+
+MessageId=0xC4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DYNLINK_FROM_INVALID_RING
+Language=English
+ERROR_DYNLINK_FROM_INVALID_RING - An attempt was made to join or substitute a drive for which a directory on the drive is the target of a previous substitute.\r
+.
+
+MessageId=0xC5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IOPL_NOT_ENABLED
+Language=English
+ERROR_IOPL_NOT_ENABLED - System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed.\r
+.
+
+MessageId=0xC6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEGDPL
+Language=English
+ERROR_INVALID_SEGDPL - The number of specified semaphore events for DosMuxSemWait is not correct.\r
+.
+
+MessageId=0xC7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_AUTODATASEG_EXCEEDS_64k
+Language=English
+ERROR_AUTODATASEG_EXCEEDS_64k - DosMuxSemWait did not execute; too many semaphores are already set.\r
+.
+
+MessageId=0xC8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RING2SEG_MUST_BE_MOVABLE
+Language=English
+ERROR_RING2SEG_MUST_BE_MOVABLE - The DosMuxSemWait list is not correct.\r
+.
+
+MessageId=0xC9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RELOC_CHAIN_XEEDS_SEGLIM
+Language=English
+ERROR_RELOC_CHAIN_XEEDS_SEGLIM - The volume label you entered exceeds the label character\r
+limit of the target file system.\r
+.
+
+MessageId=0xCA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INFLOOP_IN_RELOC_CHAIN
+Language=English
+ERROR_INFLOOP_IN_RELOC_CHAIN - Cannot create another thread.\r
+.
+
+MessageId=0xCB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ENVVAR_NOT_FOUND
+Language=English
+ERROR_ENVVAR_NOT_FOUND - The recipient process has refused the signal.\r
+.
+
+MessageId=0xCD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SIGNAL_SENT
+Language=English
+ERROR_NO_SIGNAL_SENT - The segment is already discarded and cannot be locked.\r
+.
+
+MessageId=0xCE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILENAME_EXCED_RANGE
+Language=English
+ERROR_FILENAME_EXCED_RANGE - The segment is already unlocked.\r
+.
+
+MessageId=0xCF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RING2_STACK_IN_USE
+Language=English
+ERROR_RING2_STACK_IN_USE - The address for the thread ID is not correct.\r
+.
+
+MessageId=0xD0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_META_EXPANSION_TOO_LONG
+Language=English
+ERROR_META_EXPANSION_TOO_LONG - The argument string passed to DosExecPgm is not correct.\r
+.
+
+MessageId=0xD1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SIGNAL_NUMBER
+Language=English
+ERROR_INVALID_SIGNAL_NUMBER - The specified path is invalid.\r
+.
+
+MessageId=0xD2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_THREAD_1_INACTIVE
+Language=English
+ERROR_THREAD_1_INACTIVE - A signal is already pending.\r
+.
+
+MessageId=0xD4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCKED
+Language=English
+ERROR_LOCKED
+.
+
+MessageId=0xD6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_MODULES
+Language=English
+ERROR_TOO_MANY_MODULES - No more threads can be created in the system.\r
+.
+
+MessageId=0xD7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NESTING_NOT_ALLOWED
+Language=English
+ERROR_NESTING_NOT_ALLOWED
+.
+
+MessageId=0xE6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PIPE
+Language=English
+ERROR_BAD_PIPE
+.
+
+MessageId=0xE7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_BUSY
+Language=English
+ERROR_PIPE_BUSY - Unable to lock a region of a file.\r
+.
+
+MessageId=0xE8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_DATA
+Language=English
+ERROR_NO_DATA
+.
+
+MessageId=0xE9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_NOT_CONNECTED
+Language=English
+ERROR_PIPE_NOT_CONNECTED
+.
+
+MessageId=0xEA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MORE_DATA
+Language=English
+ERROR_MORE_DATA - The requested resource is in use.\r
+.
+
+MessageId=0xF0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_VC_DISCONNECTED
+Language=English
+ERROR_VC_DISCONNECTED
+.
+
+MessageId=0xFE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EA_NAME
+Language=English
+ERROR_INVALID_EA_NAME
+.
+
+MessageId=0xFF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_LIST_INCONSISTENT
+Language=English
+ERROR_EA_LIST_INCONSISTENT - A lock request was not outstanding for the supplied cancel region.\r
+.
+
+MessageId=0x103
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_ITEMS
+Language=English
+ERROR_NO_MORE_ITEMS - The file system does not support atomic changes to the lock type.\r
+.
+
+MessageId=0x10A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_COPY
+Language=English
+ERROR_CANNOT_COPY
+.
+
+MessageId=0x10B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIRECTORY
+Language=English
+ERROR_DIRECTORY
+.
+
+MessageId=0x113
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EAS_DIDNT_FIT
+Language=English
+ERROR_EAS_DIDNT_FIT
+.
+
+MessageId=0x114
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_FILE_CORRUPT
+Language=English
+ERROR_EA_FILE_CORRUPT
+.
+
+MessageId=0x115
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_TABLE_FULL
+Language=English
+ERROR_EA_TABLE_FULL
+.
+
+MessageId=0x116
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EA_HANDLE
+Language=English
+ERROR_INVALID_EA_HANDLE - The system detected a segment number that was not correct.\r
+.
+
+MessageId=0x11A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EAS_NOT_SUPPORTED
+Language=English
+ERROR_EAS_NOT_SUPPORTED
+.
+
+MessageId=0x120
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_OWNER
+Language=English
+ERROR_NOT_OWNER
+.
+
+MessageId=0x12A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_POSTS
+Language=English
+ERROR_TOO_MANY_POSTS - Cannot create a file when that file already exists.\r
+.
+
+MessageId=0x12B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PARTIAL_COPY
+Language=English
+ERROR_PARTIAL_COPY
+.
+
+MessageId=0x13D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MR_MID_NOT_FOUND
+Language=English
+ERROR_MR_MID_NOT_FOUND
+.
+
+MessageId=0x1E7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ADDRESS
+Language=English
+ERROR_INVALID_ADDRESS - The flag passed is not correct.\r
+.
+
+MessageId=0x216
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ARITHMETIC_OVERFLOW
+Language=English
+ERROR_ARITHMETIC_OVERFLOW - The specified system semaphore name was not found.\r
+.
+
+MessageId=0x217
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_CONNECTED
+Language=English
+ERROR_PIPE_CONNECTED
+.
+
+MessageId=0x218
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_LISTENING
+Language=English
+ERROR_PIPE_LISTENING
+.
+
+MessageId=0x3E2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_ACCESS_DENIED
+Language=English
+ERROR_EA_ACCESS_DENIED
+.
+
+MessageId=0x3E3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPERATION_ABORTED
+Language=English
+ERROR_OPERATION_ABORTED
+.
+
+MessageId=0x3E4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_INCOMPLETE
+Language=English
+ERROR_IO_INCOMPLETE
+.
+
+MessageId=0x3E5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_PENDING
+Language=English
+ERROR_IO_PENDING
+.
+
+MessageId=0x3E6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOACCESS
+Language=English
+ERROR_NOACCESS
+.
+
+MessageId=0x3E7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SWAPERROR
+Language=English
+ERROR_SWAPERROR
+.
+
+MessageId=0x3E9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_STACK_OVERFLOW
+Language=English
+ERROR_STACK_OVERFLOW - The operating system cannot run this application program.\r
+.
+
+MessageId=0x3EA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGE
+Language=English
+ERROR_INVALID_MESSAGE - The operating system is not presently configured to run this application.\r
+.
+
+MessageId=0x3EB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CAN_NOT_COMPLETE
+Language=English
+ERROR_CAN_NOT_COMPLETE
+.
+
+MessageId=0x3EC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FLAGS
+Language=English
+ERROR_INVALID_FLAGS - The operating system cannot run this application program.\r
+.
+
+MessageId=0x3ED
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNRECOGNIZED_VOLUME
+Language=English
+ERROR_UNRECOGNIZED_VOLUME - The code segment cannot be greater than or equal to 64K.\r
+.
+
+MessageId=0x3EE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_INVALID
+Language=English
+ERROR_FILE_INVALID
+.
+
+MessageId=0x3EF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FULLSCREEN_MODE
+Language=English
+ERROR_FULLSCREEN_MODE
+.
+
+MessageId=0x3F0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TOKEN
+Language=English
+ERROR_NO_TOKEN - The system could not find the environment\r
+option that was entered.\r
+.
+
+MessageId=0x3F1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BADDB
+Language=English
+ERROR_BADDB
+.
+
+MessageId=0x3F2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BADKEY
+Language=English
+ERROR_BADKEY - No process in the command subtree has a\r
+signal handler.\r
+.
+
+MessageId=0x3F3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTOPEN
+Language=English
+ERROR_CANTOPEN - The filename or extension is too long.\r
+.
+
+MessageId=0x3F4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTREAD
+Language=English
+ERROR_CANTREAD - The ring 2 stack is in use.\r
+.
+
+MessageId=0x3F5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTWRITE
+Language=English
+ERROR_CANTWRITE - The global filename characters, * or ?, are entered incorrectly or too many global filename characters are specified.\r
+.
+
+MessageId=0x3F6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_RECOVERED
+Language=English
+ERROR_REGISTRY_RECOVERED - The signal being posted is not correct.\r
+.
+
+MessageId=0x3F7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_CORRUPT
+Language=English
+ERROR_REGISTRY_CORRUPT - The signal handler cannot be set.\r
+.
+
+MessageId=0x3F8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_IO_FAILED
+Language=English
+ERROR_REGISTRY_IO_FAILED
+.
+
+MessageId=0x3F9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_REGISTRY_FILE
+Language=English
+ERROR_NOT_REGISTRY_FILE - The segment is locked and cannot be reallocated.\r
+.
+
+MessageId=0x3FA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_KEY_DELETED
+Language=English
+ERROR_KEY_DELETED
+.
+
+MessageId=0x3FB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_LOG_SPACE
+Language=English
+ERROR_NO_LOG_SPACE - Too many dynamic-link modules are attached to this program or dynamic-link module.\r
+.
+
+MessageId=0x3FC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_KEY_HAS_CHILDREN
+Language=English
+ERROR_KEY_HAS_CHILDREN - Cannot nest calls to LoadModule.\r
+.
+
+MessageId=0x3FD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_MUST_BE_VOLATILE
+Language=English
+ERROR_CHILD_MUST_BE_VOLATILE
+.
+
+MessageId=0x3FE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOTIFY_ENUM_DIR
+Language=English
+ERROR_NOTIFY_ENUM_DIR
+.
+
+MessageId=0x41B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEPENDENT_SERVICES_RUNNING
+Language=English
+ERROR_DEPENDENT_SERVICES_RUNNING
+.
+
+MessageId=0x41C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_CONTROL
+Language=English
+ERROR_INVALID_SERVICE_CONTROL
+.
+
+MessageId=0x41D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_REQUEST_TIMEOUT
+Language=English
+ERROR_SERVICE_REQUEST_TIMEOUT
+.
+
+MessageId=0x41E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NO_THREAD
+Language=English
+ERROR_SERVICE_NO_THREAD
+.
+
+MessageId=0x41F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DATABASE_LOCKED
+Language=English
+ERROR_SERVICE_DATABASE_LOCKED
+.
+
+MessageId=0x420
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_ALREADY_RUNNING
+Language=English
+ERROR_SERVICE_ALREADY_RUNNING
+.
+
+MessageId=0x421
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_ACCOUNT
+Language=English
+ERROR_INVALID_SERVICE_ACCOUNT
+.
+
+MessageId=0x422
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DISABLED
+Language=English
+ERROR_SERVICE_DISABLED
+.
+
+MessageId=0x423
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CIRCULAR_DEPENDENCY
+Language=English
+ERROR_CIRCULAR_DEPENDENCY
+.
+
+MessageId=0x424
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DOES_NOT_EXIST
+Language=English
+ERROR_SERVICE_DOES_NOT_EXIST
+.
+
+MessageId=0x425
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_CANNOT_ACCEPT_CTRL
+Language=English
+ERROR_SERVICE_CANNOT_ACCEPT_CTRL
+.
+
+MessageId=0x426
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NOT_ACTIVE
+Language=English
+ERROR_SERVICE_NOT_ACTIVE
+.
+
+MessageId=0x427
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
+Language=English
+ERROR_FAILED_SERVICE_CONTROLLER_CONNECT - The pipe state is invalid.\r
+.
+
+MessageId=0x428
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXCEPTION_IN_SERVICE
+Language=English
+ERROR_EXCEPTION_IN_SERVICE - All pipe instances are busy.\r
+.
+
+MessageId=0x429
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DATABASE_DOES_NOT_EXIST
+Language=English
+ERROR_DATABASE_DOES_NOT_EXIST - The pipe is being closed.\r
+.
+
+MessageId=0x42A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_SPECIFIC_ERROR
+Language=English
+ERROR_SERVICE_SPECIFIC_ERROR - No process is on the other end of the pipe.\r
+.
+
+MessageId=0x42B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROCESS_ABORTED
+Language=English
+ERROR_PROCESS_ABORTED - More data is available.\r
+.
+
+MessageId=0x42C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DEPENDENCY_FAIL
+Language=English
+ERROR_SERVICE_DEPENDENCY_FAIL
+.
+
+MessageId=0x42D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_LOGON_FAILED
+Language=English
+ERROR_SERVICE_LOGON_FAILED
+.
+
+MessageId=0x42E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_START_HANG
+Language=English
+ERROR_SERVICE_START_HANG
+.
+
+MessageId=0x42F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_LOCK
+Language=English
+ERROR_INVALID_SERVICE_LOCK
+.
+
+MessageId=0x430
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_MARKED_FOR_DELETE
+Language=English
+ERROR_SERVICE_MARKED_FOR_DELETE
+.
+
+MessageId=0x431
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_EXISTS
+Language=English
+ERROR_SERVICE_EXISTS - The session was canceled.\r
+.
+
+MessageId=0x432
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_RUNNING_LKG
+Language=English
+ERROR_ALREADY_RUNNING_LKG
+.
+
+MessageId=0x433
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DEPENDENCY_DELETED
+Language=English
+ERROR_SERVICE_DEPENDENCY_DELETED
+.
+
+MessageId=0x434
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BOOT_ALREADY_ACCEPTED
+Language=English
+ERROR_BOOT_ALREADY_ACCEPTED
+.
+
+MessageId=0x435
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NEVER_STARTED
+Language=English
+ERROR_SERVICE_NEVER_STARTED
+.
+
+MessageId=0x436
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUPLICATE_SERVICE_NAME
+Language=English
+ERROR_DUPLICATE_SERVICE_NAME
+.
+
+MessageId=0x44C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_END_OF_MEDIA
+Language=English
+ERROR_END_OF_MEDIA
+.
+
+MessageId=0x44D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILEMARK_DETECTED
+Language=English
+ERROR_FILEMARK_DETECTED
+.
+
+MessageId=0x44E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BEGINNING_OF_MEDIA
+Language=English
+ERROR_BEGINNING_OF_MEDIA
+.
+
+MessageId=0x44F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SETMARK_DETECTED
+Language=English
+ERROR_SETMARK_DETECTED
+.
+
+MessageId=0x450
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_DATA_DETECTED
+Language=English
+ERROR_NO_DATA_DETECTED
+.
+
+MessageId=0x451
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PARTITION_FAILURE
+Language=English
+ERROR_PARTITION_FAILURE
+.
+
+MessageId=0x452
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_BLOCK_LENGTH
+Language=English
+ERROR_INVALID_BLOCK_LENGTH
+.
+
+MessageId=0x453
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_NOT_PARTITIONED
+Language=English
+ERROR_DEVICE_NOT_PARTITIONED
+.
+
+MessageId=0x454
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNABLE_TO_LOCK_MEDIA
+Language=English
+ERROR_UNABLE_TO_LOCK_MEDIA - The specified extended attribute name was invalid.\r
+.
+
+MessageId=0x455
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNABLE_TO_UNLOAD_MEDIA
+Language=English
+ERROR_UNABLE_TO_UNLOAD_MEDIA - The extended attributes are inconsistent.\r
+.
+
+MessageId=0x456
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEDIA_CHANGED
+Language=English
+ERROR_MEDIA_CHANGED
+.
+
+MessageId=0x457
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUS_RESET
+Language=English
+ERROR_BUS_RESET
+.
+
+MessageId=0x458
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MEDIA_IN_DRIVE
+Language=English
+ERROR_NO_MEDIA_IN_DRIVE - The wait operation timed out.\r
+.
+
+MessageId=0x459
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_UNICODE_TRANSLATION
+Language=English
+ERROR_NO_UNICODE_TRANSLATION - No more data is available.\r
+.
+
+MessageId=0x45A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DLL_INIT_FAILED
+Language=English
+ERROR_DLL_INIT_FAILED
+.
+
+MessageId=0x45B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHUTDOWN_IN_PROGRESS
+Language=English
+ERROR_SHUTDOWN_IN_PROGRESS
+.
+
+MessageId=0x45C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SHUTDOWN_IN_PROGRESS
+Language=English
+ERROR_NO_SHUTDOWN_IN_PROGRESS
+.
+
+MessageId=0x45D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_DEVICE
+Language=English
+ERROR_IO_DEVICE
+.
+
+MessageId=0x45E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERIAL_NO_DEVICE
+Language=English
+ERROR_SERIAL_NO_DEVICE
+.
+
+MessageId=0x45F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IRQ_BUSY
+Language=English
+ERROR_IRQ_BUSY
+.
+
+MessageId=0x460
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MORE_WRITES
+Language=English
+ERROR_MORE_WRITES - The copy functions cannot be used.\r
+.
+
+MessageId=0x461
+Severity=Success
+Facility=System
+SymbolicName=ERROR_COUNTER_TIMEOUT
+Language=English
+ERROR_COUNTER_TIMEOUT - The directory name is invalid.\r
+.
+
+MessageId=0x462
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_ID_MARK_NOT_FOUND
+Language=English
+ERROR_FLOPPY_ID_MARK_NOT_FOUND
+.
+
+MessageId=0x463
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_WRONG_CYLINDER
+Language=English
+ERROR_FLOPPY_WRONG_CYLINDER
+.
+
+MessageId=0x464
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_UNKNOWN_ERROR
+Language=English
+ERROR_FLOPPY_UNKNOWN_ERROR
+.
+
+MessageId=0x465
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_BAD_REGISTERS
+Language=English
+ERROR_FLOPPY_BAD_REGISTERS
+.
+
+MessageId=0x466
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_RECALIBRATE_FAILED
+Language=English
+ERROR_DISK_RECALIBRATE_FAILED
+.
+
+MessageId=0x467
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_OPERATION_FAILED
+Language=English
+ERROR_DISK_OPERATION_FAILED
+.
+
+MessageId=0x468
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_RESET_FAILED
+Language=English
+ERROR_DISK_RESET_FAILED
+.
+
+MessageId=0x469
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EOM_OVERFLOW
+Language=English
+ERROR_EOM_OVERFLOW - The extended attributes did not fit in the buffer.\r
+.
+
+MessageId=0x46A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_SERVER_MEMORY
+Language=English
+ERROR_NOT_ENOUGH_SERVER_MEMORY - The extended attribute file on the mounted file system is corrupt.\r
+.
+
+MessageId=0x46B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_POSSIBLE_DEADLOCK
+Language=English
+ERROR_POSSIBLE_DEADLOCK - The extended attribute table file is full.\r
+.
+
+MessageId=0x46C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MAPPED_ALIGNMENT
+Language=English
+ERROR_MAPPED_ALIGNMENT - The specified extended attribute handle is invalid.\r
+.
+
+MessageId=0x474
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SET_POWER_STATE_VETOED
+Language=English
+ERROR_SET_POWER_STATE_VETOED
+.
+
+MessageId=0x475
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SET_POWER_STATE_FAILED
+Language=English
+ERROR_SET_POWER_STATE_FAILED
+.
+
+MessageId=0x476
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_LINKS
+Language=English
+ERROR_TOO_MANY_LINKS
+.
+
+MessageId=0x47E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OLD_WIN_VERSION
+Language=English
+ERROR_OLD_WIN_VERSION - The mounted file system does not support extended attributes.\r
+.
+
+MessageId=0x47F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_APP_WRONG_OS
+Language=English
+ERROR_APP_WRONG_OS
+.
+
+MessageId=0x480
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SINGLE_INSTANCE_APP
+Language=English
+ERROR_SINGLE_INSTANCE_APP
+.
+
+MessageId=0x481
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RMODE_APP
+Language=English
+ERROR_RMODE_APP
+.
+
+MessageId=0x482
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DLL
+Language=English
+ERROR_INVALID_DLL
+.
+
+MessageId=0x483
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_ASSOCIATION
+Language=English
+ERROR_NO_ASSOCIATION
+.
+
+MessageId=0x484
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DDE_FAIL
+Language=English
+ERROR_DDE_FAIL - Attempt to release mutex not owned by caller.\r
+.
+
+MessageId=0x485
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DLL_NOT_FOUND
+Language=English
+ERROR_DLL_NOT_FOUND
+.
+
+MessageId=0x4B0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DEVICE
+Language=English
+ERROR_BAD_DEVICE
+.
+
+MessageId=0x4B1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_UNAVAIL
+Language=English
+ERROR_CONNECTION_UNAVAIL
+.
+
+MessageId=0x4B2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_ALREADY_REMEMBERED
+Language=English
+ERROR_DEVICE_ALREADY_REMEMBERED
+.
+
+MessageId=0x4B3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_NET_OR_BAD_PATH
+Language=English
+ERROR_NO_NET_OR_BAD_PATH
+.
+
+MessageId=0x4B4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PROVIDER
+Language=English
+ERROR_BAD_PROVIDER
+.
+
+MessageId=0x4B5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_OPEN_PROFILE
+Language=English
+ERROR_CANNOT_OPEN_PROFILE
+.
+
+MessageId=0x4B6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PROFILE
+Language=English
+ERROR_BAD_PROFILE
+.
+
+MessageId=0x4B7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CONTAINER
+Language=English
+ERROR_NOT_CONTAINER
+.
+
+MessageId=0x4B8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXTENDED_ERROR
+Language=English
+ERROR_EXTENDED_ERROR - Too many posts were made to a semaphore.\r
+.
+
+MessageId=0x4B9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GROUPNAME
+Language=English
+ERROR_INVALID_GROUPNAME - Only part of a ReadProcessMemory or WriteProcessMemory request was completed.\r
+.
+
+MessageId=0x4BA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_COMPUTERNAME
+Language=English
+ERROR_INVALID_COMPUTERNAME - The oplock request is denied.\r
+.
+
+MessageId=0x4BB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EVENTNAME
+Language=English
+ERROR_INVALID_EVENTNAME - An invalid oplock acknowledgment was received by the system.\r
+.
+
+MessageId=0x4BC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAINNAME
+Language=English
+ERROR_INVALID_DOMAINNAME
+.
+
+MessageId=0x4BD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICENAME
+Language=English
+ERROR_INVALID_SERVICENAME
+.
+
+MessageId=0x4BE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_NETNAME
+Language=English
+ERROR_INVALID_NETNAME
+.
+
+MessageId=0x4BF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SHARENAME
+Language=English
+ERROR_INVALID_SHARENAME
+.
+
+MessageId=0x4C0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PASSWORDNAME
+Language=English
+ERROR_INVALID_PASSWORDNAME
+.
+
+MessageId=0x4C1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGENAME
+Language=English
+ERROR_INVALID_MESSAGENAME
+.
+
+MessageId=0x4C2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGEDEST
+Language=English
+ERROR_INVALID_MESSAGEDEST
+.
+
+MessageId=0x4C3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SESSION_CREDENTIAL_CONFLICT
+Language=English
+ERROR_SESSION_CREDENTIAL_CONFLICT
+.
+
+MessageId=0x4C4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
+Language=English
+ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
+.
+
+MessageId=0x4C5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUP_DOMAINNAME
+Language=English
+ERROR_DUP_DOMAINNAME
+.
+
+MessageId=0x4C6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_NETWORK
+Language=English
+ERROR_NO_NETWORK
+.
+
+MessageId=0x4C7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANCELLED
+Language=English
+ERROR_CANCELLED
+.
+
+MessageId=0x4C8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_USER_MAPPED_FILE
+Language=English
+ERROR_USER_MAPPED_FILE
+.
+
+MessageId=0x4C9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_REFUSED
+Language=English
+ERROR_CONNECTION_REFUSED
+.
+
+MessageId=0x4CA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GRACEFUL_DISCONNECT
+Language=English
+ERROR_GRACEFUL_DISCONNECT
+.
+
+MessageId=0x4CB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADDRESS_ALREADY_ASSOCIATED
+Language=English
+ERROR_ADDRESS_ALREADY_ASSOCIATED
+.
+
+MessageId=0x4CC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADDRESS_NOT_ASSOCIATED
+Language=English
+ERROR_ADDRESS_NOT_ASSOCIATED
+.
+
+MessageId=0x4CD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_INVALID
+Language=English
+ERROR_CONNECTION_INVALID
+.
+
+MessageId=0x4CE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_ACTIVE
+Language=English
+ERROR_CONNECTION_ACTIVE
+.
+
+MessageId=0x4CF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_UNREACHABLE
+Language=English
+ERROR_NETWORK_UNREACHABLE
+.
+
+MessageId=0x4D0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOST_UNREACHABLE
+Language=English
+ERROR_HOST_UNREACHABLE
+.
+
+MessageId=0x4D1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROTOCOL_UNREACHABLE
+Language=English
+ERROR_PROTOCOL_UNREACHABLE
+.
+
+MessageId=0x4D2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PORT_UNREACHABLE
+Language=English
+ERROR_PORT_UNREACHABLE
+.
+
+MessageId=0x4D3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REQUEST_ABORTED
+Language=English
+ERROR_REQUEST_ABORTED
+.
+
+MessageId=0x4D4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_ABORTED
+Language=English
+ERROR_CONNECTION_ABORTED
+.
+
+MessageId=0x4D5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RETRY
+Language=English
+ERROR_RETRY
+.
+
+MessageId=0x4D6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_COUNT_LIMIT
+Language=English
+ERROR_CONNECTION_COUNT_LIMIT
+.
+
+MessageId=0x4D7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGIN_TIME_RESTRICTION
+Language=English
+ERROR_LOGIN_TIME_RESTRICTION
+.
+
+MessageId=0x4D8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGIN_WKSTA_RESTRICTION
+Language=English
+ERROR_LOGIN_WKSTA_RESTRICTION
+.
+
+MessageId=0x4D9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INCORRECT_ADDRESS
+Language=English
+ERROR_INCORRECT_ADDRESS
+.
+
+MessageId=0x4DA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_REGISTERED
+Language=English
+ERROR_ALREADY_REGISTERED
+.
+
+MessageId=0x4DB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NOT_FOUND
+Language=English
+ERROR_SERVICE_NOT_FOUND
+.
+
+MessageId=0x4DC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_AUTHENTICATED
+Language=English
+ERROR_NOT_AUTHENTICATED
+.
+
+MessageId=0x4DD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOGGED_ON
+Language=English
+ERROR_NOT_LOGGED_ON
+.
+
+MessageId=0x4DE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONTINUE
+Language=English
+ERROR_CONTINUE
+.
+
+MessageId=0x4DF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_INITIALIZED
+Language=English
+ERROR_ALREADY_INITIALIZED
+.
+
+MessageId=0x4E0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_DEVICES
+Language=English
+ERROR_NO_MORE_DEVICES
+.
+
+MessageId=0x514
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ALL_ASSIGNED
+Language=English
+ERROR_NOT_ALL_ASSIGNED
+.
+
+MessageId=0x515
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SOME_NOT_MAPPED
+Language=English
+ERROR_SOME_NOT_MAPPED
+.
+
+MessageId=0x516
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_QUOTAS_FOR_ACCOUNT
+Language=English
+ERROR_NO_QUOTAS_FOR_ACCOUNT
+.
+
+MessageId=0x517
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCAL_USER_SESSION_KEY
+Language=English
+ERROR_LOCAL_USER_SESSION_KEY
+.
+
+MessageId=0x518
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NULL_LM_PASSWORD
+Language=English
+ERROR_NULL_LM_PASSWORD
+.
+
+MessageId=0x519
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_REVISION
+Language=English
+ERROR_UNKNOWN_REVISION
+.
+
+MessageId=0x51A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REVISION_MISMATCH
+Language=English
+ERROR_REVISION_MISMATCH
+.
+
+MessageId=0x51B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_OWNER
+Language=English
+ERROR_INVALID_OWNER
+.
+
+MessageId=0x51C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRIMARY_GROUP
+Language=English
+ERROR_INVALID_PRIMARY_GROUP
+.
+
+MessageId=0x51D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_IMPERSONATION_TOKEN
+Language=English
+ERROR_NO_IMPERSONATION_TOKEN
+.
+
+MessageId=0x51E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_DISABLE_MANDATORY
+Language=English
+ERROR_CANT_DISABLE_MANDATORY
+.
+
+MessageId=0x51F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_LOGON_SERVERS
+Language=English
+ERROR_NO_LOGON_SERVERS
+.
+
+MessageId=0x520
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_LOGON_SESSION
+Language=English
+ERROR_NO_SUCH_LOGON_SESSION
+.
+
+MessageId=0x521
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_PRIVILEGE
+Language=English
+ERROR_NO_SUCH_PRIVILEGE
+.
+
+MessageId=0x522
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRIVILEGE_NOT_HELD
+Language=English
+ERROR_PRIVILEGE_NOT_HELD
+.
+
+MessageId=0x523
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCOUNT_NAME
+Language=English
+ERROR_INVALID_ACCOUNT_NAME
+.
+
+MessageId=0x524
+Severity=Success
+Facility=System
+SymbolicName=ERROR_USER_EXISTS
+Language=English
+ERROR_USER_EXISTS
+.
+
+MessageId=0x525
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_USER
+Language=English
+ERROR_NO_SUCH_USER
+.
+
+MessageId=0x526
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GROUP_EXISTS
+Language=English
+ERROR_GROUP_EXISTS
+.
+
+MessageId=0x527
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_GROUP
+Language=English
+ERROR_NO_SUCH_GROUP
+.
+
+MessageId=0x528
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_IN_GROUP
+Language=English
+ERROR_MEMBER_IN_GROUP
+.
+
+MessageId=0x529
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_NOT_IN_GROUP
+Language=English
+ERROR_MEMBER_NOT_IN_GROUP
+.
+
+MessageId=0x52A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LAST_ADMIN
+Language=English
+ERROR_LAST_ADMIN
+.
+
+MessageId=0x52B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRONG_PASSWORD
+Language=English
+ERROR_WRONG_PASSWORD
+.
+
+MessageId=0x52C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ILL_FORMED_PASSWORD
+Language=English
+ERROR_ILL_FORMED_PASSWORD
+.
+
+MessageId=0x52D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_RESTRICTION
+Language=English
+ERROR_PASSWORD_RESTRICTION
+.
+
+MessageId=0x52E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_FAILURE
+Language=English
+ERROR_LOGON_FAILURE
+.
+
+MessageId=0x52F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_RESTRICTION
+Language=English
+ERROR_ACCOUNT_RESTRICTION
+.
+
+MessageId=0x530
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LOGON_HOURS
+Language=English
+ERROR_INVALID_LOGON_HOURS
+.
+
+MessageId=0x531
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WORKSTATION
+Language=English
+ERROR_INVALID_WORKSTATION
+.
+
+MessageId=0x532
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_EXPIRED
+Language=English
+ERROR_PASSWORD_EXPIRED
+.
+
+MessageId=0x533
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_DISABLED
+Language=English
+ERROR_ACCOUNT_DISABLED
+.
+
+MessageId=0x534
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NONE_MAPPED
+Language=English
+ERROR_NONE_MAPPED
+.
+
+MessageId=0x535
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_LUIDS_REQUESTED
+Language=English
+ERROR_TOO_MANY_LUIDS_REQUESTED
+.
+
+MessageId=0x536
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LUIDS_EXHAUSTED
+Language=English
+ERROR_LUIDS_EXHAUSTED
+.
+
+MessageId=0x537
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SUB_AUTHORITY
+Language=English
+ERROR_INVALID_SUB_AUTHORITY
+.
+
+MessageId=0x538
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACL
+Language=English
+ERROR_INVALID_ACL
+.
+
+MessageId=0x539
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SID
+Language=English
+ERROR_INVALID_SID
+.
+
+MessageId=0x53A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SECURITY_DESCR
+Language=English
+ERROR_INVALID_SECURITY_DESCR
+.
+
+MessageId=0x53C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_INHERITANCE_ACL
+Language=English
+ERROR_BAD_INHERITANCE_ACL
+.
+
+MessageId=0x53D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_DISABLED
+Language=English
+ERROR_SERVER_DISABLED
+.
+
+MessageId=0x53E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_NOT_DISABLED
+Language=English
+ERROR_SERVER_NOT_DISABLED
+.
+
+MessageId=0x53F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ID_AUTHORITY
+Language=English
+ERROR_INVALID_ID_AUTHORITY
+.
+
+MessageId=0x540
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALLOTTED_SPACE_EXCEEDED
+Language=English
+ERROR_ALLOTTED_SPACE_EXCEEDED
+.
+
+MessageId=0x541
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GROUP_ATTRIBUTES
+Language=English
+ERROR_INVALID_GROUP_ATTRIBUTES
+.
+
+MessageId=0x542
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_IMPERSONATION_LEVEL
+Language=English
+ERROR_BAD_IMPERSONATION_LEVEL
+.
+
+MessageId=0x543
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_OPEN_ANONYMOUS
+Language=English
+ERROR_CANT_OPEN_ANONYMOUS
+.
+
+MessageId=0x544
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_VALIDATION_CLASS
+Language=English
+ERROR_BAD_VALIDATION_CLASS
+.
+
+MessageId=0x545
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_TOKEN_TYPE
+Language=English
+ERROR_BAD_TOKEN_TYPE
+.
+
+MessageId=0x546
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SECURITY_ON_OBJECT
+Language=English
+ERROR_NO_SECURITY_ON_OBJECT
+.
+
+MessageId=0x547
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_ACCESS_DOMAIN_INFO
+Language=English
+ERROR_CANT_ACCESS_DOMAIN_INFO
+.
+
+MessageId=0x548
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVER_STATE
+Language=English
+ERROR_INVALID_SERVER_STATE
+.
+
+MessageId=0x549
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAIN_STATE
+Language=English
+ERROR_INVALID_DOMAIN_STATE
+.
+
+MessageId=0x54A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAIN_ROLE
+Language=English
+ERROR_INVALID_DOMAIN_ROLE
+.
+
+MessageId=0x54B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_DOMAIN
+Language=English
+ERROR_NO_SUCH_DOMAIN
+.
+
+MessageId=0x54C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_EXISTS
+Language=English
+ERROR_DOMAIN_EXISTS
+.
+
+MessageId=0x54D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_LIMIT_EXCEEDED
+Language=English
+ERROR_DOMAIN_LIMIT_EXCEEDED
+.
+
+MessageId=0x54E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_DB_CORRUPTION
+Language=English
+ERROR_INTERNAL_DB_CORRUPTION
+.
+
+MessageId=0x54F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_ERROR
+Language=English
+ERROR_INTERNAL_ERROR
+.
+
+MessageId=0x550
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GENERIC_NOT_MAPPED
+Language=English
+ERROR_GENERIC_NOT_MAPPED
+.
+
+MessageId=0x551
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DESCRIPTOR_FORMAT
+Language=English
+ERROR_BAD_DESCRIPTOR_FORMAT
+.
+
+MessageId=0x552
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOGON_PROCESS
+Language=English
+ERROR_NOT_LOGON_PROCESS
+.
+
+MessageId=0x553
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_SESSION_EXISTS
+Language=English
+ERROR_LOGON_SESSION_EXISTS
+.
+
+MessageId=0x554
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_PACKAGE
+Language=English
+ERROR_NO_SUCH_PACKAGE
+.
+
+MessageId=0x555
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_LOGON_SESSION_STATE
+Language=English
+ERROR_BAD_LOGON_SESSION_STATE
+.
+
+MessageId=0x556
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_SESSION_COLLISION
+Language=English
+ERROR_LOGON_SESSION_COLLISION
+.
+
+MessageId=0x557
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LOGON_TYPE
+Language=English
+ERROR_INVALID_LOGON_TYPE
+.
+
+MessageId=0x558
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_IMPERSONATE
+Language=English
+ERROR_CANNOT_IMPERSONATE
+.
+
+MessageId=0x559
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RXACT_INVALID_STATE
+Language=English
+ERROR_RXACT_INVALID_STATE
+.
+
+MessageId=0x55A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RXACT_COMMIT_FAILURE
+Language=English
+ERROR_RXACT_COMMIT_FAILURE
+.
+
+MessageId=0x55B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_ACCOUNT
+Language=English
+ERROR_SPECIAL_ACCOUNT
+.
+
+MessageId=0x55C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_GROUP
+Language=English
+ERROR_SPECIAL_GROUP
+.
+
+MessageId=0x55D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_USER
+Language=English
+ERROR_SPECIAL_USER
+.
+
+MessageId=0x55E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBERS_PRIMARY_GROUP
+Language=English
+ERROR_MEMBERS_PRIMARY_GROUP
+.
+
+MessageId=0x55F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOKEN_ALREADY_IN_USE
+Language=English
+ERROR_TOKEN_ALREADY_IN_USE
+.
+
+MessageId=0x560
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_ALIAS
+Language=English
+ERROR_NO_SUCH_ALIAS
+.
+
+MessageId=0x561
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_NOT_IN_ALIAS
+Language=English
+ERROR_MEMBER_NOT_IN_ALIAS
+.
+
+MessageId=0x562
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_IN_ALIAS
+Language=English
+ERROR_MEMBER_IN_ALIAS
+.
+
+MessageId=0x563
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALIAS_EXISTS
+Language=English
+ERROR_ALIAS_EXISTS
+.
+
+MessageId=0x564
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_NOT_GRANTED
+Language=English
+ERROR_LOGON_NOT_GRANTED
+.
+
+MessageId=0x565
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SECRETS
+Language=English
+ERROR_TOO_MANY_SECRETS
+.
+
+MessageId=0x566
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SECRET_TOO_LONG
+Language=English
+ERROR_SECRET_TOO_LONG
+.
+
+MessageId=0x567
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_DB_ERROR
+Language=English
+ERROR_INTERNAL_DB_ERROR
+.
+
+MessageId=0x568
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_CONTEXT_IDS
+Language=English
+ERROR_TOO_MANY_CONTEXT_IDS
+.
+
+MessageId=0x569
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_TYPE_NOT_GRANTED
+Language=English
+ERROR_LOGON_TYPE_NOT_GRANTED
+.
+
+MessageId=0x56A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NT_CROSS_ENCRYPTION_REQUIRED
+Language=English
+ERROR_NT_CROSS_ENCRYPTION_REQUIRED
+.
+
+MessageId=0x56B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_MEMBER
+Language=English
+ERROR_NO_SUCH_MEMBER
+.
+
+MessageId=0x56C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MEMBER
+Language=English
+ERROR_INVALID_MEMBER
+.
+
+MessageId=0x56D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SIDS
+Language=English
+ERROR_TOO_MANY_SIDS
+.
+
+MessageId=0x56E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LM_CROSS_ENCRYPTION_REQUIRED
+Language=English
+ERROR_LM_CROSS_ENCRYPTION_REQUIRED
+.
+
+MessageId=0x56F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_INHERITANCE
+Language=English
+ERROR_NO_INHERITANCE
+.
+
+MessageId=0x570
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_CORRUPT
+Language=English
+ERROR_FILE_CORRUPT
+.
+
+MessageId=0x571
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_CORRUPT
+Language=English
+ERROR_DISK_CORRUPT
+.
+
+MessageId=0x572
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_USER_SESSION_KEY
+Language=English
+ERROR_NO_USER_SESSION_KEY
+.
+
+MessageId=0x573
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LICENSE_QUOTA_EXCEEDED
+Language=English
+ERROR_LICENSE_QUOTA_EXCEEDED
+.
+
+MessageId=0x578
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WINDOW_HANDLE
+Language=English
+ERROR_INVALID_WINDOW_HANDLE
+.
+
+MessageId=0x579
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MENU_HANDLE
+Language=English
+ERROR_INVALID_MENU_HANDLE
+.
+
+MessageId=0x57A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_CURSOR_HANDLE
+Language=English
+ERROR_INVALID_CURSOR_HANDLE
+.
+
+MessageId=0x57B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCEL_HANDLE
+Language=English
+ERROR_INVALID_ACCEL_HANDLE
+.
+
+MessageId=0x57C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HOOK_HANDLE
+Language=English
+ERROR_INVALID_HOOK_HANDLE
+.
+
+MessageId=0x57D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DWP_HANDLE
+Language=English
+ERROR_INVALID_DWP_HANDLE
+.
+
+MessageId=0x57E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TLW_WITH_WSCHILD
+Language=English
+ERROR_TLW_WITH_WSCHILD
+.
+
+MessageId=0x57F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_FIND_WND_CLASS
+Language=English
+ERROR_CANNOT_FIND_WND_CLASS
+.
+
+MessageId=0x580
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_OF_OTHER_THREAD
+Language=English
+ERROR_WINDOW_OF_OTHER_THREAD
+.
+
+MessageId=0x581
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOTKEY_ALREADY_REGISTERED
+Language=English
+ERROR_HOTKEY_ALREADY_REGISTERED
+.
+
+MessageId=0x582
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_ALREADY_EXISTS
+Language=English
+ERROR_CLASS_ALREADY_EXISTS
+.
+
+MessageId=0x583
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_DOES_NOT_EXIST
+Language=English
+ERROR_CLASS_DOES_NOT_EXIST
+.
+
+MessageId=0x584
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_HAS_WINDOWS
+Language=English
+ERROR_CLASS_HAS_WINDOWS
+.
+
+MessageId=0x585
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_INDEX
+Language=English
+ERROR_INVALID_INDEX
+.
+
+MessageId=0x586
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ICON_HANDLE
+Language=English
+ERROR_INVALID_ICON_HANDLE
+.
+
+MessageId=0x587
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRIVATE_DIALOG_INDEX
+Language=English
+ERROR_PRIVATE_DIALOG_INDEX
+.
+
+MessageId=0x588
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LISTBOX_ID_NOT_FOUND
+Language=English
+ERROR_LISTBOX_ID_NOT_FOUND
+.
+
+MessageId=0x589
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_WILDCARD_CHARACTERS
+Language=English
+ERROR_NO_WILDCARD_CHARACTERS
+.
+
+MessageId=0x58A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLIPBOARD_NOT_OPEN
+Language=English
+ERROR_CLIPBOARD_NOT_OPEN
+.
+
+MessageId=0x58B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOTKEY_NOT_REGISTERED
+Language=English
+ERROR_HOTKEY_NOT_REGISTERED
+.
+
+MessageId=0x58C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_NOT_DIALOG
+Language=English
+ERROR_WINDOW_NOT_DIALOG
+.
+
+MessageId=0x58D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONTROL_ID_NOT_FOUND
+Language=English
+ERROR_CONTROL_ID_NOT_FOUND
+.
+
+MessageId=0x58E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_COMBOBOX_MESSAGE
+Language=English
+ERROR_INVALID_COMBOBOX_MESSAGE
+.
+
+MessageId=0x58F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_NOT_COMBOBOX
+Language=English
+ERROR_WINDOW_NOT_COMBOBOX
+.
+
+MessageId=0x590
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EDIT_HEIGHT
+Language=English
+ERROR_INVALID_EDIT_HEIGHT
+.
+
+MessageId=0x591
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DC_NOT_FOUND
+Language=English
+ERROR_DC_NOT_FOUND
+.
+
+MessageId=0x592
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HOOK_FILTER
+Language=English
+ERROR_INVALID_HOOK_FILTER
+.
+
+MessageId=0x593
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FILTER_PROC
+Language=English
+ERROR_INVALID_FILTER_PROC
+.
+
+MessageId=0x594
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOOK_NEEDS_HMOD
+Language=English
+ERROR_HOOK_NEEDS_HMOD
+.
+
+MessageId=0x595
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GLOBAL_ONLY_HOOK
+Language=English
+ERROR_GLOBAL_ONLY_HOOK
+.
+
+MessageId=0x596
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOURNAL_HOOK_SET
+Language=English
+ERROR_JOURNAL_HOOK_SET
+.
+
+MessageId=0x597
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOOK_NOT_INSTALLED
+Language=English
+ERROR_HOOK_NOT_INSTALLED
+.
+
+MessageId=0x598
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LB_MESSAGE
+Language=English
+ERROR_INVALID_LB_MESSAGE
+.
+
+MessageId=0x599
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SETCOUNT_ON_BAD_LB
+Language=English
+ERROR_SETCOUNT_ON_BAD_LB
+.
+
+MessageId=0x59A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LB_WITHOUT_TABSTOPS
+Language=English
+ERROR_LB_WITHOUT_TABSTOPS
+.
+
+MessageId=0x59B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DESTROY_OBJECT_OF_OTHER_THREAD
+Language=English
+ERROR_DESTROY_OBJECT_OF_OTHER_THREAD
+.
+
+MessageId=0x59C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_WINDOW_MENU
+Language=English
+ERROR_CHILD_WINDOW_MENU
+.
+
+MessageId=0x59D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SYSTEM_MENU
+Language=English
+ERROR_NO_SYSTEM_MENU
+.
+
+MessageId=0x59E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MSGBOX_STYLE
+Language=English
+ERROR_INVALID_MSGBOX_STYLE
+.
+
+MessageId=0x59F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SPI_VALUE
+Language=English
+ERROR_INVALID_SPI_VALUE
+.
+
+MessageId=0x5A0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SCREEN_ALREADY_LOCKED
+Language=English
+ERROR_SCREEN_ALREADY_LOCKED
+.
+
+MessageId=0x5A1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HWNDS_HAVE_DIFF_PARENT
+Language=English
+ERROR_HWNDS_HAVE_DIFF_PARENT
+.
+
+MessageId=0x5A2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CHILD_WINDOW
+Language=English
+ERROR_NOT_CHILD_WINDOW
+.
+
+MessageId=0x5A3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GW_COMMAND
+Language=English
+ERROR_INVALID_GW_COMMAND
+.
+
+MessageId=0x5A4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_THREAD_ID
+Language=English
+ERROR_INVALID_THREAD_ID
+.
+
+MessageId=0x5A5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NON_MDICHILD_WINDOW
+Language=English
+ERROR_NON_MDICHILD_WINDOW
+.
+
+MessageId=0x5A6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_POPUP_ALREADY_ACTIVE
+Language=English
+ERROR_POPUP_ALREADY_ACTIVE
+.
+
+MessageId=0x5A7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SCROLLBARS
+Language=English
+ERROR_NO_SCROLLBARS
+.
+
+MessageId=0x5A8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SCROLLBAR_RANGE
+Language=English
+ERROR_INVALID_SCROLLBAR_RANGE
+.
+
+MessageId=0x5A9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SHOWWIN_COMMAND
+Language=English
+ERROR_INVALID_SHOWWIN_COMMAND
+.
+
+MessageId=0x5AA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SYSTEM_RESOURCES
+Language=English
+ERROR_NO_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NONPAGED_SYSTEM_RESOURCES
+Language=English
+ERROR_NONPAGED_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PAGED_SYSTEM_RESOURCES
+Language=English
+ERROR_PAGED_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WORKING_SET_QUOTA
+Language=English
+ERROR_WORKING_SET_QUOTA - Attempt to access invalid address.\r
+.
+
+MessageId=0x5AE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PAGEFILE_QUOTA
+Language=English
+ERROR_PAGEFILE_QUOTA
+.
+
+MessageId=0x5AF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_COMMITMENT_LIMIT
+Language=English
+ERROR_COMMITMENT_LIMIT
+.
+
+MessageId=0x5B0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MENU_ITEM_NOT_FOUND
+Language=English
+ERROR_MENU_ITEM_NOT_FOUND
+.
+
+MessageId=0x5DC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_FILE_CORRUPT
+Language=English
+ERROR_EVENTLOG_FILE_CORRUPT
+.
+
+MessageId=0x5DD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_CANT_START
+Language=English
+ERROR_EVENTLOG_CANT_START
+.
+
+MessageId=0x5DE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOG_FILE_FULL
+Language=English
+ERROR_LOG_FILE_FULL
+.
+
+MessageId=0x5DF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_FILE_CHANGED
+Language=English
+ERROR_EVENTLOG_FILE_CHANGED
+.
+
+MessageId=0x6A4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_STRING_BINDING
+Language=English
+RPC_S_INVALID_STRING_BINDING
+.
+
+MessageId=0x6A5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_WRONG_KIND_OF_BINDING
+Language=English
+RPC_S_WRONG_KIND_OF_BINDING
+.
+
+MessageId=0x6A6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_BINDING
+Language=English
+RPC_S_INVALID_BINDING
+.
+
+MessageId=0x6A7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTSEQ_NOT_SUPPORTED
+Language=English
+RPC_S_PROTSEQ_NOT_SUPPORTED
+.
+
+MessageId=0x6A8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_RPC_PROTSEQ
+Language=English
+RPC_S_INVALID_RPC_PROTSEQ
+.
+
+MessageId=0x6A9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_STRING_UUID
+Language=English
+RPC_S_INVALID_STRING_UUID
+.
+
+MessageId=0x6AA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_ENDPOINT_FORMAT
+Language=English
+RPC_S_INVALID_ENDPOINT_FORMAT
+.
+
+MessageId=0x6AB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NET_ADDR
+Language=English
+RPC_S_INVALID_NET_ADDR
+.
+
+MessageId=0x6AC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_ENDPOINT_FOUND
+Language=English
+RPC_S_NO_ENDPOINT_FOUND
+.
+
+MessageId=0x6AD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_TIMEOUT
+Language=English
+RPC_S_INVALID_TIMEOUT
+.
+
+MessageId=0x6AE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_OBJECT_NOT_FOUND
+Language=English
+RPC_S_OBJECT_NOT_FOUND
+.
+
+MessageId=0x6AF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ALREADY_REGISTERED
+Language=English
+RPC_S_ALREADY_REGISTERED
+.
+
+MessageId=0x6B0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_TYPE_ALREADY_REGISTERED
+Language=English
+RPC_S_TYPE_ALREADY_REGISTERED
+.
+
+MessageId=0x6B1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ALREADY_LISTENING
+Language=English
+RPC_S_ALREADY_LISTENING
+.
+
+MessageId=0x6B2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PROTSEQS_REGISTERED
+Language=English
+RPC_S_NO_PROTSEQS_REGISTERED
+.
+
+MessageId=0x6B3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_LISTENING
+Language=English
+RPC_S_NOT_LISTENING
+.
+
+MessageId=0x6B4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_MGR_TYPE
+Language=English
+RPC_S_UNKNOWN_MGR_TYPE
+.
+
+MessageId=0x6B5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_IF
+Language=English
+RPC_S_UNKNOWN_IF
+.
+
+MessageId=0x6B6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_BINDINGS
+Language=English
+RPC_S_NO_BINDINGS
+.
+
+MessageId=0x6B7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PROTSEQS
+Language=English
+RPC_S_NO_PROTSEQS
+.
+
+MessageId=0x6B8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CANT_CREATE_ENDPOINT
+Language=English
+RPC_S_CANT_CREATE_ENDPOINT
+.
+
+MessageId=0x6B9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_OUT_OF_RESOURCES
+Language=English
+RPC_S_OUT_OF_RESOURCES
+.
+
+MessageId=0x6BA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SERVER_UNAVAILABLE
+Language=English
+RPC_S_SERVER_UNAVAILABLE
+.
+
+MessageId=0x6BB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SERVER_TOO_BUSY
+Language=English
+RPC_S_SERVER_TOO_BUSY
+.
+
+MessageId=0x6BC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NETWORK_OPTIONS
+Language=English
+RPC_S_INVALID_NETWORK_OPTIONS
+.
+
+MessageId=0x6BD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_CALL_ACTIVE
+Language=English
+RPC_S_NO_CALL_ACTIVE
+.
+
+MessageId=0x6BE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_FAILED
+Language=English
+RPC_S_CALL_FAILED
+.
+
+MessageId=0x6BF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_FAILED_DNE
+Language=English
+RPC_S_CALL_FAILED_DNE
+.
+
+MessageId=0x6C0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTOCOL_ERROR
+Language=English
+RPC_S_PROTOCOL_ERROR
+.
+
+MessageId=0x6C2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_TRANS_SYN
+Language=English
+RPC_S_UNSUPPORTED_TRANS_SYN
+.
+
+MessageId=0x6C4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_TYPE
+Language=English
+RPC_S_UNSUPPORTED_TYPE
+.
+
+MessageId=0x6C5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_TAG
+Language=English
+RPC_S_INVALID_TAG
+.
+
+MessageId=0x6C6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_BOUND
+Language=English
+RPC_S_INVALID_BOUND
+.
+
+MessageId=0x6C7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_ENTRY_NAME
+Language=English
+RPC_S_NO_ENTRY_NAME
+.
+
+MessageId=0x6C8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NAME_SYNTAX
+Language=English
+RPC_S_INVALID_NAME_SYNTAX
+.
+
+MessageId=0x6C9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_NAME_SYNTAX
+Language=English
+RPC_S_UNSUPPORTED_NAME_SYNTAX
+.
+
+MessageId=0x6CB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UUID_NO_ADDRESS
+Language=English
+RPC_S_UUID_NO_ADDRESS
+.
+
+MessageId=0x6CC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_DUPLICATE_ENDPOINT
+Language=English
+RPC_S_DUPLICATE_ENDPOINT
+.
+
+MessageId=0x6CD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_TYPE
+Language=English
+RPC_S_UNKNOWN_AUTHN_TYPE
+.
+
+MessageId=0x6CE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_MAX_CALLS_TOO_SMALL
+Language=English
+RPC_S_MAX_CALLS_TOO_SMALL - Arithmetic result exceeded 32 bits.\r
+.
+
+MessageId=0x6CF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_STRING_TOO_LONG
+Language=English
+RPC_S_STRING_TOO_LONG - There is a process on other end of the pipe.\r
+.
+
+MessageId=0x6D0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTSEQ_NOT_FOUND
+Language=English
+RPC_S_PROTSEQ_NOT_FOUND - Waiting for a process to open the other end of the pipe.\r
+.
+
+MessageId=0x6D1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROCNUM_OUT_OF_RANGE
+Language=English
+RPC_S_PROCNUM_OUT_OF_RANGE
+.
+
+MessageId=0x6D2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_BINDING_HAS_NO_AUTH
+Language=English
+RPC_S_BINDING_HAS_NO_AUTH
+.
+
+MessageId=0x6D3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_SERVICE
+Language=English
+RPC_S_UNKNOWN_AUTHN_SERVICE
+.
+
+MessageId=0x6D4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_LEVEL
+Language=English
+RPC_S_UNKNOWN_AUTHN_LEVEL
+.
+
+MessageId=0x6D5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_AUTH_IDENTITY
+Language=English
+RPC_S_INVALID_AUTH_IDENTITY
+.
+
+MessageId=0x6D6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHZ_SERVICE
+Language=English
+RPC_S_UNKNOWN_AUTHZ_SERVICE
+.
+
+MessageId=0x6D7
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_INVALID_ENTRY
+Language=English
+EPT_S_INVALID_ENTRY
+.
+
+MessageId=0x6D8
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_CANT_PERFORM_OP
+Language=English
+EPT_S_CANT_PERFORM_OP
+.
+
+MessageId=0x6D9
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_NOT_REGISTERED
+Language=English
+EPT_S_NOT_REGISTERED
+.
+
+MessageId=0x6DA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOTHING_TO_EXPORT
+Language=English
+RPC_S_NOTHING_TO_EXPORT
+.
+
+MessageId=0x6DB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INCOMPLETE_NAME
+Language=English
+RPC_S_INCOMPLETE_NAME
+.
+
+MessageId=0x6DC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_VERS_OPTION
+Language=English
+RPC_S_INVALID_VERS_OPTION
+.
+
+MessageId=0x6DD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_MORE_MEMBERS
+Language=English
+RPC_S_NO_MORE_MEMBERS
+.
+
+MessageId=0x6DE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_ALL_OBJS_UNEXPORTED
+Language=English
+RPC_S_NOT_ALL_OBJS_UNEXPORTED
+.
+
+MessageId=0x6DF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INTERFACE_NOT_FOUND
+Language=English
+RPC_S_INTERFACE_NOT_FOUND
+.
+
+MessageId=0x6E0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ENTRY_ALREADY_EXISTS
+Language=English
+RPC_S_ENTRY_ALREADY_EXISTS
+.
+
+MessageId=0x6E1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ENTRY_NOT_FOUND
+Language=English
+RPC_S_ENTRY_NOT_FOUND
+.
+
+MessageId=0x6E2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NAME_SERVICE_UNAVAILABLE
+Language=English
+RPC_S_NAME_SERVICE_UNAVAILABLE
+.
+
+MessageId=0x6E3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NAF_ID
+Language=English
+RPC_S_INVALID_NAF_ID
+.
+
+MessageId=0x6E4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CANNOT_SUPPORT
+Language=English
+RPC_S_CANNOT_SUPPORT
+.
+
+MessageId=0x6E5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_CONTEXT_AVAILABLE
+Language=English
+RPC_S_NO_CONTEXT_AVAILABLE
+.
+
+MessageId=0x6E6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INTERNAL_ERROR
+Language=English
+RPC_S_INTERNAL_ERROR
+.
+
+MessageId=0x6E7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ZERO_DIVIDE
+Language=English
+RPC_S_ZERO_DIVIDE
+.
+
+MessageId=0x6E8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ADDRESS_ERROR
+Language=English
+RPC_S_ADDRESS_ERROR
+.
+
+MessageId=0x6E9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_DIV_ZERO
+Language=English
+RPC_S_FP_DIV_ZERO
+.
+
+MessageId=0x6EA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_UNDERFLOW
+Language=English
+RPC_S_FP_UNDERFLOW
+.
+
+MessageId=0x6EB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_OVERFLOW
+Language=English
+RPC_S_FP_OVERFLOW
+.
+
+MessageId=0x6EC
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_NO_MORE_ENTRIES
+Language=English
+RPC_X_NO_MORE_ENTRIES
+.
+
+MessageId=0x6ED
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CHAR_TRANS_OPEN_FAIL
+Language=English
+RPC_X_SS_CHAR_TRANS_OPEN_FAIL
+.
+
+MessageId=0x6EE
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CHAR_TRANS_SHORT_FILE
+Language=English
+RPC_X_SS_CHAR_TRANS_SHORT_FILE
+.
+
+MessageId=0x6EF
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_IN_NULL_CONTEXT
+Language=English
+RPC_X_SS_IN_NULL_CONTEXT
+.
+
+MessageId=0x6F1
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CONTEXT_DAMAGED
+Language=English
+RPC_X_SS_CONTEXT_DAMAGED
+.
+
+MessageId=0x6F2
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_HANDLES_MISMATCH
+Language=English
+RPC_X_SS_HANDLES_MISMATCH
+.
+
+MessageId=0x6F3
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CANNOT_GET_CALL_HANDLE
+Language=English
+RPC_X_SS_CANNOT_GET_CALL_HANDLE
+.
+
+MessageId=0x6F4
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_NULL_REF_POINTER
+Language=English
+RPC_X_NULL_REF_POINTER
+.
+
+MessageId=0x6F5
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_ENUM_VALUE_OUT_OF_RANGE
+Language=English
+RPC_X_ENUM_VALUE_OUT_OF_RANGE
+.
+
+MessageId=0x6F6
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_BYTE_COUNT_TOO_SMALL
+Language=English
+RPC_X_BYTE_COUNT_TOO_SMALL
+.
+
+MessageId=0x6F7
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_BAD_STUB_DATA
+Language=English
+RPC_X_BAD_STUB_DATA
+.
+
+MessageId=0x6F8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_USER_BUFFER
+Language=English
+ERROR_INVALID_USER_BUFFER
+.
+
+MessageId=0x6F9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNRECOGNIZED_MEDIA
+Language=English
+ERROR_UNRECOGNIZED_MEDIA
+.
+
+MessageId=0x6FA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TRUST_LSA_SECRET
+Language=English
+ERROR_NO_TRUST_LSA_SECRET
+.
+
+MessageId=0x6FB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TRUST_SAM_ACCOUNT
+Language=English
+ERROR_NO_TRUST_SAM_ACCOUNT
+.
+
+MessageId=0x6FC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUSTED_DOMAIN_FAILURE
+Language=English
+ERROR_TRUSTED_DOMAIN_FAILURE
+.
+
+MessageId=0x6FD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUSTED_RELATIONSHIP_FAILURE
+Language=English
+ERROR_TRUSTED_RELATIONSHIP_FAILURE
+.
+
+MessageId=0x6FE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUST_FAILURE
+Language=English
+ERROR_TRUST_FAILURE
+.
+
+MessageId=0x6FF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_IN_PROGRESS
+Language=English
+RPC_S_CALL_IN_PROGRESS
+.
+
+MessageId=0x700
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETLOGON_NOT_STARTED
+Language=English
+ERROR_NETLOGON_NOT_STARTED
+.
+
+MessageId=0x701
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_EXPIRED
+Language=English
+ERROR_ACCOUNT_EXPIRED
+.
+
+MessageId=0x702
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REDIRECTOR_HAS_OPEN_HANDLES
+Language=English
+ERROR_REDIRECTOR_HAS_OPEN_HANDLES
+.
+
+MessageId=0x703
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
+Language=English
+ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
+.
+
+MessageId=0x704
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PORT
+Language=English
+ERROR_UNKNOWN_PORT
+.
+
+MessageId=0x705
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINTER_DRIVER
+Language=English
+ERROR_UNKNOWN_PRINTER_DRIVER
+.
+
+MessageId=0x706
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINTPROCESSOR
+Language=English
+ERROR_UNKNOWN_PRINTPROCESSOR
+.
+
+MessageId=0x707
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEPARATOR_FILE
+Language=English
+ERROR_INVALID_SEPARATOR_FILE
+.
+
+MessageId=0x708
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRIORITY
+Language=English
+ERROR_INVALID_PRIORITY
+.
+
+MessageId=0x709
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_NAME
+Language=English
+ERROR_INVALID_PRINTER_NAME
+.
+
+MessageId=0x70A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_ALREADY_EXISTS
+Language=English
+ERROR_PRINTER_ALREADY_EXISTS
+.
+
+MessageId=0x70B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_COMMAND
+Language=English
+ERROR_INVALID_PRINTER_COMMAND
+.
+
+MessageId=0x70C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DATATYPE
+Language=English
+ERROR_INVALID_DATATYPE
+.
+
+MessageId=0x70D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ENVIRONMENT
+Language=English
+ERROR_INVALID_ENVIRONMENT
+.
+
+MessageId=0x70E
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_MORE_BINDINGS
+Language=English
+RPC_S_NO_MORE_BINDINGS
+.
+
+MessageId=0x70F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
+.
+
+MessageId=0x710
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT
+.
+
+MessageId=0x711
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_SERVER_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_SERVER_TRUST_ACCOUNT
+.
+
+MessageId=0x712
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_TRUST_INCONSISTENT
+Language=English
+ERROR_DOMAIN_TRUST_INCONSISTENT
+.
+
+MessageId=0x713
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_HAS_OPEN_HANDLES
+Language=English
+ERROR_SERVER_HAS_OPEN_HANDLES
+.
+
+MessageId=0x714
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_DATA_NOT_FOUND
+Language=English
+ERROR_RESOURCE_DATA_NOT_FOUND
+.
+
+MessageId=0x715
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_TYPE_NOT_FOUND
+Language=English
+ERROR_RESOURCE_TYPE_NOT_FOUND
+.
+
+MessageId=0x716
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_NAME_NOT_FOUND
+Language=English
+ERROR_RESOURCE_NAME_NOT_FOUND
+.
+
+MessageId=0x717
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_LANG_NOT_FOUND
+Language=English
+ERROR_RESOURCE_LANG_NOT_FOUND
+.
+
+MessageId=0x718
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_QUOTA
+Language=English
+ERROR_NOT_ENOUGH_QUOTA
+.
+
+MessageId=0x719
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_INTERFACES
+Language=English
+RPC_S_NO_INTERFACES
+.
+
+MessageId=0x71A
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_CANCELLED
+Language=English
+RPC_S_CALL_CANCELLED
+.
+
+MessageId=0x71B
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_BINDING_INCOMPLETE
+Language=English
+RPC_S_BINDING_INCOMPLETE
+.
+
+MessageId=0x71C
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_COMM_FAILURE
+Language=English
+RPC_S_COMM_FAILURE
+.
+
+MessageId=0x71D
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_AUTHN_LEVEL
+Language=English
+RPC_S_UNSUPPORTED_AUTHN_LEVEL
+.
+
+MessageId=0x71E
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PRINC_NAME
+Language=English
+RPC_S_NO_PRINC_NAME
+.
+
+MessageId=0x71F
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_RPC_ERROR
+Language=English
+RPC_S_NOT_RPC_ERROR
+.
+
+MessageId=0x720
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UUID_LOCAL_ONLY
+Language=English
+RPC_S_UUID_LOCAL_ONLY
+.
+
+MessageId=0x721
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SEC_PKG_ERROR
+Language=English
+RPC_S_SEC_PKG_ERROR
+.
+
+MessageId=0x722
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_CANCELLED
+Language=English
+RPC_S_NOT_CANCELLED
+.
+
+MessageId=0x723
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_INVALID_ES_ACTION
+Language=English
+RPC_X_INVALID_ES_ACTION
+.
+
+MessageId=0x724
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_ES_VERSION
+Language=English
+RPC_X_WRONG_ES_VERSION
+.
+
+MessageId=0x725
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_STUB_VERSION
+Language=English
+RPC_X_WRONG_STUB_VERSION
+.
+
+MessageId=0x726
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_INVALID_PIPE_OBJECT
+Language=English
+RPC_X_INVALID_PIPE_OBJECT
+.
+
+MessageId=0x727
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_PIPE_ORDER
+Language=English
+RPC_X_WRONG_PIPE_ORDER
+.
+
+MessageId=0x728
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_PIPE_VERSION
+Language=English
+RPC_X_WRONG_PIPE_VERSION
+.
+
+MessageId=0x76A
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_GROUP_MEMBER_NOT_FOUND
+Language=English
+RPC_S_GROUP_MEMBER_NOT_FOUND
+.
+
+MessageId=0x76B
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_CANT_CREATE
+Language=English
+EPT_S_CANT_CREATE
+.
+
+MessageId=0x76C
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_OBJECT
+Language=English
+RPC_S_INVALID_OBJECT
+.
+
+MessageId=0x76D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_TIME
+Language=English
+ERROR_INVALID_TIME
+.
+
+MessageId=0x76E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FORM_NAME
+Language=English
+ERROR_INVALID_FORM_NAME
+.
+
+MessageId=0x76F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FORM_SIZE
+Language=English
+ERROR_INVALID_FORM_SIZE
+.
+
+MessageId=0x770
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_WAITING
+Language=English
+ERROR_ALREADY_WAITING
+.
+
+MessageId=0x771
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DELETED
+Language=English
+ERROR_PRINTER_DELETED
+.
+
+MessageId=0x772
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_STATE
+Language=English
+ERROR_INVALID_PRINTER_STATE
+.
+
+MessageId=0x773
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_MUST_CHANGE
+Language=English
+ERROR_PASSWORD_MUST_CHANGE
+.
+
+MessageId=0x774
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_CONTROLLER_NOT_FOUND
+Language=English
+ERROR_DOMAIN_CONTROLLER_NOT_FOUND
+.
+
+MessageId=0x775
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_LOCKED_OUT
+Language=English
+ERROR_ACCOUNT_LOCKED_OUT
+.
+
+MessageId=0x776
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_OXID
+Language=English
+OR_INVALID_OXID
+.
+
+MessageId=0x777
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_OID
+Language=English
+OR_INVALID_OID
+.
+
+MessageId=0x778
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_SET
+Language=English
+OR_INVALID_SET
+.
+
+MessageId=0x779
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SEND_INCOMPLETE
+Language=English
+RPC_S_SEND_INCOMPLETE
+.
+
+MessageId=0x7D0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PIXEL_FORMAT
+Language=English
+ERROR_INVALID_PIXEL_FORMAT
+.
+
+MessageId=0x7D1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DRIVER
+Language=English
+ERROR_BAD_DRIVER
+.
+
+MessageId=0x7D2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WINDOW_STYLE
+Language=English
+ERROR_INVALID_WINDOW_STYLE
+.
+
+MessageId=0x7D3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_METAFILE_NOT_SUPPORTED
+Language=English
+ERROR_METAFILE_NOT_SUPPORTED
+.
+
+MessageId=0x7D4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRANSFORM_NOT_SUPPORTED
+Language=English
+ERROR_TRANSFORM_NOT_SUPPORTED
+.
+
+MessageId=0x7D5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLIPPING_NOT_SUPPORTED
+Language=English
+ERROR_CLIPPING_NOT_SUPPORTED
+.
+
+MessageId=0x89A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_USERNAME
+Language=English
+ERROR_BAD_USERNAME
+.
+
+MessageId=0x8CA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CONNECTED
+Language=English
+ERROR_NOT_CONNECTED
+.
+
+MessageId=0x961
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPEN_FILES
+Language=English
+ERROR_OPEN_FILES
+.
+
+MessageId=0x962
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACTIVE_CONNECTIONS
+Language=English
+ERROR_ACTIVE_CONNECTIONS
+.
+
+MessageId=0x964
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_IN_USE
+Language=English
+ERROR_DEVICE_IN_USE
+.
+
+MessageId=0xBB8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINT_MONITOR
+Language=English
+ERROR_UNKNOWN_PRINT_MONITOR
+.
+
+MessageId=0xBB9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DRIVER_IN_USE
+Language=English
+ERROR_PRINTER_DRIVER_IN_USE
+.
+
+MessageId=0xBBA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPOOL_FILE_NOT_FOUND
+Language=English
+ERROR_SPOOL_FILE_NOT_FOUND
+.
+
+MessageId=0xBBB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPL_NO_STARTDOC
+Language=English
+ERROR_SPL_NO_STARTDOC
+.
+
+MessageId=0xBBC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPL_NO_ADDJOB
+Language=English
+ERROR_SPL_NO_ADDJOB
+.
+
+MessageId=0xBBD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED
+Language=English
+ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED
+.
+
+MessageId=0xBBE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_MONITOR_ALREADY_INSTALLED
+Language=English
+ERROR_PRINT_MONITOR_ALREADY_INSTALLED
+.
+
+MessageId=0xFA0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINS_INTERNAL
+Language=English
+ERROR_WINS_INTERNAL
+.
+
+MessageId=0xFA1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CAN_NOT_DEL_LOCAL_WINS
+Language=English
+ERROR_CAN_NOT_DEL_LOCAL_WINS
+.
+
+MessageId=0xFA2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_STATIC_INIT
+Language=English
+ERROR_STATIC_INIT
+.
+
+MessageId=0xFA3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INC_BACKUP
+Language=English
+ERROR_INC_BACKUP
+.
+
+MessageId=0xFA4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FULL_BACKUP
+Language=English
+ERROR_FULL_BACKUP
+.
+
+MessageId=0xFA5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REC_NON_EXISTENT
+Language=English
+ERROR_REC_NON_EXISTENT
+.
+
+MessageId=0xFA6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RPL_NOT_ALLOWED
+Language=English
+ERROR_RPL_NOT_ALLOWED
+.
+
+MessageId=0x17E6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_BROWSER_SERVERS_FOUND
+Language=English
+ERROR_NO_BROWSER_SERVERS_FOUND
+.
+
+; EOF
diff --git a/lib/kernel32/misc/errormsg.c b/lib/kernel32/misc/errormsg.c
new file mode 100644 (file)
index 0000000..162f964
--- /dev/null
@@ -0,0 +1,796 @@
+/* $Id$
+ *
+ * reactos/lib/kernel32/misc/errormsg.c
+ *
+ */
+/*
+ * FormatMessage implementation
+ *
+ * Copyright 1996 Marcus Meissner
+ *
+ * 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
+ */
+
+#include <ddk/ntddk.h>
+
+// #define NDEBUG
+#include <kernel32/kernel32.h>
+#include <kernel32/error.h>
+
+#define USE_WINE_PORT
+
+#ifdef USE_WINE_PORT
+
+//#define NDEBUG
+//#include <ntdll/ntdll.h>
+
+//#define DPRINTF DPRINT
+//#define ERR DPRINT
+//#define SetLastError(x)
+//#define WARN DPRINT
+#define TRACE DPRINT
+#define FIXME DPRINT
+
+#define strlenW lstrlen
+#define strlen  lstrlen
+
+#define MAKEINTRESOURCE(i)  (LPTSTR) ((DWORD) ((WORD) (i)))
+//#define MAKEINTRESOURCEA(i)  (LPTSTR) ((DWORD) ((WORD) (i)))
+//#define MAKEINTRESOURCEW(i)  (LPTSTR) ((DWORD) ((WORD) (i)))
+
+#define MAKEINTRESOURCEA(i) (LPSTR)((ULONG_PTR)((WORD)(i)))
+#define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG_PTR)((WORD)(i)))
+//#define MAKEINTRESOURCE WINELIB_NAME_AW(MAKEINTRESOURCE)
+
+
+
+int HEAP_strdupWtoA(HANDLE hHeap, int flags, LPWSTR lpSource)
+{
+    return 0;
+}
+
+/* INTERNAL */
+
+//#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+//#include "windef.h"
+//#include "winbase.h"
+//#include "winerror.h"
+//#include "winuser.h"
+//#include "winnls.h"
+//#include "wine/unicode.h"
+//#include "heap.h"
+//#include "wine/debug.h"
+
+//WINE_DEFAULT_DEBUG_CHANNEL(resource);
+
+typedef struct tagMESSAGE_RESOURCE_ENTRY {
+        WORD    Length;
+        WORD    Flags;
+        BYTE    Text[1];
+} MESSAGE_RESOURCE_ENTRY,*PMESSAGE_RESOURCE_ENTRY;
+#define MESSAGE_RESOURCE_UNICODE        0x0001
+
+typedef struct tagMESSAGE_RESOURCE_BLOCK {
+        DWORD   LowId;
+        DWORD   HighId;
+        DWORD   OffsetToEntries;
+} MESSAGE_RESOURCE_BLOCK,*PMESSAGE_RESOURCE_BLOCK;
+
+typedef struct tagMESSAGE_RESOURCE_DATA {
+        DWORD                   NumberOfBlocks;
+        MESSAGE_RESOURCE_BLOCK  Blocks[ 1 ];
+} MESSAGE_RESOURCE_DATA,*PMESSAGE_RESOURCE_DATA;
+
+
+//#define RT_RCDATAA         MAKEINTRESOURCEA(10)
+//#define RT_RCDATAW         MAKEINTRESOURCEW(10)
+////#define RT_RCDATA            WINELIB_NAME_AW(RT_RCDATA)
+//#define RT_MESSAGETABLEA   MAKEINTRESOURCEA(11)
+#define RT_MESSAGETABLEW   MAKEINTRESOURCEW(11)
+////#define RT_MESSAGETABLE       WINELIB_NAME_AW(RT_MESSAGETABLE)
+
+/* Messages...used by FormatMessage32* (KERNEL32.something)
+ *
+ * They can be specified either directly or using a message ID and
+ * loading them from the resource.
+ *
+ * The resourcedata has following format:
+ * start:
+ * 0: DWORD nrofentries
+ * nrofentries * subentry:
+ *      0: DWORD firstentry
+ *      4: DWORD lastentry
+ *      8: DWORD offset from start to the stringentries
+ *
+ * (lastentry-firstentry) * stringentry:
+ * 0: WORD len (0 marks end)    [ includes the 4 byte header length ]
+ * 2: WORD flags
+ * 4: CHAR[len-4]
+ *      (stringentry i of a subentry refers to the ID 'firstentry+i')
+ *
+ * Yes, ANSI strings in win32 resources. Go figure.
+ */
+
+/**********************************************************************
+ *      load_messageA           (internal)
+ */
+static INT load_messageA( HMODULE instance, UINT id, WORD lang,
+                          LPSTR buffer, INT buflen )
+{
+    HGLOBAL     hmem;
+    HRSRC       hrsrc;
+    PMESSAGE_RESOURCE_DATA      mrd;
+    PMESSAGE_RESOURCE_BLOCK     mrb;
+    PMESSAGE_RESOURCE_ENTRY     mre;
+    int         i,slen;
+
+    //TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
+
+    /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
+    hrsrc = FindResourceExW(instance,RT_MESSAGETABLEW,(LPWSTR)1,lang);
+    if (!hrsrc) return 0;
+    hmem = LoadResource( instance, hrsrc );
+    if (!hmem) return 0;
+
+    mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
+    mre = NULL;
+    mrb = &(mrd->Blocks[0]);
+    for (i=mrd->NumberOfBlocks;i--;) {
+        if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
+            mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
+            id  -= mrb->LowId;
+            break;
+        }
+        mrb++;
+    }
+    if (!mre)
+        return 0;
+    for (i=id;i--;) {
+        if (!mre->Length)
+                return 0;
+        mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+mre->Length);
+    }
+    slen=mre->Length;
+    //TRACE("  - strlen=%d\n",slen);
+    i = min(buflen - 1, slen);
+    if (buffer == NULL)
+        return slen;
+    if (i>0) {
+        if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
+            WideCharToMultiByte( CP_ACP, 0, (LPWSTR)mre->Text, -1, buffer, i, NULL, NULL );
+        else
+            lstrcpynA(buffer, (LPSTR)mre->Text, i);
+        buffer[i]=0;
+    } else {
+        if (buflen>1) {
+            buffer[0]=0;
+            return 0;
+        }
+    }
+    if (buffer) {
+        //TRACE("'%s' copied !\n", buffer);
+        TRACE("'%s'\n", buffer);
+    }
+    return i;
+}
+
+#if 0  /* FIXME */
+/**********************************************************************
+ *      load_messageW   (internal)
+ */
+static INT load_messageW( HMODULE instance, UINT id, WORD lang,
+                          LPWSTR buffer, INT buflen )
+{
+    INT retval;
+    LPSTR buffer2 = NULL;
+    if (buffer && buflen)
+        buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
+    retval = load_messageA(instance,id,lang,buffer2,buflen);
+    if (buffer)
+    {
+        if (retval) {
+            lstrcpynAtoW( buffer, buffer2, buflen );
+            retval = strlenW( buffer );
+        }
+        HeapFree( GetProcessHeap(), 0, buffer2 );
+    }
+    return retval;
+}
+#endif
+
+
+/***********************************************************************
+ *           FormatMessageA   (KERNEL32.@)
+ * FIXME: missing wrap,
+ */
+DWORD WINAPI FormatMessageA(
+        DWORD   dwFlags,
+        LPCVOID lpSource,
+        DWORD   dwMessageId,
+        DWORD   dwLanguageId,
+        LPSTR   lpBuffer,
+        DWORD   nSize,
+        va_list* _args )
+{
+    LPDWORD args=(LPDWORD)_args;
+#if defined(__i386__) || defined(__sparc__)
+/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
+    LPSTR       target,t;
+    DWORD       talloced;
+    LPSTR       from,f;
+    DWORD       width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
+    BOOL    eos = FALSE;
+    INT bufsize;
+    HMODULE     hmodule = (HMODULE)lpSource;
+    CHAR        ch;
+
+    //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
+    if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
+        &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
+           || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
+
+    if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
+        FIXME("line wrapping (%lu) not supported.\n", width);
+    from = NULL;
+    if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
+    {
+        from = HeapAlloc( GetProcessHeap(), 0, strlen((LPSTR)lpSource)+1 );
+        strcpy( from, (LPSTR)lpSource );
+    }
+    else {
+        bufsize = 0;
+
+        if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
+        {
+           bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+           if ((!bufsize) && (!dwLanguageId)) {
+                bufsize=load_messageA(hmodule,dwMessageId,
+                                      MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+            }
+        }
+        if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
+        {
+           hmodule = GetModuleHandleA("kernel32");
+           bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+           if ((!bufsize) && (!dwLanguageId)) {
+                bufsize=load_messageA(hmodule,dwMessageId,
+                                      MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+            }
+        }
+
+        if (!bufsize) {
+            SetLastError (ERROR_RESOURCE_LANG_NOT_FOUND);
+            return 0;
+        }
+        from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
+        load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
+    }
+    target      = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
+    t   = target;
+    talloced= 100;
+
+#define ADD_TO_T(c) do { \
+        *t++=c;\
+        if (t-target == talloced) {\
+            target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
+            t = target+talloced;\
+            talloced*=2;\
+      }\
+} while (0)
+
+    if (from) {
+        f=from;
+        if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
+            while (*f && !eos)
+                ADD_TO_T(*f++);
+        }
+        else {
+            while (*f && !eos) {
+                if (*f=='%') {
+                    int insertnr;
+                    char *fmtstr,*x,*lastf;
+                    DWORD *argliststart;
+
+                    fmtstr = NULL;
+                    lastf = f;
+                    f++;
+                    if (!*f) {
+                        ADD_TO_T('%');
+                        continue;
+                    }
+                    switch (*f) {
+                    case '1':case '2':case '3':case '4':case '5':
+                    case '6':case '7':case '8':case '9':
+                        insertnr=*f-'0';
+                        switch (f[1]) {
+                        case '0':case '1':case '2':case '3':
+                        case '4':case '5':case '6':case '7':
+                        case '8':case '9':
+                            f++;
+                            insertnr=insertnr*10+*f-'0';
+                            f++;
+                            break;
+                        default:
+                            f++;
+                            break;
+                        }
+                        if (*f=='!') {
+                            f++;
+                            if (NULL!=(x=strchr(f,'!'))) {
+                                *x='\0';
+                                fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
+                                sprintf(fmtstr,"%%%s",f);
+                                f=x+1;
+                            } else {
+                                fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
+                                sprintf(fmtstr,"%%%s",f);
+                                f+=strlen(f); /*at \0*/
+                            }
+                        } else {
+                            if(!args) break;
+                            fmtstr = HeapAlloc(GetProcessHeap(),0,3);
+                            strcpy( fmtstr, "%s" );
+                        }
+                        if (args) {
+                            int sz;
+                            LPSTR b;
+
+                            if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
+                                argliststart=args+insertnr-1;
+                            else
+                                argliststart=(*(DWORD**)args)+insertnr-1;
+
+                                /* FIXME: precision and width components are not handled correctly */
+                            if ( (strcmp(fmtstr, "%ls") == 0) || (strcmp(fmtstr,"%S") == 0) ) {
+                                sz = WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, NULL, 0, NULL, NULL);
+                                b = HeapAlloc(GetProcessHeap(), 0, sz);
+                                WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, b, sz, NULL, NULL);
+                            } else {
+                                b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 1000);
+                                /* CMF - This makes a BIG assumption about va_list */
+                                TRACE("A BIG assumption\n");
+                                //vsnprintf(b, sz, fmtstr, (va_list) argliststart);
+                            }
+                            for (x=b; *x; x++) ADD_TO_T(*x);
+
+                            HeapFree(GetProcessHeap(),0,b);
+                        } else {
+                                /* NULL args - copy formatstr
+                                 * (probably wrong)
+                                 */
+                            while ((lastf<f)&&(*lastf)) {
+                                ADD_TO_T(*lastf++);
+                            }
+                        }
+                        HeapFree(GetProcessHeap(),0,fmtstr);
+                        break;
+                    case 'n':
+                        ADD_TO_T('\r');
+                        ADD_TO_T('\n');
+                        f++;
+                        break;
+                    case '0':
+                        eos = TRUE;
+                        f++;
+                        break;
+                    default:
+                        ADD_TO_T(*f++);
+                        break;
+                    }
+                } else {
+                    ch = *f;
+                    f++;
+                    if (ch == '\r') {
+                        if (*f == '\n')
+                            f++;
+                        if(width)
+                            ADD_TO_T(' ');
+                        else
+                        {
+                            ADD_TO_T('\r');
+                            ADD_TO_T('\n');
+                        }
+                    } else {
+                        if (ch == '\n')
+                        {
+                            if(width)
+                                ADD_TO_T(' ');
+                            else
+                            {
+                                ADD_TO_T('\r');
+                                ADD_TO_T('\n');
+                            }
+                        }
+                        else
+                            ADD_TO_T(ch);
+                    }
+                }
+            }
+        }
+        *t='\0';
+    }
+    talloced = strlen(target)+1;
+    if (nSize && talloced<nSize) {
+        target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
+    }
+    //TRACE("-- %s\n",debugstr_a(target));
+    if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+        *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,max(nSize, talloced));
+        memcpy(*(LPSTR*)lpBuffer,target,talloced);
+    } else {
+        lstrcpynA(lpBuffer,target,nSize);
+    }
+    HeapFree(GetProcessHeap(),0,target);
+    if (from) HeapFree(GetProcessHeap(),0,from);
+    //TRACE("-- returning %d\n", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?  strlen(*(LPSTR*)lpBuffer):strlen(lpBuffer));
+    return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
+        strlen(*(LPSTR*)lpBuffer):
+            strlen(lpBuffer);
+#else
+    return 0;
+#endif /* __i386__ */
+}
+#undef ADD_TO_T
+
+
+/***********************************************************************
+ *           FormatMessageW   (KERNEL32.@)
+ */
+DWORD WINAPI FormatMessageW(
+        DWORD   dwFlags,
+        LPCVOID lpSource,
+        DWORD   dwMessageId,
+        DWORD   dwLanguageId,
+        LPWSTR  lpBuffer,
+        DWORD   nSize,
+        va_list* _args)
+{
+    LPDWORD args=(LPDWORD)_args;
+#if defined(__i386__) || defined(__sparc__)
+/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
+    LPSTR target,t;
+    DWORD talloced;
+    LPSTR from,f;
+    DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
+    BOOL eos = FALSE;
+    INT bufsize;
+    HMODULE hmodule = (HMODULE)lpSource;
+    CHAR ch;
+
+    //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
+    if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
+        &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
+           || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
+
+    if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) {
+        FIXME("line wrapping not supported.\n");
+    }
+    from = NULL;
+    if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
+        from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
+    }
+    else {
+        bufsize = 0;
+
+        if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
+        {
+           bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+           if ((!bufsize) && (!dwLanguageId)) {
+                bufsize=load_messageA(hmodule,dwMessageId,
+                                      MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+            }
+        }
+        if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
+        {
+           hmodule = GetModuleHandleA("kernel32");
+           bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+           if ((!bufsize) && (!dwLanguageId)) {
+                bufsize=load_messageA(hmodule,dwMessageId,
+                                      MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+                if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+                                                    MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+            }
+        }
+
+        if (!bufsize) {
+            SetLastError (ERROR_RESOURCE_LANG_NOT_FOUND);
+            return 0;
+        }
+        from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
+        load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
+    }
+    target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
+    t = target;
+    talloced= 100;
+
+#define ADD_TO_T(c)  do {\
+    *t++=c;\
+    if (t-target == talloced) {\
+        target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
+        t = target+talloced;\
+        talloced*=2;\
+    } \
+} while (0)
+
+    if (from) {
+        f=from;
+        if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
+            while (*f && !eos)
+                ADD_TO_T(*f++);
+        }
+        else {
+            while (*f && !eos) {
+                if (*f=='%') {
+                    int insertnr;
+                    char *fmtstr,*sprintfbuf,*x;
+                    DWORD *argliststart;
+
+                    fmtstr = NULL;
+                    f++;
+                    if (!*f) {
+                        ADD_TO_T('%');
+                        continue;
+                    }
+
+                    switch (*f) {
+                    case '1':case '2':case '3':case '4':case '5':
+                    case '6':case '7':case '8':case '9':
+                        insertnr=*f-'0';
+                        switch (f[1]) {
+                        case '0':case '1':case '2':case '3':
+                        case '4':case '5':case '6':case '7':
+                        case '8':case '9':
+                            f++;
+                            insertnr=insertnr*10+*f-'0';
+                            f++;
+                            break;
+                        default:
+                            f++;
+                            break;
+                        }
+                        if (*f=='!') {
+                            f++;
+                            if (NULL!=(x=strchr(f,'!'))) {
+                                *x='\0';
+                                fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
+                                sprintf(fmtstr,"%%%s",f);
+                                f=x+1;
+                            } else {
+                                fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
+                                sprintf(fmtstr,"%%%s",f);
+                                f+=strlen(f); /*at \0*/
+                            }
+                        } else {
+                            if(!args) break;
+                            fmtstr = HeapAlloc( GetProcessHeap(),0,3);
+                            strcpy( fmtstr, "%s" );
+                        }
+                        if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
+                            argliststart=args+insertnr-1;
+                        else
+                            argliststart=(*(DWORD**)args)+insertnr-1;
+
+                        if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) {
+                            DWORD xarr[3];
+
+                            xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
+                            /* possible invalid pointers */
+                            xarr[1]=*(argliststart+1);
+                            xarr[2]=*(argliststart+2);
+                            sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlenW((LPWSTR)argliststart[0])*2+1);
+
+                            /* CMF - This makes a BIG assumption about va_list */
+                            vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
+                            HeapFree(GetProcessHeap(), 0, (LPVOID) xarr[0]);
+                        } else {
+                            sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
+
+                            /* CMF - This makes a BIG assumption about va_list */
+                            vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
+                        }
+                        x=sprintfbuf;
+                        while (*x) {
+                            ADD_TO_T(*x++);
+                        }
+                        HeapFree(GetProcessHeap(),0,sprintfbuf);
+                        HeapFree(GetProcessHeap(),0,fmtstr);
+                        break;
+                    case 'n':
+                        ADD_TO_T('\r');
+                        ADD_TO_T('\n');
+                        f++;
+                        break;
+                    case '0':
+                        eos = TRUE;
+                        f++;
+                        break;
+                    default:
+                        ADD_TO_T(*f++);
+                        break;
+                    }
+                } else {
+                    ch = *f;
+                    f++;
+                    if (ch == '\r') {
+                        if (*f == '\n')
+                            f++;
+                        if(width)
+                            ADD_TO_T(' ');
+                        else
+                        {
+                            ADD_TO_T('\r');
+                            ADD_TO_T('\n');
+                        }
+                    } else {
+                        if (ch == '\n')
+                        {
+                            if(width)
+                                ADD_TO_T(' ');
+                            else
+                            {
+                                ADD_TO_T('\r');
+                                ADD_TO_T('\n');
+                            }
+                        }
+                        else
+                            ADD_TO_T(ch);
+                    }
+                }
+            }
+        }
+        *t='\0';
+    }
+    talloced = strlen(target)+1;
+    if (nSize && talloced<nSize)
+        target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
+    if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+        /* nSize is the MINIMUM size */
+        DWORD len = MultiByteToWideChar( CP_ACP, 0, target, -1, NULL, 0 );
+        *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,len*sizeof(WCHAR));
+        MultiByteToWideChar( CP_ACP, 0, target, -1, *(LPWSTR*)lpBuffer, len );
+    }
+    else
+    {
+        if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, target, -1, lpBuffer, nSize ))
+            lpBuffer[nSize-1] = 0;
+    }
+    HeapFree(GetProcessHeap(),0,target);
+    if (from) HeapFree(GetProcessHeap(),0,from);
+    return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
+        strlenW(*(LPWSTR*)lpBuffer):
+            strlenW(lpBuffer);
+#else
+    return 0;
+#endif /* __i386__ */
+}
+#undef ADD_TO_T
+
+
+#else
+
+/* EXPORTED */
+
+DWORD
+STDCALL
+FormatMessageW(
+    DWORD    dwFlags,
+    LPCVOID  lpSource,
+    DWORD    dwMessageId,
+    DWORD    dwLanguageId,
+    LPWSTR   lpBuffer,
+    DWORD    nSize,
+    va_list* Arguments)
+{
+
+// RtlFormatMessage
+
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+
+DWORD
+STDCALL
+FormatMessageA(
+    DWORD    dwFlags,
+    LPCVOID  lpSource,
+    DWORD    dwMessageId,
+    DWORD    dwLanguageId,
+    LPSTR    lpBuffer,
+    DWORD    nSize,
+    va_list* Arguments)
+{
+    HLOCAL pBuf = NULL;
+    //LPSTR pBuf = NULL;
+
+#define MAX_MSG_STR_LEN 200
+
+    if (lpBuffer != NULL) {
+
+        if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+            pBuf = LocalAlloc(LPTR, max(nSize, MAX_MSG_STR_LEN));
+            if (pBuf == NULL) {
+                return 0;
+            }
+            *(LPSTR*)lpBuffer = pBuf;
+        } else {
+            pBuf = *(LPSTR*)lpBuffer;
+        }
+
+        if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
+        } else {
+        }
+
+//FORMAT_MESSAGE_IGNORE_INSERTS
+//FORMAT_MESSAGE_FROM_STRING
+//FORMAT_MESSAGE_FROM_HMODULE
+//FORMAT_MESSAGE_FROM_SYSTEM
+//FORMAT_MESSAGE_ARGUMENT_ARRAY 
+
+    }
+/*
+        if (FormatMessage(
+          FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+          0,
+          error,
+          MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+          (PTSTR)&msg,
+          0,
+          NULL)
+        )
+ */
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+#endif
+
+/* EOF */
diff --git a/lib/kernel32/misc/getname.c b/lib/kernel32/misc/getname.c
new file mode 100644 (file)
index 0000000..f016af5
--- /dev/null
@@ -0,0 +1,49 @@
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+WINBOOL
+STDCALL
+GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize)
+{
+    WCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
+    DWORD Size = 0;
+
+    /*
+     * FIXME: get the computer's name from the registry.
+     */
+    lstrcpyW(Name, L"ROSHost"); /* <-- FIXME -- */
+    Size = lstrlenW(Name) + 1;
+    if (Size > *nSize) {
+        *nSize = Size;
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        return FALSE;
+    }
+    lstrcpyW(lpBuffer, Name);
+    return TRUE;
+}
+
+
+WINBOOL
+STDCALL
+GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)
+{
+    WCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
+    int i;
+
+    if (FALSE == GetComputerNameW(Name, nSize)) {
+        return FALSE;
+    }
+
+/* FIXME --> */
+/* Use UNICODE to ANSI */
+    for (i = 0; Name[i]; ++i) {
+        lpBuffer[i] = (CHAR)Name[i];
+    }
+    lpBuffer[i] = '\0';
+/* FIXME <-- */
+
+    return TRUE;
+}
diff --git a/lib/kernel32/misc/mbchars.c b/lib/kernel32/misc/mbchars.c
new file mode 100644 (file)
index 0000000..32e5135
--- /dev/null
@@ -0,0 +1,302 @@
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+/**********************************************************************
+ * NAME                         PRIVATE
+ *  IsInstalledCP@4
+ *
+ * RETURN VALUE
+ *  TRUE if CodePage is installed in the system.
+ */
+static
+BOOL
+STDCALL
+IsInstalledCP(UINT CodePage)
+{
+    /* FIXME */
+    return TRUE;
+}
+
+
+/**********************************************************************
+ * NAME                         EXPORTED
+ *  MultiByteToWideChar@24
+ *
+ * ARGUMENTS
+ *  CodePage
+ *      CP_ACP      ANSI code page
+ *      CP_MACCP    Macintosh code page
+ *      CP_OEMCP    OEM code page
+ *      (UINT)      Any installed code page
+ *
+ *  dwFlags
+ *      MB_PRECOMPOSED
+ *      MB_COMPOSITE
+ *      MB_ERR_INVALID_CHARS
+ *      MB_USEGLYPHCHARS
+ *
+ *  lpMultiByteStr
+ *      Input buffer;
+ *
+ *  cchMultiByte
+ *      Size of MultiByteStr, or -1 if MultiByteStr is
+ *      NULL terminated;
+ *
+ *  lpWideCharStr
+ *      Output buffer;
+ *
+ *  cchWideChar
+ *      Size (in WCHAR unit) of WideCharStr, or 0
+ *      if the caller just wants to know how large
+ *      WideCharStr should be for a successful
+ *      conversion.
+ *
+ * RETURN VALUE
+ *  0 on error; otherwise the number of WCHAR written
+ *  in the WideCharStr buffer.
+ *
+ * NOTE
+ *  A raw converter for now. It assumes lpMultiByteStr is
+ *  NEVER multi-byte (that is each input character is
+ *  8-bit ASCII) and is ALWAYS NULL terminated.
+ *  FIXME-FIXME-FIXME-FIXME
+ */
+INT
+STDCALL
+MultiByteToWideChar(
+    UINT    CodePage,
+    DWORD   dwFlags,
+    LPCSTR  lpMultiByteStr,
+    int     cchMultiByte,
+    LPWSTR  lpWideCharStr,
+    int     cchWideChar)
+{
+    int InStringLength = 0;
+    PCHAR   r;
+    PWCHAR  w;
+    int cchConverted;
+
+    /*
+     * Check the parameters.
+     */
+    if (/* --- CODE PAGE --- */
+        (  (CP_ACP != CodePage)
+                && (CP_MACCP != CodePage)
+                && (CP_OEMCP != CodePage)
+                && (FALSE == IsInstalledCP(CodePage)) )
+        /* --- FLAGS --- */
+        || (dwFlags & ~(MB_PRECOMPOSED | MB_COMPOSITE |
+                        MB_ERR_INVALID_CHARS | MB_USEGLYPHCHARS))
+        /* --- INPUT BUFFER --- */
+        || (NULL == lpMultiByteStr)  )
+    {
+        SetLastError (ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    /*
+     * Compute the input buffer length.
+     */
+    //if (-1 == cchMultiByte)
+    if (cchMultiByte < 0)
+    {
+        InStringLength = lstrlen(lpMultiByteStr) + 1;
+    }
+    else
+    {
+        InStringLength = cchMultiByte;
+    }
+    /*
+     * Does caller query for output
+     * buffer size?
+     */
+    if (0 == cchWideChar)
+    {
+        //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+        return InStringLength;
+    }
+    /*
+     * Is space provided for the translated
+     * string enough?
+     */
+    if (cchWideChar < InStringLength)
+    {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return 0;
+    }
+    /*
+     * Raw 8- to 16-bit conversion.
+     */
+    for (cchConverted = 0,
+        r = (PCHAR)lpMultiByteStr,
+        w = (PWCHAR)lpWideCharStr;
+
+        cchConverted < InStringLength;
+
+        r++,
+        w++,
+        cchConverted++)
+    {
+        *w = (WCHAR)*r;
+    }
+    /*
+     * Return how many characters we
+     * wrote in the output buffer.
+     */
+    //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+    return cchConverted;
+}
+
+
+/**********************************************************************
+ * NAME                         EXPORTED
+ *  WideCharToMultiByte@32
+ * 
+ *  Not yet implemented complete (without NLS so far)
+ *
+ * ARGUMENTS
+ *  CodePage
+ *      CP_ACP ANSI code page 
+ *      CP_MACCP Macintosh code page 
+ *      CP_OEMCP OEM code page 
+ *      CP_SYMBOL Symbol code page (42) 
+ *      CP_THREAD_ACP Current thread's ANSI code page 
+ *      CP_UTF7 Translate using UTF-7 
+ *      CP_UTF8 Translate using UTF-8 
+ *      (UINT)      Any installed code page
+ *
+ *  dwFlags
+ *      WC_NO_BEST_FIT_CHARS    
+ *      WC_COMPOSITECHECK Convert composite characters to precomposed characters. 
+ *      WC_DISCARDNS Discard nonspacing characters during conversion. 
+ *      WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior. 
+ *      WC_DEFAULTCHAR Replace exceptions with the default character during conversion. 
+ *
+ *  lpWideCharStr 
+ *      Points to the wide-character string to be converted. 
+ *
+ *  cchWideChar
+ *      Size (in WCHAR unit) of WideCharStr, or 0
+ *      if the caller just wants to know how large
+ *      WideCharStr should be for a successful
+ *      conversion.
+ *  lpMultiByteStr 
+ *      Points to the buffer to receive the translated string. 
+ *  cchMultiByte 
+ *      Specifies the size in bytes of the buffer pointed to by the 
+ *      lpMultiByteStr parameter. If this value is zero, the function 
+ *      returns the number of bytes required for the buffer. 
+ *  lpDefaultChar 
+ *      Points to the character used if a wide character cannot be 
+ *      represented in the specified code page. If this parameter is 
+ *      NULL, a system default value is used. 
+        FIXME: ignored
+ *  lpUsedDefaultChar 
+ *      Points to a flag that indicates whether a default character was used. 
+ *      This parameter may be NULL. 
+        FIXME: allways set to FALSE.
+ *
+ *
+ *
+ * RETURN VALUE
+ *  0 on error; otherwise the number of bytes written
+ *  in the lpMultiByteStr buffer. Or the number of
+ *  bytes needed for the lpMultiByteStr buffer if cchMultiByte is zero.
+ *
+ * NOTE
+ *  A raw converter for now. It just cuts off the upper 9 Bit.
+ *  So the MBCS-string does not contain any LeadCharacters
+ *  FIXME - FIXME - FIXME - FIXME
+ */
+
+int
+STDCALL
+WideCharToMultiByte(
+    UINT    CodePage,
+    DWORD   dwFlags,
+    LPCWSTR lpWideCharStr,
+    int     cchWideChar,
+    LPSTR   lpMultiByteStr,
+    int     cchMultiByte,
+    LPCSTR  lpDefaultChar,
+    LPBOOL  lpUsedDefaultChar
+    )
+{
+    int wi, di;  // wide counter, dbcs byte count
+
+    /*
+     * Check the parameters.
+     */
+    if (    /* --- CODE PAGE --- */
+        (   (CP_ACP != CodePage)
+            && (CP_MACCP != CodePage)
+            && (CP_OEMCP != CodePage)
+            && (CP_SYMBOL != CodePage)
+            && (CP_THREAD_ACP != CodePage)
+            && (CP_UTF7 != CodePage)
+            && (CP_UTF8 != CodePage)
+            && (FALSE == IsInstalledCP (CodePage))
+            )
+        /* --- FLAGS --- */
+        || (dwFlags & ~(/*WC_NO_BEST_FIT_CHARS
+                |*/ WC_COMPOSITECHECK
+                | WC_DISCARDNS
+                | WC_SEPCHARS
+                | WC_DEFAULTCHAR
+                )
+            )
+        /* --- INPUT BUFFER --- */
+        || (NULL == lpWideCharStr)
+        )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    // for now, make no difference but only convert cut the characters to 7Bit
+    //if (cchWideChar == -1) // assume its a 0-terminated str
+    if (cchWideChar < 0) // assume its a 0-terminated str
+    {           // and determine its length
+//        for (cchWideChar=0; lpWideCharStr[cchWideChar]!=0; cchWideChar++)
+//            cchWideChar++;
+        for (cchWideChar = 0; lpWideCharStr[cchWideChar] != 0; cchWideChar++) {
+        }
+        cchWideChar++; // length includes the null terminator
+    }
+
+    // user wants to determine needed space
+    if (cchMultiByte == 0) 
+    {
+        //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+        return cchWideChar;         // FIXME: determine correct.
+    }
+    // the lpWideCharStr is cchWideChar characters long.
+    for (wi=0, di=0; wi<cchWideChar && di<cchMultiByte; ++wi, ++di)
+    {
+        // Flag and a not displayable char    FIXME
+        /*if( (dwFlags&WC_NO_BEST_FIT_CHARS) && (lpWideCharStr[wi] >127) ) 
+        {
+            lpMultiByteStr[di]=
+            *lpUsedDefaultChar = TRUE;
+
+        }*/
+        // FIXME
+        // just cut off the upper 9 Bit, since vals>=128 mean LeadByte.
+        lpMultiByteStr[di] = lpWideCharStr[wi] & 0x007F;
+    }
+    // has MultiByte exceeded but Wide is still in the string?
+    if (wi < cchWideChar && di >= cchMultiByte)
+    {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return 0;
+    }
+    // else return # of bytes wirtten to MBCSbuffer (di)
+    //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+    // FIXME: move that elsewhere
+    if (lpUsedDefaultChar != NULL) *lpUsedDefaultChar = FALSE; 
+    return di;
+}
+
+/* EOF */
diff --git a/lib/kernel32/misc/muldiv.c b/lib/kernel32/misc/muldiv.c
new file mode 100644 (file)
index 0000000..3b9a559
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+/***********************************************************************
+ *           MulDiv   (KERNEL32.@)
+ * RETURNS
+ *      Result of multiplication and division
+ *      -1: Overflow occurred or Divisor was 0
+ */
+
+//FIXME! move to correct file
+INT STDCALL MulDiv(
+             INT nMultiplicand,
+             INT nMultiplier,
+             INT nDivisor)
+{
+#if SIZEOF_LONG_LONG >= 8
+    long long ret;
+
+    if (!nDivisor) return -1;
+
+    /* We want to deal with a positive divisor to simplify the logic. */
+    if (nDivisor < 0)
+    {
+      nMultiplicand = - nMultiplicand;
+      nDivisor = -nDivisor;
+    }
+
+    /* If the result is positive, we "add" to round. else, we subtract to round. */
+    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
+         ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+      ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+    else
+      ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
+    return ret;
+#else
+    if (!nDivisor) return -1;
+
+    /* We want to deal with a positive divisor to simplify the logic. */
+    if (nDivisor < 0)
+    {
+      nMultiplicand = - nMultiplicand;
+      nDivisor = -nDivisor;
+    }
+
+    /* If the result is positive, we "add" to round. else, we subtract to round. */
+    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
+         ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+      return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+
+    return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+#endif
+}
+
+
diff --git a/lib/kernel32/misc/perfcnt.c b/lib/kernel32/misc/perfcnt.c
new file mode 100644 (file)
index 0000000..c8bdaa4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$ */
+/*
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/kernel32/misc/perfcnt.c
+ * PURPOSE:         Performance counter
+ * PROGRAMMER:      Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <k32.h>
+
+#define NDEBUG
+#include <kernel32/kernel32.h>
+
+
+/* FUNCTIONS ****************************************************************/
+
+WINBOOL STDCALL
+QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
+{
+  LARGE_INTEGER Frequency;
+  NTSTATUS Status;
+
+  Status = NtQueryPerformanceCounter(lpPerformanceCount,
+                                    &Frequency);
+  if (!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return(FALSE);
+  }
+
+  if (Frequency.QuadPart == 0ULL)
+  {
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return(FALSE);
+  }
+
+  return(TRUE);
+}
+
+
+WINBOOL STDCALL
+QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
+{
+  LARGE_INTEGER Count;
+  NTSTATUS Status;
+
+  Status = NtQueryPerformanceCounter(&Count,
+                                    lpFrequency);
+  if (!NT_SUCCESS(Status))
+  {
+    SetLastErrorByStatus(Status);
+    return(FALSE);
+  }
+
+  if (lpFrequency->QuadPart == 0ULL)
+  {
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return(FALSE);
+  }
+
+  return(TRUE);
+}
+
+/* EOF */
diff --git a/lib/kernel32/misc/toolhelp.c b/lib/kernel32/misc/toolhelp.c
new file mode 100644 (file)
index 0000000..30417de
--- /dev/null
@@ -0,0 +1,317 @@
+/* $Id$
+ *
+ * KERNEL32.DLL toolhelp functions
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/kernel32/misc/toolhelp.c
+ * PURPOSE:         Toolhelp functions
+ * PROGRAMMER:      Robert Dickenson (robd@mok.lvcm.com)
+ * UPDATE HISTORY:
+ *                  Created 05 January 2003
+ */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+
+#define CHECK_PARAM_SIZE(ptr, siz) \
+    if (!ptr || ptr->dwSize != siz) { \
+        SetLastError(ERROR_INVALID_PARAMETER); \
+        return FALSE; \
+    }
+
+
+BOOL WINAPI
+Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
+{
+    CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Heap32Next(LPHEAPENTRY32 lphe)
+{
+/*
+typedef struct tagHEAPENTRY32 {
+       DWORD dwSize;
+       HANDLE hHandle;
+       DWORD dwAddress;
+       DWORD dwBlockSize;
+       DWORD dwFlags;
+       DWORD dwLockCount;
+       DWORD dwResvd;
+       DWORD th32ProcessID;
+       DWORD th32HeapID;
+} HEAPENTRY32,*PHEAPENTRY32,*LPHEAPENTRY32;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
+{
+    CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lph1)
+{
+/*
+typedef struct tagHEAPLIST32 {
+       DWORD dwSize;
+       DWORD th32ProcessID;
+       DWORD th32HeapID;
+       DWORD dwFlags;
+} HEAPLIST32,*PHEAPLIST32,*LPHEAPLIST32;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
+{
+    CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+    CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
+{
+/*
+typedef struct tagMODULEENTRY32 {
+       DWORD dwSize;
+       DWORD th32ModuleID;
+       DWORD th32ProcessID;
+       DWORD GlblcntUsage;
+       DWORD ProccntUsage;
+       BYTE *modBaseAddr;
+       DWORD modBaseSize;
+       HMODULE hModule;
+       char szModule[MAX_MODULE_NAME32 + 1];
+       char szExePath[MAX_PATH];
+} MODULEENTRY32,*PMODULEENTRY32,*LPMODULEENTRY32;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+/*
+typedef struct tagMODULEENTRY32W {
+       DWORD dwSize;
+       DWORD th32ModuleID;
+       DWORD th32ProcessID;
+       DWORD GlblcntUsage;
+       DWORD ProccntUsage;
+       BYTE *modBaseAddr;
+       DWORD modBaseSize;
+       HMODULE hModule; 
+       WCHAR szModule[MAX_MODULE_NAME32 + 1];
+       WCHAR szExePath[MAX_PATH];
+} MODULEENTRY32W,*PMODULEENTRY32W,*LPMODULEENTRY32W;
+
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL STDCALL
+Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
+{
+    CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL STDCALL
+Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
+{
+/*
+typedef struct tagPROCESSENTRY32 {
+       DWORD dwSize;
+       DWORD cntUsage;
+       DWORD th32ProcessID;
+       DWORD th32DefaultHeapID;
+       DWORD th32ModuleID;
+       DWORD cntThreads;
+       DWORD th32ParentProcessID;
+       LONG pcPriClassBase;
+       DWORD dwFlags;
+       CHAR  szExeFile[MAX_PATH];
+} PROCESSENTRY32,*PPROCESSENTRY32,*LPPROCESSENTRY32;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL STDCALL
+Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
+{
+    CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL STDCALL
+Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
+{
+/*
+typedef struct tagPROCESSENTRY32W {
+       DWORD dwSize;
+       DWORD cntUsage;
+       DWORD th32ProcessID;
+       DWORD th32DefaultHeapID;
+       DWORD th32ModuleID;
+       DWORD cntThreads;
+       DWORD th32ParentProcessID;
+       LONG pcPriClassBase;
+       DWORD dwFlags;
+       WCHAR szExeFile[MAX_PATH];
+} PROCESSENTRY32W,*PPROCESSENTRY32W,*LPPROCESSENTRY32W;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+
+BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+{
+    CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
+
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+{
+/*
+typedef struct tagTHREADENTRY32 {
+       DWORD dwSize;
+       DWORD cntUsage;
+       DWORD th32ThreadID;
+       DWORD th32OwnerProcessID;
+       LONG tpBasePri;
+       LONG tpDeltaPri;
+       DWORD dwFlags;
+} THREADENTRY32,*PTHREADENTRY32,*LPTHREADENTRY32;
+ */
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+BOOL WINAPI
+Toolhelp32ReadProcessMemory(DWORD th32ProcessID,
+  LPCVOID lpBaseAddress, LPVOID lpBuffer,
+  DWORD cbRead, LPDWORD lpNumberOfBytesRead)
+{
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+#define TL_DEV_NAME L"\\??\\TlHelpDevice"
+
+HANDLE STDCALL
+CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
+{
+    // return open handle to snapshot on success, -1 on failure
+    // the snapshot handle behavies like an object handle
+    SECURITY_ATTRIBUTES sa;
+    HANDLE hSnapshot = (HANDLE)-1;
+
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+
+    if (dwFlags & TH32CS_INHERIT) {
+    }
+    if (dwFlags & TH32CS_SNAPHEAPLIST) {
+    }
+    if (dwFlags & TH32CS_SNAPMODULE) {
+    }
+    if (dwFlags & TH32CS_SNAPPROCESS) {
+    }
+    if (dwFlags & TH32CS_SNAPTHREAD) {
+    }
+    hSnapshot = CreateFileW(TL_DEV_NAME,
+                           GENERIC_READ, FILE_SHARE_READ + FILE_SHARE_WRITE,
+                           &sa, OPEN_EXISTING, 0L/*FILE_ATTRIBUTE_SYSTEM*/, 0);
+    if (hSnapshot != INVALID_HANDLE_VALUE) {
+
+    }
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+
+    // caller must use CloseHandle to destroy the returned snapshot handle
+    return hSnapshot;
+}
+
+
+#if 0 /* extracted from mingw tlhelp32.h for easy reference while working above */
+/*
+#define HF32_DEFAULT   1
+#define HF32_SHARED    2
+#define LF32_FIXED     0x1
+#define LF32_FREE      0x2
+#define LF32_MOVEABLE  0x4
+#define MAX_MODULE_NAME32      255
+#define TH32CS_SNAPHEAPLIST    0x1
+#define TH32CS_SNAPPROCESS     0x2
+#define TH32CS_SNAPTHREAD      0x4
+#define TH32CS_SNAPMODULE      0x8
+#define TH32CS_SNAPALL (TH32CS_SNAPHEAPLIST|TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)
+#define TH32CS_INHERIT 0x80000000
+
+BOOL WINAPI Heap32First(LPHEAPENTRY32,DWORD,DWORD);
+BOOL WINAPI Heap32ListFirst(HANDLE,LPHEAPLIST32);
+BOOL WINAPI Heap32ListNext(HANDLE,LPHEAPLIST32);
+BOOL WINAPI Heap32Next(LPHEAPENTRY32);
+BOOL WINAPI Module32First(HANDLE,LPMODULEENTRY32);
+BOOL WINAPI Module32FirstW(HANDLE,LPMODULEENTRY32W);
+BOOL WINAPI Module32Next(HANDLE,LPMODULEENTRY32);
+BOOL WINAPI Module32NextW(HANDLE,LPMODULEENTRY32W);
+BOOL WINAPI Process32First(HANDLE,LPPROCESSENTRY32);
+BOOL WINAPI Process32FirstW(HANDLE,LPPROCESSENTRY32W);
+BOOL WINAPI Process32Next(HANDLE,LPPROCESSENTRY32);
+BOOL WINAPI Process32NextW(HANDLE,LPPROCESSENTRY32W);
+BOOL WINAPI Thread32First(HANDLE,LPTHREADENTRY32);
+BOOL WINAPI Thread32Next(HANDLE,LPTHREADENTRY32);
+BOOL WINAPI Toolhelp32ReadProcessMemory(DWORD,LPCVOID,LPVOID,DWORD,LPDWORD);
+HANDLE WINAPI CreateToolhelp32Snapshot(DWORD,DWORD);
+
+#ifdef UNICODE
+#define LPMODULEENTRY32 LPMODULEENTRY32W
+#define LPPROCESSENTRY32 LPPROCESSENTRY32W
+#define MODULEENTRY32 MODULEENTRY32W
+#define Module32First Module32FirstW
+#define Module32Next Module32NextW
+#define PMODULEENTRY32 PMODULEENTRY32W
+#define PPROCESSENTRY32 PPROCESSENTRY32W
+#define PROCESSENTRY32 PROCESSENTRY32W
+#define Process32First Process32FirstW
+#define Process32Next Process32NextW
+#endif // UNICODE
+ */
+#endif /* 0 */
+
+/* EOF */
diff --git a/lib/msafd/misc/.cvsignore b/lib/msafd/misc/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/msvcrt/ctype/ctype.c b/lib/msvcrt/ctype/ctype.c
new file mode 100644 (file)
index 0000000..5861d6d
--- /dev/null
@@ -0,0 +1,264 @@
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/ctype.h>
+
+unsigned short _ctype[] = {
+       0,                      /* <EOF>, 0xFFFF */
+       _CONTROL,               /* CTRL+@, 0x00 */
+       _CONTROL,               /* CTRL+A, 0x01 */
+       _CONTROL,               /* CTRL+B, 0x02 */
+       _CONTROL,               /* CTRL+C, 0x03 */
+       _CONTROL,               /* CTRL+D, 0x04 */
+       _CONTROL,               /* CTRL+E, 0x05 */
+       _CONTROL,               /* CTRL+F, 0x06 */
+       _CONTROL,               /* CTRL+G, 0x07 */
+       _CONTROL,               /* CTRL+H, 0x08 */
+       _CONTROL | _SPACE,      /* CTRL+I, 0x09 */
+       _CONTROL | _SPACE,      /* CTRL+J, 0x0a */
+       _CONTROL | _SPACE,      /* CTRL+K, 0x0b */
+       _CONTROL | _SPACE,      /* CTRL+L, 0x0c */
+       _CONTROL | _SPACE,      /* CTRL+M, 0x0d */
+       _CONTROL,               /* CTRL+N, 0x0e */
+       _CONTROL,               /* CTRL+O, 0x0f */
+       _CONTROL,               /* CTRL+P, 0x10 */
+       _CONTROL,               /* CTRL+Q, 0x11 */
+       _CONTROL,               /* CTRL+R, 0x12 */
+       _CONTROL,               /* CTRL+S, 0x13 */
+       _CONTROL,               /* CTRL+T, 0x14 */
+       _CONTROL,               /* CTRL+U, 0x15 */
+       _CONTROL,               /* CTRL+V, 0x16 */
+       _CONTROL,               /* CTRL+W, 0x17 */
+       _CONTROL,               /* CTRL+X, 0x18 */
+       _CONTROL,               /* CTRL+Y, 0x19 */
+       _CONTROL,               /* CTRL+Z, 0x1a */
+       _CONTROL,               /* CTRL+[, 0x1b */
+       _CONTROL,               /* CTRL+\, 0x1c */
+       _CONTROL,               /* CTRL+], 0x1d */
+       _CONTROL,               /* CTRL+^, 0x1e */
+       _CONTROL,               /* CTRL+_, 0x1f */
+       _SPACE | _BLANK,        /* ` ', 0x20 */
+       _PUNCT,                 /* `!', 0x21 */
+       _PUNCT,                 /* 0x22 */
+       _PUNCT,                 /* `#', 0x23 */
+       _PUNCT,                 /* `$', 0x24 */
+       _PUNCT,                 /* `%', 0x25 */
+       _PUNCT,                 /* `&', 0x26 */
+       _PUNCT,                 /* 0x27 */
+       _PUNCT,                 /* `(', 0x28 */
+       _PUNCT,                 /* `)', 0x29 */
+       _PUNCT,                 /* `*', 0x2a */
+       _PUNCT,                 /* `+', 0x2b */
+       _PUNCT,                 /* `,', 0x2c */
+       _PUNCT,                 /* `-', 0x2d */
+       _PUNCT,                 /* `.', 0x2e */
+       _PUNCT,                 /* `/', 0x2f */
+       _DIGIT | _HEX,          /* `0', 0x30 */
+       _DIGIT | _HEX,          /* `1', 0x31 */
+       _DIGIT | _HEX,          /* `2', 0x32 */
+       _DIGIT | _HEX,          /* `3', 0x33 */
+       _DIGIT | _HEX,          /* `4', 0x34 */
+       _DIGIT | _HEX,          /* `5', 0x35 */
+       _DIGIT | _HEX,          /* `6', 0x36 */
+       _DIGIT | _HEX,          /* `7', 0x37 */
+       _DIGIT | _HEX,          /* `8', 0x38 */
+       _DIGIT | _HEX,          /* `9', 0x39 */
+       _PUNCT,                 /* `:', 0x3a */
+       _PUNCT,                 /* `;', 0x3b */
+       _PUNCT,                 /* `<', 0x3c */
+       _PUNCT,                 /* `=', 0x3d */
+       _PUNCT,                 /* `>', 0x3e */
+       _PUNCT,                 /* `?', 0x3f */
+       _PUNCT,                 /* `@', 0x40 */
+       _UPPER | _HEX,          /* `A', 0x41 */
+       _UPPER | _HEX,          /* `B', 0x42 */
+       _UPPER | _HEX,          /* `C', 0x43 */
+       _UPPER | _HEX,          /* `D', 0x44 */
+       _UPPER | _HEX,          /* `E', 0x45 */
+       _UPPER | _HEX,          /* `F', 0x46 */
+       _UPPER,                 /* `G', 0x47 */
+       _UPPER,                 /* `H', 0x48 */
+       _UPPER,                 /* `I', 0x49 */
+       _UPPER,                 /* `J', 0x4a */
+       _UPPER,                 /* `K', 0x4b */
+       _UPPER,                 /* `L', 0x4c */
+       _UPPER,                 /* `M', 0x4d */
+       _UPPER,                 /* `N', 0x4e */
+       _UPPER,                 /* `O', 0x4f */
+       _UPPER,                 /* `P', 0x50 */
+       _UPPER,                 /* `Q', 0x51 */
+       _UPPER,                 /* `R', 0x52 */
+       _UPPER,                 /* `S', 0x53 */
+       _UPPER,                 /* `T', 0x54 */
+       _UPPER,                 /* `U', 0x55 */
+       _UPPER,                 /* `V', 0x56 */
+       _UPPER,                 /* `W', 0x57 */
+       _UPPER,                 /* `X', 0x58 */
+       _UPPER,                 /* `Y', 0x59 */
+       _UPPER,                 /* `Z', 0x5a */
+       _PUNCT,                 /* `[', 0x5b */
+       _PUNCT,                 /* 0x5c */
+       _PUNCT,                 /* `]', 0x5d */
+       _PUNCT,                 /* `^', 0x5e */
+       _PUNCT,                 /* `_', 0x5f */
+       _PUNCT,                 /* 0x60 */
+       _LOWER | _HEX,          /* `a', 0x61 */
+       _LOWER | _HEX,          /* `b', 0x62 */
+       _LOWER | _HEX,          /* `c', 0x63 */
+       _LOWER | _HEX,          /* `d', 0x64 */
+       _LOWER | _HEX,          /* `e', 0x65 */
+       _LOWER | _HEX,          /* `f', 0x66 */
+       _LOWER,                 /* `g', 0x67 */
+       _LOWER,                 /* `h', 0x68 */
+       _LOWER,                 /* `i', 0x69 */
+       _LOWER,                 /* `j', 0x6a */
+       _LOWER,                 /* `k', 0x6b */
+       _LOWER,                 /* `l', 0x6c */
+       _LOWER,                 /* `m', 0x6d */
+       _LOWER,                 /* `n', 0x6e */
+       _LOWER,                 /* `o', 0x6f */
+       _LOWER,                 /* `p', 0x70 */
+       _LOWER,                 /* `q', 0x71 */
+       _LOWER,                 /* `r', 0x72 */
+       _LOWER,                 /* `s', 0x73 */
+       _LOWER,                 /* `t', 0x74 */
+       _LOWER,                 /* `u', 0x75 */
+       _LOWER,                 /* `v', 0x76 */
+       _LOWER,                 /* `w', 0x77 */
+       _LOWER,                 /* `x', 0x78 */
+       _LOWER,                 /* `y', 0x79 */
+       _LOWER,                 /* `z', 0x7a */
+       _PUNCT,                 /* `{', 0x7b */
+       _PUNCT,                 /* `|', 0x7c */
+       _PUNCT,                 /* `}', 0x7d */
+       _PUNCT,                 /* `~', 0x7e */
+       _CONTROL,               /* 0x7f */
+       0,                      /* 0x80 */
+       0,                      /* 0x81 */
+       0,                      /* 0x82 */
+       0,                      /* 0x83 */
+       0,                      /* 0x84 */
+       0,                      /* 0x85 */
+       0,                      /* 0x86 */
+       0,                      /* 0x87 */
+       0,                      /* 0x88 */
+       0,                      /* 0x89 */
+       0,                      /* 0x8a */
+       0,                      /* 0x8b */
+       0,                      /* 0x8c */
+       0,                      /* 0x8d */
+       0,                      /* 0x8e */
+       0,                      /* 0x8f */
+       0,                      /* 0x90 */
+       0,                      /* 0x91 */
+       0,                      /* 0x92 */
+       0,                      /* 0x93 */
+       0,                      /* 0x94 */
+       0,                      /* 0x95 */
+       0,                      /* 0x96 */
+       0,                      /* 0x97 */
+       0,                      /* 0x98 */
+       0,                      /* 0x99 */
+       0,                      /* 0x9a */
+       0,                      /* 0x9b */
+       0,                      /* 0x9c */
+       0,                      /* 0x9d */
+       0,                      /* 0x9e */
+       0,                      /* 0x9f */
+       0,                      /* 0xa0 */
+       0,                      /* 0xa1 */
+       0,                      /* 0xa2 */
+       0,                      /* 0xa3 */
+       0,                      /* 0xa4 */
+       0,                      /* 0xa5 */
+       0,                      /* 0xa6 */
+       0,                      /* 0xa7 */
+       0,                      /* 0xa8 */
+       0,                      /* 0xa9 */
+       0,                      /* 0xaa */
+       0,                      /* 0xab */
+       0,                      /* 0xac */
+       0,                      /* 0xad */
+       0,                      /* 0xae */
+       0,                      /* 0xaf */
+       0,                      /* 0xb0 */
+       0,                      /* 0xb1 */
+       0,                      /* 0xb2 */
+       0,                      /* 0xb3 */
+       0,                      /* 0xb4 */
+       0,                      /* 0xb5 */
+       0,                      /* 0xb6 */
+       0,                      /* 0xb7 */
+       0,                      /* 0xb8 */
+       0,                      /* 0xb9 */
+       0,                      /* 0xba */
+       0,                      /* 0xbb */
+       0,                      /* 0xbc */
+       0,                      /* 0xbd */
+       0,                      /* 0xbe */
+       0,                      /* 0xbf */
+       0,                      /* 0xc0 */
+       0,                      /* 0xc1 */
+       0,                      /* 0xc2 */
+       0,                      /* 0xc3 */
+       0,                      /* 0xc4 */
+       0,                      /* 0xc5 */
+       0,                      /* 0xc6 */
+       0,                      /* 0xc7 */
+       0,                      /* 0xc8 */
+       0,                      /* 0xc9 */
+       0,                      /* 0xca */
+       0,                      /* 0xcb */
+       0,                      /* 0xcc */
+       0,                      /* 0xcd */
+       0,                      /* 0xce */
+       0,                      /* 0xcf */
+       0,                      /* 0xd0 */
+       0,                      /* 0xd1 */
+       0,                      /* 0xd2 */
+       0,                      /* 0xd3 */
+       0,                      /* 0xd4 */
+       0,                      /* 0xd5 */
+       0,                      /* 0xd6 */
+       0,                      /* 0xd7 */
+       0,                      /* 0xd8 */
+       0,                      /* 0xd9 */
+       0,                      /* 0xda */
+       0,                      /* 0xdb */
+       0,                      /* 0xdc */
+       0,                      /* 0xdd */
+       0,                      /* 0xde */
+       0,                      /* 0xdf */
+       0,                      /* 0xe0 */
+       0,                      /* 0xe1 */
+       0,                      /* 0xe2 */
+       0,                      /* 0xe3 */
+       0,                      /* 0xe4 */
+       0,                      /* 0xe5 */
+       0,                      /* 0xe6 */
+       0,                      /* 0xe7 */
+       0,                      /* 0xe8 */
+       0,                      /* 0xe9 */
+       0,                      /* 0xea */
+       0,                      /* 0xeb */
+       0,                      /* 0xec */
+       0,                      /* 0xed */
+       0,                      /* 0xee */
+       0,                      /* 0xef */
+       0,                      /* 0xf0 */
+       0,                      /* 0xf1 */
+       0,                      /* 0xf2 */
+       0,                      /* 0xf3 */
+       0,                      /* 0xf4 */
+       0,                      /* 0xf5 */
+       0,                      /* 0xf6 */
+       0,                      /* 0xf7 */
+       0,                      /* 0xf8 */
+       0,                      /* 0xf9 */
+       0,                      /* 0xfa */
+       0,                      /* 0xfb */
+       0,                      /* 0xfc */
+       0,                      /* 0xfd */
+       0,                      /* 0xfe */
+       0                       /* 0xff */
+};
+
+/* EOF */
diff --git a/lib/msvcrt/direct/wchdir.c b/lib/msvcrt/direct/wchdir.c
new file mode 100644 (file)
index 0000000..5772036
--- /dev/null
@@ -0,0 +1,13 @@
+#include <windows.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/direct.h>
+
+
+int _wchdir (const wchar_t *_path)
+{
+    if (_path[1] == L':')
+        _chdrive(towlower(_path[0] - L'a')+1);
+    if (!SetCurrentDirectoryW((wchar_t *)_path))
+        return -1;
+    return 0;
+}
diff --git a/lib/msvcrt/direct/wgetcwd.c b/lib/msvcrt/direct/wgetcwd.c
new file mode 100644 (file)
index 0000000..14e71bc
--- /dev/null
@@ -0,0 +1,20 @@
+#include <windows.h>
+#include <msvcrt/direct.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wgetcwd(wchar_t* buffer, int maxlen)
+{
+    wchar_t *cwd;
+    int len;
+    if (buffer == NULL) {
+        cwd = malloc(MAX_PATH * sizeof(wchar_t));
+        len = MAX_PATH;
+    } else {
+        cwd = buffer;
+        len = maxlen;
+    }
+    if (GetCurrentDirectoryW(len, cwd) == 0 )
+        return NULL;
+    return cwd;
+}
diff --git a/lib/msvcrt/direct/wgetdcwd.c b/lib/msvcrt/direct/wgetdcwd.c
new file mode 100644 (file)
index 0000000..804e25a
--- /dev/null
@@ -0,0 +1,24 @@
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+
+wchar_t* _wgetdcwd(int nDrive, wchar_t* caBuffer, int nBufLen)
+{
+    int i =0;
+    int dr = _getdrive();
+
+    if (nDrive < 1 || nDrive > 26)
+        return NULL;
+
+    if (dr != nDrive)
+        _chdrive(nDrive);
+
+    i = GetCurrentDirectoryW(nBufLen, caBuffer);
+    if (i  == nBufLen)
+        return NULL;
+
+    if (dr != nDrive)
+        _chdrive(dr);
+
+    return caBuffer;
+}
diff --git a/lib/msvcrt/direct/wmkdir.c b/lib/msvcrt/direct/wmkdir.c
new file mode 100644 (file)
index 0000000..6b979c4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+
+int _wmkdir(const wchar_t* _path)
+{
+    if (!CreateDirectoryW(_path, NULL))
+        return -1;
+    return 0;
+}
diff --git a/lib/msvcrt/direct/wrmdir.c b/lib/msvcrt/direct/wrmdir.c
new file mode 100644 (file)
index 0000000..ce3bb22
--- /dev/null
@@ -0,0 +1,9 @@
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+int _wrmdir(const wchar_t* _path)
+{
+    if (!RemoveDirectoryW(_path))
+        return -1;
+    return 0;
+}
diff --git a/lib/msvcrt/io/fileleni.c b/lib/msvcrt/io/fileleni.c
new file mode 100644 (file)
index 0000000..9c2d406
--- /dev/null
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <msvcrt/io.h>
+
+
+__int64 _filelengthi64(int _fd)
+{
+    long lo_length, hi_length;
+
+    lo_length = GetFileSize(_get_osfhandle(_fd), &hi_length);
+    return((((__int64)hi_length) << 32) + lo_length);
+}
diff --git a/lib/msvcrt/io/lseeki64.c b/lib/msvcrt/io/lseeki64.c
new file mode 100644 (file)
index 0000000..71b8e76
--- /dev/null
@@ -0,0 +1,39 @@
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/internal/file.h>
+
+
+//#define SETFILEPOINTEREX_AVAILABLE
+
+__int64 _lseeki64(int _fildes, __int64 _offset, int _whence)
+{
+#ifdef SETFILEPOINTEREX_AVAILABLE
+    LARGE_INTEGER new_pos;
+    LARGE_INTEGER offset;
+    offset.QuadPart = _offset;
+
+//    if (invalid_filehnd(_fildes)) {
+//        errno = EBADF;
+//        return -1L;
+//    }
+    if (SetFilePointerEx((HANDLE)filehnd(_fildes), offset, &new_pos, _whence)) {
+    } else {
+        //errno = EINVAL;
+        return -1L;
+    }
+    return new_pos.QuadPart;
+#else
+    //ULONG lo_pos;
+    //DWORD hi_pos = 0;  // must equal 0 or -1 if supplied, -1 for negative 32 seek value
+    //lo_pos = SetFilePointer((HANDLE)filehnd(_fildes), _offset, &hi_pos, _whence);
+    //return((((__int64)hi_pos) << 32) + lo_pos);
+
+    LARGE_INTEGER offset;
+    offset.QuadPart = _offset;
+
+    offset.u.LowPart = SetFilePointer((HANDLE)filehnd(_fildes), 
+                          offset.u.LowPart, &offset.u.HighPart, _whence);
+    return ((((__int64)offset.u.HighPart) << 32) + offset.u.LowPart);
+
+#endif /*SETFILEPOINTEREX_AVAILABLE*/
+}
diff --git a/lib/msvcrt/io/telli64.c b/lib/msvcrt/io/telli64.c
new file mode 100644 (file)
index 0000000..5b03d88
--- /dev/null
@@ -0,0 +1,8 @@
+#include <msvcrt/errno.h>
+#include <msvcrt/io.h>
+
+
+__int64 _telli64(int _file)
+{
+    return _lseeki64(_file, 0, SEEK_CUR);
+}
diff --git a/lib/msvcrt/io/waccess.c b/lib/msvcrt/io/waccess.c
new file mode 100644 (file)
index 0000000..24932fc
--- /dev/null
@@ -0,0 +1,29 @@
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _waccess(const wchar_t *_path, int _amode)
+{
+    DWORD Attributes = GetFileAttributesW(_path);
+
+    if (Attributes == -1) {
+        __set_errno(ENOENT);
+        return -1;
+    }
+    if ((_amode & W_OK) == W_OK) {
+        if ((Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
+            __set_errno(EACCES);
+            return -1;
+        }
+    }
+    if ((_amode & D_OK) == D_OK) {
+        if ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
+            __set_errno(EACCES);
+            return -1;
+        }
+    }
+    return 0;
+}
diff --git a/lib/msvcrt/io/wchmod.c b/lib/msvcrt/io/wchmod.c
new file mode 100644 (file)
index 0000000..e10d632
--- /dev/null
@@ -0,0 +1,33 @@
+#include <windows.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+#define mode_t int
+
+
+int _wchmod(const wchar_t* filename, mode_t mode)
+{
+    DWORD FileAttributes = 0;
+    DPRINT("_wchmod('%S', %x)\n", filename, mode);
+
+    FileAttributes = GetFileAttributesW(filename);
+    if ( FileAttributes == -1 )
+        return -1;
+
+    if ( mode == 0 )
+        return -1;
+
+    if ((mode & _S_IREAD) == _S_IREAD && (mode & _S_IWRITE) != _S_IWRITE)
+        FileAttributes &= FILE_ATTRIBUTE_READONLY;
+    else if (((mode & _S_IREAD) != _S_IREAD) && ((mode & _S_IWRITE) == _S_IWRITE))
+        FileAttributes &= FILE_ATTRIBUTE_NORMAL;
+    else
+        FileAttributes &= FILE_ATTRIBUTE_NORMAL;
+
+    if (SetFileAttributesW(filename, FileAttributes) == FALSE)
+        return -1;
+
+    return 1;
+}
diff --git a/lib/msvcrt/io/wcreate.c b/lib/msvcrt/io/wcreate.c
new file mode 100644 (file)
index 0000000..6234d81
--- /dev/null
@@ -0,0 +1,12 @@
+#include <msvcrt/io.h>
+#include <msvcrt/fcntl.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wcreat(const wchar_t* filename, int mode)
+{
+    DPRINT("_wcreat('%S', mode %x)\n", filename, mode);
+    return _wopen(filename,_O_CREAT|_O_TRUNC,mode);
+}
diff --git a/lib/msvcrt/io/wfind.c b/lib/msvcrt/io/wfind.c
new file mode 100644 (file)
index 0000000..221a33e
--- /dev/null
@@ -0,0 +1,203 @@
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/string.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wfindfirst(const wchar_t* _name, struct _wfinddata_t* result)
+{
+    WIN32_FIND_DATAW FindFileData;
+    wchar_t dir[MAX_PATH];
+    long hFindFile;
+    int len = 0;
+
+    if ( _name == NULL || _name[0] == 0 ) {
+        len = GetCurrentDirectoryW(MAX_PATH-4, dir);
+        if (dir[len-1] != L'\\') {
+            dir[len] = L'\\';
+            dir[len+1] = 0;
+        }
+        wcscat(dir, L"*.*");
+    } else {
+        wcscpy(dir, _name);
+    }
+
+    hFindFile = (long)FindFirstFileW(dir, &FindFileData);
+    if (hFindFile == -1) {
+        memset(result,0,sizeof(struct _wfinddata_t));
+        return -1;
+    }
+
+    result->attrib = FindFileData.dwFileAttributes;
+    result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+    result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+    result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+    result->size = FindFileData.nFileSizeLow;
+    wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+    // if no wildcard the find file handle can be closed right away
+    // a return value of 0 can flag this.
+    if (!wcschr(dir, L'*') && !wcschr(dir, L'?')) {
+        _findclose(hFindFile);
+        return 0;
+    }
+
+    return hFindFile;
+}
+
+int _findfirsti64(const char *_name, struct _finddatai64_t *result)
+{
+  WIN32_FIND_DATAA FindFileData;
+  char dir[MAX_PATH];
+  long hFindFile;
+  int len = 0;
+
+  if ( _name == NULL || _name[0] == 0 )
+    {
+      len = GetCurrentDirectoryA(MAX_PATH-4,dir);
+      if (dir[len-1] != '\\')
+    {
+      dir[len] = '\\';
+      dir[len+1] = 0;
+    }
+      strcat(dir, "*.*");
+    }
+  else
+    strcpy(dir, _name);
+
+  hFindFile = (long)FindFirstFileA(dir, &FindFileData);
+  if (hFindFile == -1)
+    {
+      memset(result,0,sizeof(struct _finddatai64_t));
+      return -1;
+    }
+
+  result->attrib = FindFileData.dwFileAttributes;
+  result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+  result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+  result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+  result->size =
+    (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+  strncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+  // if no wildcard the find file handle can be closed right away
+  // a return value of 0 can flag this.
+
+  if (!strchr(dir,'*') && !strchr(dir,'?')) {
+      _findclose(hFindFile);
+      return 0;
+    }
+  return hFindFile;
+}
+
+int _findnexti64(int handle, struct _finddatai64_t *result)
+{
+  WIN32_FIND_DATAA FindFileData;
+
+  // check no wildcards or invalid handle
+  if (handle == 0 || handle == -1)
+    return 0;
+
+  if (!FindNextFileA((void *)handle, &FindFileData))
+    return -1;
+
+  result->attrib = FindFileData.dwFileAttributes;
+  result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+  result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+  result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+  result->size =
+    (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+  strncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+  return 0;
+}
+
+int _wfindfirsti64(const wchar_t *_name, struct _wfinddatai64_t *result)
+{
+  WIN32_FIND_DATAW FindFileData;
+  wchar_t dir[MAX_PATH];
+  long hFindFile;
+  int len = 0;
+
+  if (_name == NULL || _name[0] == 0)
+    {
+      len = GetCurrentDirectoryW(MAX_PATH-4,dir);
+      if (dir[len-1] != L'\\')
+    {
+      dir[len] = L'\\';
+      dir[len+1] = 0;
+    }
+      wcscat(dir, L"*.*");
+    }
+  else
+    wcscpy(dir, _name);
+
+  hFindFile = (long)FindFirstFileW(dir, &FindFileData);
+  if (hFindFile == -1)
+    {
+      memset(result,0,sizeof(struct _wfinddatai64_t));
+      return -1;
+    }
+
+  result->attrib = FindFileData.dwFileAttributes;
+  result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+  result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+  result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+  result->size =
+    (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+  wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+  // if no wildcard the find file handle can be closed right away
+  // a return value of 0 can flag this.
+
+  if (!wcschr(dir,L'*') && !wcschr(dir,L'?'))
+    {
+      _findclose(hFindFile);
+      return 0;
+    }
+
+  return hFindFile;
+}
+
+int _wfindnext(int handle, struct _wfinddata_t *result)
+{
+  WIN32_FIND_DATAW FindFileData;
+
+  // check no wildcards or invalid handle
+  if (handle == 0 || handle == -1)
+    return 0;
+
+  if (!FindNextFileW((void *)handle, &FindFileData))
+    return -1;
+
+  result->attrib = FindFileData.dwFileAttributes;
+  result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+  result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+  result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+  result->size = FindFileData.nFileSizeLow;
+  wcsncpy(result->name,FindFileData.cFileName, MAX_PATH);
+
+  return 0;
+}
+
+int _wfindnexti64(int handle, struct _wfinddatai64_t *result)
+{
+  WIN32_FIND_DATAW FindFileData;
+
+  // check no wildcards or invalid handle
+  if (handle == 0 || handle == -1)
+    return 0;
+
+  if (!FindNextFileW((void *)handle, &FindFileData))
+    return -1;
+
+  result->attrib = FindFileData.dwFileAttributes;
+  result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+  result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+  result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+  result->size =
+    (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+  wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+  return 0;
+}
diff --git a/lib/msvcrt/io/wmktemp.c b/lib/msvcrt/io/wmktemp.c
new file mode 100644 (file)
index 0000000..d52d431
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ *      Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details 
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/io/mktemp.c
+ * PURPOSE:     Makes a temp file based on a template
+ * PROGRAMER:   DJ Delorie
+                Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Appropriated for the Reactos Kernel
+ */
+
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/stdio.h>
+#include <msvcrt/string.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+wchar_t* _wmktemp (wchar_t *_template)
+{
+  static int count = 0;
+  wchar_t *cp, *dp;
+  int i, len, xcount, loopcnt;
+
+  DPRINT("_wmktemp('%S')\n", _template);
+  len = wcslen (_template);
+  cp = _template + len;
+
+  xcount = 0;
+  while (xcount < 6 && cp > _template && cp[-1] == L'X')
+    xcount++, cp--;
+
+  if (xcount) {
+    dp = cp;
+    while (dp > _template && dp[-1] != L'/' && dp[-1] != L'\\' && dp[-1] != L':')
+      dp--;
+
+    /* Keep the first characters of the template, but turn the rest into
+       Xs.  */
+    while (cp > dp + 8 - xcount) {
+      *--cp = L'X';
+      xcount = (xcount >= 6) ? 6 : 1 + xcount;
+    }
+
+    /* If dots occur too early -- squash them.  */
+    while (dp < cp) {
+      if (*dp == L'.') *dp = L'a';
+      dp++;
+    }
+
+    /* Try to add ".tmp" to the filename.  Truncate unused Xs.  */
+    if (cp + xcount + 3 < _template + len)
+      wcscpy (cp + xcount, L".tmp");
+    else
+      cp[xcount] = 0;
+
+    /* This loop can run up to 2<<(5*6) times, or about 10^9 times.  */
+    for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) {
+      int c = count++;
+      for (i = 0; i < xcount; i++, c >>= 5)
+    cp[i] = L"abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f];
+      if (_waccess(_template,0) == -1)
+    return _template;
+    }
+  }
+
+  /* Failure:  truncate the template and return NULL.  */
+  *_template = 0;
+  return 0;
+}
diff --git a/lib/msvcrt/io/wopen.c b/lib/msvcrt/io/wopen.c
new file mode 100644 (file)
index 0000000..c98c2eb
--- /dev/null
@@ -0,0 +1,140 @@
+/* $Id$
+ *
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/io/open.c
+ * PURPOSE:     Opens a file and translates handles to fileno
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+
+// rember to interlock the allocation of fileno when making this thread safe
+// possibly store extra information at the handle
+
+#include <windows.h>
+#if !defined(NDEBUG) && defined(DBG)
+#include <msvcrt/stdarg.h>
+#endif
+#include <msvcrt/io.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+#include <msvcrt/string.h>
+#include <msvcrt/share.h>
+#include <msvcrt/errno.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wopen(const wchar_t* _path, int _oflag, ...)
+{
+#if !defined(NDEBUG) && defined(DBG)
+    va_list arg;
+    int pmode;
+#endif
+    HANDLE hFile;
+    DWORD dwDesiredAccess = 0;
+    DWORD dwShareMode = 0;
+    DWORD dwCreationDistribution = 0;
+    DWORD dwFlagsAndAttributes = 0;
+    SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+#if !defined(NDEBUG) && defined(DBG)
+    va_start(arg, _oflag);
+    pmode = va_arg(arg, int);
+#endif
+
+//    DPRINT("_wopen('%S', %x, (%x))\n", _path, _oflag, pmode);
+
+    if ((_oflag & S_IREAD) == S_IREAD)
+        dwShareMode = FILE_SHARE_READ;
+    else if ( ( _oflag & S_IWRITE) == S_IWRITE) {
+        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+    }
+
+   /*
+    *
+    * _O_BINARY   Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
+    * _O_TEXT   Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
+    * 
+    * _O_APPEND   Moves file pointer to end of file before every write operation.
+    */
+#if 0
+    if ((_oflag & _O_RDWR) == _O_RDWR)
+        dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
+                           FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
+                           FILE_WRITE_ATTRIBUTES;
+    else if ((_oflag & O_RDONLY) == O_RDONLY)
+        dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
+                           FILE_WRITE_ATTRIBUTES;
+    else if ((_oflag & _O_WRONLY) == _O_WRONLY)
+        dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
+                           FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+#else
+    if ((_oflag & _O_WRONLY) == _O_WRONLY)
+        dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
+                           FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+    else if ((_oflag & _O_RDWR) == _O_RDWR)
+        dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
+                           FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
+                           FILE_WRITE_ATTRIBUTES;
+    else //if ((_oflag & O_RDONLY) == O_RDONLY)
+        dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
+                           FILE_WRITE_ATTRIBUTES;
+#endif
+
+    if ((_oflag & S_IREAD) == S_IREAD)
+        dwShareMode |= FILE_SHARE_READ;
+
+    if ((_oflag & S_IWRITE) == S_IWRITE)
+        dwShareMode |= FILE_SHARE_WRITE;
+
+    if ((_oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
+        dwCreationDistribution |= CREATE_NEW;
+
+    else if ((_oflag &  O_TRUNC) == O_TRUNC) {
+        if ((_oflag &  O_CREAT) ==  O_CREAT)
+            dwCreationDistribution |= CREATE_ALWAYS;
+        else if ((_oflag & O_RDONLY) != O_RDONLY)
+            dwCreationDistribution |= TRUNCATE_EXISTING;
+    }
+    else if ((_oflag & _O_APPEND) == _O_APPEND)
+        dwCreationDistribution |= OPEN_EXISTING;
+    else if ((_oflag &  _O_CREAT) == _O_CREAT)
+        dwCreationDistribution |= OPEN_ALWAYS;
+    else
+        dwCreationDistribution |= OPEN_EXISTING;
+
+    if ((_oflag &  _O_RANDOM) == _O_RANDOM)
+        dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+    if ((_oflag &  _O_SEQUENTIAL) == _O_SEQUENTIAL)
+        dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+
+    if ((_oflag &  _O_TEMPORARY) == _O_TEMPORARY)
+        dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+    if ((_oflag &  _O_SHORT_LIVED) == _O_SHORT_LIVED)
+        dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+    if (_oflag & _O_NOINHERIT)
+        sa.bInheritHandle = FALSE;
+
+    hFile = CreateFileW(_path,
+               dwDesiredAccess,
+               dwShareMode,
+               &sa,
+               dwCreationDistribution,
+               dwFlagsAndAttributes,
+               NULL);
+    if (hFile == (HANDLE)-1)
+        return -1;
+    return __fileno_alloc(hFile,_oflag);
+}
+
+int _wsopen(wchar_t* path, int access, int shflag, int mode)
+{
+    return _wopen((path), (access)|(shflag), (mode));
+}
diff --git a/lib/msvcrt/io/wunlink.c b/lib/msvcrt/io/wunlink.c
new file mode 100644 (file)
index 0000000..c7d2989
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/io/unlink.c
+ * PURPOSE:     Deletes a file
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wunlink(const wchar_t* filename)
+{
+    DPRINT("_wunlink('%S')\n", filename);
+    if (!DeleteFileW(filename))
+        return -1;
+    return 0;
+}
diff --git a/lib/msvcrt/io/wutime.c b/lib/msvcrt/io/wutime.c
new file mode 100644 (file)
index 0000000..be87e8b
--- /dev/null
@@ -0,0 +1,22 @@
+#include <msvcrt/stdio.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/sys/utime.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wutime(const wchar_t* filename, struct _utimbuf* buf)
+{
+    int fn;
+    int ret;
+  
+    fn = _wopen(filename, _O_RDWR);
+    if (fn == -1) {
+        __set_errno(EBADF);
+        return -1;
+    }
+    ret = _futime(fn, buf);
+    if (_close(fn) < 0)
+        return -1;
+    return ret;
+}
diff --git a/lib/msvcrt/math/math.c b/lib/msvcrt/math/math.c
new file mode 100644 (file)
index 0000000..157b72f
--- /dev/null
@@ -0,0 +1,120 @@
+#include <msvcrt/math.h>
+
+#pragma function(fmod,sqrt)
+#pragma function(log,log10,pow,exp)
+#pragma function(tan,atan,atan2,tanh)
+#pragma function(cos,acos,cosh)
+#pragma function(sin,asin,sinh)
+
+
+double linkme_ceil(double __x)
+{
+    return ceil(__x);
+}
+
+double linkme_fabs(double __x)
+{
+    return fabs(__x);
+}
+
+double linkme_floor(double __x)
+{
+    return floor(__x);
+}
+
+double linkme_ldexp(double __x, int __y)
+{
+    return ldexp(__x, __y);
+}
+
+double linkme_log2(double __x)
+{
+    //return log2(__x);
+    return 0;
+}
+
+double linkme_fmod(double __x, double __y)
+{
+    return fmod(__x, __y);
+}
+
+double linkme_sqrt(double __x)
+{
+    return sqrt(__x);
+}
+
+double linkme_log(double __x)
+{
+    return log(__x);
+}
+
+double linkme_log10(double __x)
+{
+    return log10(__x);
+}
+
+double linkme_pow(double __x, double __y)
+{
+    return pow(__x, __y);
+}
+
+double linkme_exp(double __x)
+{
+    return exp(__x);
+}
+
+double linkme_tan(double __x)
+{
+    return tan(__x);
+}
+
+double linkme_atan(double __x)
+{
+    return atan(__x);
+}
+
+double linkme_atan2(double __x, double __y)
+{
+    return atan2(__x, __y);
+}
+
+double linkme_tanh(double __x)
+{
+    return tanh(__x);
+}
+
+double linkme_cos(double __x)
+{
+    return cos(__x);
+}
+
+double linkme_acos(double __x)
+{
+    return acos(__x);
+}
+
+double linkme_cosh(double __x)
+{
+    return cosh(__x);
+}
+
+double linkme_sin(double __x)
+{
+    return sin(__x);
+}
+
+double linkme_asin(double __x)
+{
+    return asin(__x);
+}
+
+double linkme_sinh(double __x)
+{
+    return sinh(__x);
+}
+/*
+linkme_log2
+linkme_floor
+_linkme_ldexp
+_linkme_pow
+ */
diff --git a/lib/msvcrt/misc/crtmain.c b/lib/msvcrt/misc/crtmain.c
new file mode 100644 (file)
index 0000000..2693522
--- /dev/null
@@ -0,0 +1,99 @@
+/* $Id$
+ *
+ * ReactOS MSVCRT.DLL Compatibility Library
+ */
+#include <windows.h>
+//#include <msvcrt/stdlib.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+#ifndef __GNUC__
+
+/* GLOBAL VARIABLES *******************************************************/
+
+int _fltused;
+
+
+/* FUNCTIONS **************************************************************/
+
+int 
+STDCALL
+_except_handler3(void)
+{
+    return 0;
+}
+
+int
+STDCALL
+_local_unwind2(void)
+{
+    return 0;
+}
+
+int
+STDCALL
+_spawnlp(int a, const char* b, const char* args, ...)
+{
+    return 0;
+}
+
+#else /*__GNUC__*/
+
+int
+_spawnlp(int a, const char* b, const char* args, ...)
+{
+    return 0;
+}
+
+#endif /*__GNUC__*/
+
+
+/*
+int __cdecl _allmul(void)
+{
+    return 0;
+}
+
+int __cdecl _allshl(void)
+{
+    return 0;
+}
+
+void __cdecl _chkesp(int value1, int value2)
+{
+}
+
+int __cdecl _alloca_probe(void)
+{
+    return 0;
+}
+
+int STDCALL _abnormal_termination(void)
+{
+    return 0;
+}
+
+int STDCALL _setjmp(void)
+{
+    return 0;
+}
+*/
+/*
+BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved);
+
+int STDCALL _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+    BOOL result;
+
+    //__fileno_init();
+    //result = DllMain(hInst, ul_reason_for_call, lpReserved);
+
+    result = DllMain(hInst, DLL_PROCESS_ATTACH, lpReserved);
+    
+
+    return (result ? 1 : 0);
+}
+ */
+
+/* EOF */
diff --git a/lib/msvcrt/misc/environ.c b/lib/msvcrt/misc/environ.c
new file mode 100644 (file)
index 0000000..7dc8d43
--- /dev/null
@@ -0,0 +1,123 @@
+/* $Id$
+ *
+ * dllmain.c
+ *
+ * ReactOS MSVCRT.DLL Compatibility Library
+ */
+
+#include <windows.h>
+#include <msvcrt/internal/tls.h>
+#include <msvcrt/stdlib.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+unsigned int _osver = 0;
+unsigned int _winminor = 0;
+unsigned int _winmajor = 0;
+unsigned int _winver = 0;
+
+char *_acmdln = NULL;       /* pointer to ascii command line */
+#undef _environ
+char **_environ = NULL;     /* pointer to environment block */
+char ***_environ_dll = &_environ;/* pointer to environment block */
+char **__initenv = NULL;
+char *_pgmptr = NULL;       /* pointer to program name */
+int __app_type = 0; //_UNKNOWN_APP; /* application type */
+int __mb_cur_max = 1;
+
+int _commode = _IOCOMMIT;
+
+
+int *__p__commode(void) // not exported by NTDLL
+{
+   return &_commode;
+}
+
+int BlockEnvToEnviron(void)
+{
+    char * ptr, * ptr2;
+    int i, len;
+
+    DPRINT("BlockEnvToEnviron()\n");
+
+    if (_environ) {
+        FreeEnvironmentStringsA(_environ[0]);
+        free(_environ);
+        _environ = NULL;
+    }
+    ptr2 = ptr = (char*)GetEnvironmentStringsA();
+    if (ptr == NULL) {
+        DPRINT("GetEnvironmentStringsA() returnd NULL\n");
+        return -1;
+    }
+    len = 0;
+    while (*ptr2) {
+        len++;
+        while (*ptr2++);
+    }
+    _environ = malloc((len + 1) * sizeof(char*));
+    if (_environ == NULL) {
+        FreeEnvironmentStringsA(ptr);
+        return -1;
+    }
+    for (i = 0; i < len && *ptr; i++) {
+        _environ[i] = ptr;
+        while (*ptr++);
+    }
+    _environ[i] = NULL;
+    return 0;
+}
+
+void __set_app_type(int app_type)
+{
+    __app_type = app_type;
+}
+
+char **__p__acmdln(void)
+{
+    return &_acmdln;
+}
+
+char ***__p__environ(void)
+{
+    return _environ_dll;
+}
+
+char ***__p___initenv(void)
+{
+    return &__initenv;
+}
+
+int *__p___mb_cur_max(void)
+{
+    return &__mb_cur_max;
+}
+
+unsigned int *__p__osver(void)
+{
+    return &_osver;
+}
+
+char **__p__pgmptr(void)
+{
+    return &_pgmptr;
+}
+
+unsigned int *__p__winmajor(void)
+{
+    return &_winmajor;
+}
+
+unsigned int *__p__winminor(void)
+{
+    return &_winminor;
+}
+
+unsigned int *__p__winver(void)
+{
+    return &_winver;
+}
+
+/* EOF */
diff --git a/lib/msvcrt/process/threadx.c b/lib/msvcrt/process/threadx.c
new file mode 100644 (file)
index 0000000..12a63f6
--- /dev/null
@@ -0,0 +1,26 @@
+/* $Id$
+ *
+ */
+#include <windows.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/process.h>
+
+
+unsigned long _beginthreadex(
+    void* security,
+    unsigned stack_size,
+    unsigned (__stdcall *start_address)(void*),
+    void* arglist,
+    unsigned initflag,
+    unsigned* thrdaddr)
+{
+    errno = ENOSYS;
+    return (unsigned long)-1;
+}
+
+
+void _endthreadex(unsigned retval)
+{
+}
+
+/* EOF */
diff --git a/lib/msvcrt/stdio/fgetws.c b/lib/msvcrt/stdio/fgetws.c
new file mode 100644 (file)
index 0000000..0f2dae6
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id$
+ *
+ *  ReactOS msvcrt library
+ *
+ *  fgets.c
+ *
+ *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+ *
+ *  Based on original work Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details
+ *                         28/12/1998: Appropriated for Reactos
+ *
+ * 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
+ */
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+
+//#include <msvcrt/ctype.h>
+#ifndef WEOF
+#define WEOF    (wchar_t)(0xFFFF)
+#endif
+
+wchar_t* fgetws(wchar_t* s, int n, FILE* f)
+{
+  wchar_t c = 0;
+  wchar_t* cs;
+
+  cs = s;
+  //while (--n > 0 && (c = getwc(f)) != WEOF) {
+  while (n > 0) {
+    c = getwc(f);
+    if (c == WEOF)
+      break;
+    n--;
+    *cs++ = c;
+    if (c == L'\n')
+      break;
+  }
+  if (c == WEOF && cs == s) {
+    return NULL;
+  }
+  *cs++ = L'\0';
+  return s;
+}
diff --git a/lib/msvcrt/stdio/wfdopen.c b/lib/msvcrt/stdio/wfdopen.c
new file mode 100644 (file)
index 0000000..6e4ec0b
--- /dev/null
@@ -0,0 +1,54 @@
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+FILE* __alloc_file(void);
+
+
+FILE* _wfdopen(int handle, wchar_t* mode)
+{
+  FILE* file;
+  int rw;
+
+  if (handle == 0)
+    return stdin;
+
+  if (handle == 1)
+    return stdout;
+
+  if (handle == 2)
+    return stderr;
+
+  if (handle == 3)
+    return stdaux;
+
+  if (handle == 4)
+    return stdprn;
+
+  file = __alloc_file();
+  if (file == NULL)
+    return NULL;
+  file->_file = handle;
+
+  rw = (mode[1] == L'+') || (mode[1] && (mode[2] == L'+'));
+
+  if (*mode == L'a')
+    _lseek(handle, 0, SEEK_END);
+
+  file->_cnt = 0;
+  file->_file = handle;
+  file->_bufsiz = 0;
+
+// The mode of the stream must be compatible with the mode of the file descriptor.
+// this should be checked.
+
+  if (rw)
+    file->_flag = _IOREAD | _IOWRT;
+  else if (*mode == L'r')
+    file->_flag = _IOREAD;
+  else
+    file->_flag = _IOWRT;
+
+  file->_base = file->_ptr = NULL;
+
+  return file;
+}
diff --git a/lib/msvcrt/stdio/wrename.c b/lib/msvcrt/stdio/wrename.c
new file mode 100644 (file)
index 0000000..f580216
--- /dev/null
@@ -0,0 +1,15 @@
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/io.h>
+
+
+int _wrename(const wchar_t* old_, const wchar_t* new_)
+{
+    if (old_ == NULL || new_ == NULL)
+        return -1;
+
+    if (!MoveFileW(old_, new_))
+        return -1;
+
+    return 0;
+}
diff --git a/lib/msvcrt/stdio/wtempnam.c b/lib/msvcrt/stdio/wtempnam.c
new file mode 100644 (file)
index 0000000..c35118b
--- /dev/null
@@ -0,0 +1,22 @@
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wtempnam(const wchar_t* dir, const wchar_t* prefix)
+{
+    wchar_t* TempFileName = malloc(MAX_PATH);
+    wchar_t* d;
+
+    if (dir == NULL)
+        d = _wgetenv(L"TMP");
+    else
+        d = (wchar_t*)dir;
+
+    if (GetTempFileNameW(d, prefix, 1, TempFileName) == 0) {
+        free(TempFileName);
+        return NULL;
+    }
+
+    return TempFileName;
+}
diff --git a/lib/msvcrt/stdio/wtmpnam.c b/lib/msvcrt/stdio/wtmpnam.c
new file mode 100644 (file)
index 0000000..5169901
--- /dev/null
@@ -0,0 +1,16 @@
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/string.h>
+
+
+wchar_t* _wtmpnam(wchar_t* s)
+{
+    wchar_t PathName[MAX_PATH];
+    static wchar_t static_buf[MAX_PATH];
+
+    GetTempPathW(MAX_PATH, PathName);
+    GetTempFileNameW(PathName, L"ARI", 007, static_buf);
+    wcscpy(s, static_buf);
+
+    return s;
+}
diff --git a/lib/msvcrt/stdlib/mbtowc.c b/lib/msvcrt/stdlib/mbtowc.c
new file mode 100644 (file)
index 0000000..501f124
--- /dev/null
@@ -0,0 +1,52 @@
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/ctype.h>
+
+
+#if 1
+
+int mbtowc(wchar_t *dst, const char *str, size_t n)
+{
+//    printf("\t\t\tmbtowc(%p, %p, %d) called.\n", dst, str, n);
+
+    if (n <= 0 || !str)
+        return 0;
+
+    *dst = *str;
+
+    if (!*str)
+        return 0;
+    return 1;
+}
+
+#else
+
+int mbtowc(wchar_t *dst, const char *str, size_t n)
+{
+    if (n <= 0 || !str)
+        return 0;
+    if (!MultiByteToWideChar(CP_ACP, 0, str, n, dst, (dst == NULL) ? 0 : 1)) {
+        DWORD err = GetLastError();
+        switch (err) {
+        case ERROR_INSUFFICIENT_BUFFER:
+            break;
+        case ERROR_INVALID_FLAGS:
+            break;
+        case ERROR_INVALID_PARAMETER:
+            break;
+        case ERROR_NO_UNICODE_TRANSLATION:
+            break;
+        default:
+            return 1;
+        }
+        return -1;
+    }
+    /* return the number of bytes from src that have been used */
+    if (!*str)
+        return 0;
+    if (n >= 2 && isleadbyte(*str) && str[1])
+        return 2;
+    return 1;
+}
+
+#endif
diff --git a/lib/msvcrt/stdlib/wctomb.c b/lib/msvcrt/stdlib/wctomb.c
new file mode 100644 (file)
index 0000000..1603a5a
--- /dev/null
@@ -0,0 +1,146 @@
+/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/wchar.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+int
+STDCALL
+WideCharToMultiByte(
+    UINT     CodePage,
+    DWORD    dwFlags,
+    LPCWSTR  lpWideCharStr,
+    int      cchWideChar,
+    LPSTR    lpMultiByteStr,
+    int      cchMultiByte,
+    LPCSTR   lpDefaultChar,
+    LPBOOL   lpUsedDefaultChar);
+
+
+int wctomb(char* dst, wchar_t ch)
+{
+#if 0
+    return WideCharToMultiByte(CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL);
+#else
+    if (dst == NULL) {
+        return 1;
+    }
+    *dst = ch;
+    return 1;
+#endif
+}
+
+
+#if 0
+
+#ifndef EILSEQ
+#define EILSEQ EINVAL
+#endif
+
+static const wchar_t encoding_mask[] =
+{
+    /* This reflects the sources *nix origin where type wchar_t 
+       was 32 bits wide. Since our type wchar_t is only 16 bits
+       wide all this module will need to be reviewed.
+       Simplest option may well be to forward this modules work 
+       on to the kernel which already has support for this.
+      */
+    ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff
+    //~0x0000-07ff, ~0x0000-ffff, ~0x001f-ffff, ~0x03ff-ffff
+};
+
+static const unsigned char encoding_byte[] =
+{
+    0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+};
+
+/* The state is for this UTF8 encoding not used.  */
+//static mbstate_t internal;
+//extern mbstate_t __no_r_state;  /* Defined in mbtowc.c.  */
+
+size_t __wcrtomb(char *s, wchar_t wc);
+
+/* Convert WCHAR into its multibyte character representation,
+   putting this in S and returning its length.
+
+   Attention: this function should NEVER be intentionally used.
+   The interface is completely stupid.  The state is shared between
+   all conversion functions.  You should use instead the restartable
+   version `wcrtomb'.  */
+
+int wctomb(char *s, wchar_t wchar)
+{
+  /* If S is NULL the function has to return null or not null
+     depending on the encoding having a state depending encoding or
+     not.  This is nonsense because any multibyte encoding has a
+     state.  The ISO C amendment 1 corrects this while introducing the
+     restartable functions.  We simply say here all encodings have a
+     state.  */
+    if (s == NULL) {
+        return 1;
+    }
+    return __wcrtomb(s, wchar);
+}
+
+size_t __wcrtomb(char *s, wchar_t wc)
+{
+    char fake[1];
+    size_t written = 0;
+
+    if (s == NULL) {
+        s = fake;
+        wc = L'\0';
+    }
+    /* Store the UTF8 representation of WC.  */
+    //if (wc < 0 || wc > 0x7fffffff) {
+    if (wc < 0 || wc > 0x7fff) {
+        /* This is no correct ISO 10646 character.  */
+        __set_errno (EILSEQ);
+        return (size_t) -1;
+    }
+    if (wc < 0x80) {
+        /* It's a one byte sequence.  */
+        if (s != NULL) {
+            *s = (char)wc;
+        }
+        return 1;
+    }
+    for (written = 2; written < 6; ++written) {
+        if ((wc & encoding_mask[written - 2]) == 0) {
+            break;
+        }
+    }
+    if (s != NULL) {
+        size_t cnt = written;
+        s[0] = encoding_byte[cnt - 2];
+        --cnt;
+        do {
+            s[cnt] = 0x80 | (wc & 0x3f);
+            wc >>= 6;
+        } while (--cnt > 0);
+        s[0] |= wc;
+    }
+    return written;
+}
+
+#endif
diff --git a/lib/msvcrt/stdlib/wfulpath.c b/lib/msvcrt/stdlib/wfulpath.c
new file mode 100644 (file)
index 0000000..21b44cf
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/stdlib/fullpath.c
+ * PURPOSE:     Gets the fullpathname
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wfullpath(wchar_t* absPath, const wchar_t* relPath, size_t maxLength)
+{
+    wchar_t* lpFilePart;
+
+    if (GetFullPathNameW(relPath,maxLength,absPath,&lpFilePart) == 0)
+        return NULL;
+
+    return absPath;
+}
diff --git a/lib/msvcrt/stdlib/witoa.c b/lib/msvcrt/stdlib/witoa.c
new file mode 100644 (file)
index 0000000..6ff4d2f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/stdlib/itoa.c
+ * PURPOSE:     converts a integer to ascii
+ * PROGRAMER:   
+ * UPDATE HISTORY:
+ *              1995: Created
+ *              1998: Added ltoa Boudewijn Dekker
+ */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/errno.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+
+
+char* _i64toa(__int64 value, char* string, int radix)
+{
+  char tmp[65];
+  char *tp = tmp;
+  int i;
+  unsigned v;
+  int sign;
+  char *sp;
+
+  if (radix > 36 || radix <= 1)
+  {
+    __set_errno(EDOM);
+    return 0;
+  }
+
+  sign = (radix == 10 && value < 0);
+  if (sign)
+    v = -value;
+  else
+    v = (unsigned)value;
+  while (v || tp == tmp)
+  {
+    i = v % radix;
+    v = v / radix;
+    if (i < 10)
+      *tp++ = i+'0';
+    else
+      *tp++ = i + 'a' - 10;
+  }
+
+  if (string == 0)
+    string = (char *)malloc((tp-tmp)+sign+1);
+  sp = string;
+
+  if (sign)
+    *sp++ = '-';
+  while (tp > tmp)
+    *sp++ = *--tp;
+  *sp = 0;
+  return string;
+}
+
+char* _ui64toa(unsigned __int64 value, char* string, int radix)
+{
+  char tmp[65];
+  char *tp = tmp;
+  long i;
+  unsigned long v = value;
+  char *sp;
+
+  if (radix > 36 || radix <= 1)
+  {
+    __set_errno(EDOM);
+    return 0;
+  }
+
+  while (v || tp == tmp)
+  {
+    i = v % radix;
+    v = v / radix;
+    if (i < 10)
+      *tp++ = i+'0';
+    else
+      *tp++ = i + 'a' - 10;
+  }
+
+  if (string == 0)
+    string = (char *)malloc((tp-tmp)+1);
+  sp = string;
+
+  while (tp > tmp)
+    *sp++ = *--tp;
+  *sp = 0;
+  return string;
+}
diff --git a/lib/msvcrt/stdlib/witow.c b/lib/msvcrt/stdlib/witow.c
new file mode 100644 (file)
index 0000000..4e0c089
--- /dev/null
@@ -0,0 +1,90 @@
+/* $Id$
+ *
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/stdlib/itow.c
+ * PURPOSE:     converts a integer to wchar_t
+ * PROGRAMER:   
+ * UPDATE HISTORY:
+ *              1995: Created
+ *              1998: Added ltoa Boudewijn Dekker
+ *              2000: derived from ./itoa.c by ea
+ */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/errno.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _i64tow(__int64 value, wchar_t* string, int radix)
+{
+  wchar_t tmp[65];
+  wchar_t* tp = tmp;
+  int i;
+  unsigned v;
+  int sign;
+  wchar_t* sp;
+
+  if (radix > 36 || radix <= 1) {
+    __set_errno(EDOM);
+    return 0;
+  }
+
+  sign = (radix == 10 && value < 0);
+  if (sign)
+    v = -value;
+  else
+    v = (unsigned)value;
+  while (v || tp == tmp) {
+    i = v % radix;
+    v = v / radix;
+    if (i < 10)
+      *tp++ = i+L'0';
+    else
+      *tp++ = i + L'a' - 10;
+  }
+
+  if (string == 0)
+    string = (wchar_t*)malloc(((tp-tmp)+sign+1)*sizeof(wchar_t));
+  sp = string;
+
+  if (sign)
+    *sp++ = L'-';
+  while (tp > tmp)
+    *sp++ = *--tp;
+  *sp = 0;
+  return string;
+}
+
+wchar_t* _ui64tow(unsigned __int64 value, wchar_t* string, int radix)
+{
+  wchar_t tmp[65];
+  wchar_t* tp = tmp;
+  long i;
+  unsigned long v = value;
+  wchar_t* sp;
+
+  if (radix > 36 || radix <= 1) {
+    __set_errno(EDOM);
+    return 0;
+  }
+
+  while (v || tp == tmp) {
+    i = v % radix;
+    v = v / radix;
+    if (i < 10)
+      *tp++ = i+L'0';
+    else
+      *tp++ = i + L'a' - 10;
+  }
+
+  if (string == 0)
+    string = (wchar_t*)malloc(((tp-tmp)+1)*sizeof(wchar_t));
+  sp = string;
+
+  while (tp > tmp)
+    *sp++ = *--tp;
+  *sp = 0;
+  return string;
+}
diff --git a/lib/msvcrt/stdlib/wmakpath.c b/lib/msvcrt/stdlib/wmakpath.c
new file mode 100644 (file)
index 0000000..9367bdc
--- /dev/null
@@ -0,0 +1,33 @@
+/* $Id$
+ */
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+
+void _wmakepath(wchar_t* path, const wchar_t* drive, const wchar_t* dir, const wchar_t* fname, const wchar_t* ext)
+{
+    int dir_len;
+
+    if ((drive != NULL) && (*drive)) {
+        wcscpy(path, drive);
+        wcscat(path, L":");
+    } else {
+        (*path) = 0;
+    }
+
+    if (dir != NULL) {
+        wcscat(path, dir);
+        dir_len = wcslen(dir);
+        if (dir_len && *(dir + dir_len - 1) != L'\\')
+            wcscat(path, L"\\");
+    }
+
+    if (fname != NULL) {
+        wcscat(path, fname);
+        if (ext != NULL && *ext != 0) {
+            if (*ext != L'.')
+                wcscat(path, L".");
+            wcscat(path, ext);
+        }
+    }
+}
diff --git a/lib/msvcrt/stdlib/wputenv.c b/lib/msvcrt/stdlib/wputenv.c
new file mode 100644 (file)
index 0000000..08bfff5
--- /dev/null
@@ -0,0 +1,31 @@
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+extern int BlockEnvToEnviron(); // defined in misc/dllmain.c
+
+int _wputenv(const wchar_t* val)
+{
+    wchar_t* buffer;
+    wchar_t* epos;
+    int res;
+
+    DPRINT("_wputenv('%S')\n", val);
+    epos = wcsrchr(val, L'=');
+    if (epos == NULL)
+        return -1;
+    buffer = (char*)malloc((epos - val + 1) * sizeof(wchar_t));
+    if (buffer == NULL)
+        return -1;
+    wcsncpy(buffer, val, epos - val);
+    buffer[epos - val] = 0;
+    res = SetEnvironmentVariableW(buffer, epos+1);
+    free(buffer);
+    if (BlockEnvToEnviron())
+        return 0;
+    return  res;
+}
diff --git a/lib/msvcrt/stdlib/wsenv.c b/lib/msvcrt/stdlib/wsenv.c
new file mode 100644 (file)
index 0000000..24fe949
--- /dev/null
@@ -0,0 +1,32 @@
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+void _wsearchenv(const wchar_t* file,const wchar_t* var,wchar_t* path)
+{
+    wchar_t* env = _wgetenv(var);
+    wchar_t* x;
+    wchar_t* y;
+    wchar_t* FilePart;
+
+    DPRINT("_wsearchenv()\n");
+    x = wcschr(env,L'=');
+    if ( x != NULL ) {
+        *x = 0;
+        x++;
+    }
+    y = wcschr(env,L';');
+    while ( y != NULL ) {
+        *y = 0;
+        if ( SearchPathW(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) {
+            return;
+        }
+        x = y+1;
+        y = wcschr(env,L';');
+    }
+    return;
+}
diff --git a/lib/msvcrt/stdlib/wsplitp.c b/lib/msvcrt/stdlib/wsplitp.c
new file mode 100644 (file)
index 0000000..7d20667
--- /dev/null
@@ -0,0 +1,48 @@
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+
+void _wsplitpath(const wchar_t* path, wchar_t* drive, wchar_t* dir, wchar_t* fname, wchar_t* ext)
+{
+    wchar_t* tmp_drive;
+    wchar_t* tmp_dir;
+    wchar_t* tmp_ext;
+
+    tmp_drive = (wchar_t*)wcschr(path,L':');
+    if ( tmp_drive != (wchar_t*)NULL ) {
+        wcsncpy(drive,tmp_drive-1,1);
+        *(drive+1) = 0;
+    }
+    else {
+        *drive = 0;
+        tmp_drive = (wchar_t*)path;
+    }
+
+    tmp_dir = (wchar_t*)wcsrchr(path,L'\\');
+    if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) {
+        wcsncpy(dir,tmp_drive+1,tmp_dir - tmp_drive);
+        *(dir + (tmp_dir - tmp_drive)) = 0;
+    }
+    else
+        *dir =0;
+
+    tmp_ext = (wchar_t*)wcsrchr(path,L'.');
+    if ( tmp_ext != NULL ) {
+        wcscpy(ext,tmp_ext);
+    }
+    else
+    {
+        *ext = 0;
+        tmp_ext = (wchar_t*)path+wcslen(path);
+    }
+
+    if ( tmp_dir != NULL ) {
+        wcsncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1);
+        *(fname + (tmp_ext - tmp_dir -1)) = 0;
+    }
+    else
+    {
+        wcsncpy(fname,path,tmp_ext - path);
+        *(fname+(tmp_ext-path))=0;
+    }
+}
diff --git a/lib/msvcrt/string/strncoll.c b/lib/msvcrt/string/strncoll.c
new file mode 100644 (file)
index 0000000..161b3fd
--- /dev/null
@@ -0,0 +1,17 @@
+#include <windows.h>
+#include <msvcrt/string.h>
+
+/* Compare S1 and S2, returning less than, equal to or
+   greater than zero if the collated form of S1 is lexicographically
+   less than, equal to or greater than the collated form of S2.  */
+
+
+int _strncoll(const char* s1, const char* s2, size_t c)
+{
+    return strncmp(s1, s2, c);
+}
+
+int _strnicoll(const char* s1, const char* s2, size_t c)
+{
+    return _strnicmp(s1, s2, c);
+}
diff --git a/lib/msvcrt/sys_stat/fstati64.c b/lib/msvcrt/sys_stat/fstati64.c
new file mode 100644 (file)
index 0000000..ebde056
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id$
+ *
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/sys/fstat.c
+ * PURPOSE:     Gather file information
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/sys/types.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/string.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+__int64 _fstati64(int fd, struct _stati64* statbuf)
+{
+  BY_HANDLE_FILE_INFORMATION FileInformation;
+  DWORD dwFileType;
+  void *handle;
+
+  if (!statbuf)
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  if ((void*)-1 == (handle = _get_osfhandle(fd)))
+  {
+    __set_errno(EBADF);
+    return -1;
+  }
+  
+  fflush(NULL);
+
+  memset(statbuf, 0, sizeof(struct _stati64));
+
+  dwFileType = GetFileType(handle);
+
+  if (dwFileType == FILE_TYPE_DISK)
+  {
+    if (!GetFileInformationByHandle(handle,&FileInformation))
+    {
+       __set_errno(EBADF);
+       return -1;
+    }
+    statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL);
+    statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL);
+    statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL);
+
+    statbuf->st_dev = fd;
+    statbuf->st_size = (((__int64)FileInformation.nFileSizeHigh) << 32) +
+             FileInformation.nFileSizeLow;
+    statbuf->st_mode = S_IREAD;
+    if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
+      statbuf->st_mode |= S_IFDIR;
+    else
+      statbuf->st_mode |= S_IFREG;
+    if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE;
+  }
+  else if (dwFileType == FILE_TYPE_CHAR)
+  {
+    statbuf->st_dev = fd;
+    statbuf->st_mode = S_IFCHR;
+  }
+  else if (dwFileType == FILE_TYPE_PIPE)
+  {
+    statbuf->st_dev = fd;
+    statbuf->st_mode = S_IFIFO;
+  }
+  else
+  {
+    // dwFileType is FILE_TYPE_UNKNOWN or has a bad value
+    __set_errno(EBADF);
+    return -1;
+  }
+  return 0;
+}
diff --git a/lib/msvcrt/sys_stat/wstat.c b/lib/msvcrt/sys_stat/wstat.c
new file mode 100644 (file)
index 0000000..8d37299
--- /dev/null
@@ -0,0 +1,146 @@
+#include <windows.h>
+#include <msvcrt/sys/types.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/string.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wstat (const wchar_t *path, struct stat *buffer)
+{
+  HANDLE findHandle;
+  WIN32_FIND_DATAW findData;
+
+  if (!buffer)
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  if(wcschr(path, L'*') || wcschr(path, L'?'))
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  findHandle = FindFirstFileW(path, &findData);
+  if (findHandle == INVALID_HANDLE_VALUE)
+  {
+    __set_errno(ENOENT);
+    return -1;
+  }
+
+  FindClose(findHandle);
+
+  memset (buffer, 0, sizeof(struct stat));
+
+  buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+  buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+  buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+//  statbuf->st_dev = fd;
+  buffer->st_size = findData.nFileSizeLow;
+  buffer->st_mode = S_IREAD;
+  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
+    buffer->st_mode |= S_IFDIR;
+  else
+    buffer->st_mode |= S_IFREG;
+  if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 
+    buffer->st_mode |= S_IWRITE;
+
+  return 0;
+}
+
+__int64 _stati64 (const char *path, struct _stati64 *buffer)
+{
+  HANDLE findHandle;
+  WIN32_FIND_DATAA findData;
+
+  if (!buffer)
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  if(strchr(path, '*') || strchr(path, '?'))
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  findHandle = FindFirstFileA(path, &findData);
+  if (findHandle == INVALID_HANDLE_VALUE)
+  {
+    __set_errno(ENOENT);
+    return -1;
+  }
+
+  FindClose(findHandle);
+
+  memset (buffer, 0, sizeof(struct stat));
+
+  buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+  buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+  buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+//  statbuf->st_dev = fd;
+  buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) +
+             findData.nFileSizeLow;
+  buffer->st_mode = S_IREAD;
+  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
+    buffer->st_mode |= S_IFDIR;
+  else
+    buffer->st_mode |= S_IFREG;
+  if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 
+    buffer->st_mode |= S_IWRITE;
+
+  return 0;
+}
+
+__int64 _wstati64 (const wchar_t *path, struct _stati64 *buffer)
+{
+  HANDLE findHandle;
+  WIN32_FIND_DATAW findData;
+
+  if (!buffer)
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  if(wcschr(path, L'*') || wcschr(path, L'?'))
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  findHandle = FindFirstFileW(path, &findData);
+  if (findHandle == INVALID_HANDLE_VALUE)
+  {
+    __set_errno(ENOENT);
+    return -1;
+  }
+
+  FindClose(findHandle);
+
+  memset (buffer, 0, sizeof(struct stat));
+
+  buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+  buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+  buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+//  statbuf->st_dev = fd;
+  buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) +
+             findData.nFileSizeLow;
+  buffer->st_mode = S_IREAD;
+  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
+    buffer->st_mode |= S_IFDIR;
+  else
+    buffer->st_mode |= S_IFREG;
+  if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 
+    buffer->st_mode |= S_IWRITE;
+
+  return 0;
+}
diff --git a/lib/msvcrt/time/tz_vars.c b/lib/msvcrt/time/tz_vars.c
new file mode 100644 (file)
index 0000000..aad68dc
--- /dev/null
@@ -0,0 +1,21 @@
+#include <msvcrt/string.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/stdlib.h>
+
+
+int _daylight;
+int _timezone;
+
+
+void _set_daylight_export(int value)
+{
+    _daylight =  value;
+}
+
+void _set_timezone_export(int value)
+{
+    _timezone =  value;
+}
+
+
+
diff --git a/lib/msvcrt/time/wctime.c b/lib/msvcrt/time/wctime.c
new file mode 100644 (file)
index 0000000..08ad9cd
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/* This file has been modified by DJ Delorie.  These modifications are
+** Copyright (C) 1995 DJ Delorie, 24 Kirsten Ave, Rochester NH,
+** 03867-2954, USA.
+*/
+
+/*
+ * Copyright (c) 1987, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <msvcrt/fcntl.h>
+#include <msvcrt/time.h>
+#include <windows.h>
+#include "tzfile.h"
+
+
+wchar_t* _wasctime(const struct tm* timeptr)
+{
+#ifdef __GNUC__
+  static const wchar_t wday_name[DAYSPERWEEK][3] = {
+    L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
+  };
+  static const wchar_t mon_name[MONSPERYEAR][3] = {
+    L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+    L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+  };
+#else
+  static const wchar_t wday_name[DAYSPERWEEK][4] = {
+    L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
+  };
+  static const wchar_t mon_name[MONSPERYEAR][4] = {
+    L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+    L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+  };
+#endif
+  static wchar_t result[26];
+
+  (void)swprintf(result, L"%.3s %.3s%3d %02d:%02d:%02d %d\n",
+         wday_name[timeptr->tm_wday],
+         mon_name[timeptr->tm_mon],
+         timeptr->tm_mday, timeptr->tm_hour,
+         timeptr->tm_min, timeptr->tm_sec,
+         TM_YEAR_BASE + timeptr->tm_year);
+  return result;
+}
+
+
+wchar_t* _wctime(const time_t* const timep)
+{
+    return _wasctime(localtime(timep));
+}
diff --git a/lib/msvcrt/time/wstrdate.c b/lib/msvcrt/time/wstrdate.c
new file mode 100644 (file)
index 0000000..3d5a3ba
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/time/strtime.c
+ * PURPOSE:     Fills a buffer with a formatted date representation
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+#include <msvcrt/time.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _wstrdate(const wchar_t* datestr)
+{
+    time_t t;
+    struct tm* d;
+    wchar_t* dt = (wchar_t*)datestr;
+
+    if (datestr == NULL) {
+        __set_errno(EINVAL);
+        return NULL;
+    }
+    t = time(NULL);
+    d = localtime(&t);
+    swprintf(dt,L"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year);
+    return dt;
+}
diff --git a/lib/msvcrt/time/wstrtime.c b/lib/msvcrt/time/wstrtime.c
new file mode 100644 (file)
index 0000000..8af7e56
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/msvcrt/time/strtime.c
+ * PURPOSE:     Fills a buffer with a formatted time representation
+ * PROGRAMER:   Boudewijn Dekker
+ * UPDATE HISTORY:
+ *              28/12/98: Created
+ */
+#include <msvcrt/time.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _wstrtime(wchar_t* buf)
+{
+    time_t t;
+    struct tm* d;
+    wchar_t* dt = (wchar_t*)buf;
+
+    if ( buf == NULL ) {
+        __set_errno(EINVAL);
+        return NULL;
+    }
+    t = time(NULL);
+    d = localtime(&t);
+    swprintf(dt,L"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec);
+    return dt;
+}
diff --git a/lib/ntdll/ldr/res.c b/lib/ntdll/ldr/res.c
new file mode 100644 (file)
index 0000000..f3f7f35
--- /dev/null
@@ -0,0 +1,268 @@
+/* $Id$
+ * 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            lib/ntdll/ldr/res.c
+ * PURPOSE:         Resource access for PE executables
+ * PROGRAMMERS:     Jean Michault
+ *                  Rex Jolliff (rex@lvcablemodem.com)
+ *                  Robert Dickenson (robd@mok.lvcm.com)
+ */
+
+/*
+ * TODO:
+ *  - any comments ??
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <reactos/config.h>
+#include <ddk/ntddk.h>
+#include <windows.h>
+#include <string.h>
+#include <wchar.h>
+#include <ntdll/ldr.h>
+#include <ntos/minmax.h>
+
+#define NDEBUG
+#include <ntdll/ntdll.h>
+
+/* PROTOTYPES ****************************************************************/
+
+
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+       Status = LdrFindResource_U (hModule,
+                                   &ResourceInfo,
+                                   RESOURCE_DATA_LEVEL,
+                                   &ResourceDataEntry);
+ */
+NTSTATUS STDCALL
+LdrFindResource_U(PVOID BaseAddress,
+                  PLDR_RESOURCE_INFO ResourceInfo,
+                  ULONG Level,
+                  PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
+{
+    PIMAGE_RESOURCE_DIRECTORY ResDir;
+    PIMAGE_RESOURCE_DIRECTORY ResBase;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG EntryCount;
+    PWCHAR ws;
+    ULONG i;
+    ULONG Id;
+
+    //DPRINT("LdrFindResource_U()\n");
+    DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry);
+
+    /* Get the pointer to the resource directory */
+    ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
+                      TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
+    if (ResDir == NULL) {
+        return STATUS_RESOURCE_DATA_NOT_FOUND;
+    }
+
+    DPRINT("ResourceDirectory: %x  Size: %d\n", (ULONG)ResDir, (int)i);
+
+    ResBase = ResDir;
+
+    /* Let's go into resource tree */
+    for (i = 0; i < Level; i++) {
+        DPRINT("ResDir: %x  Level: %d\n", (ULONG)ResDir, i);
+
+        Id = ((PULONG)ResourceInfo)[i];
+//     ResourceInfo.Type = (ULONG)lpType;
+//     ResourceInfo.Name = (ULONG)lpName;
+//     ResourceInfo.Language = (ULONG)wLanguage;
+
+        EntryCount = ResDir->NumberOfNamedEntries;
+        DPRINT("    Id: %d  NumberOfNamedEntries: %d\n", Id, EntryCount);
+        ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
+        //DPRINT("ResEntry %x\n", (ULONG)ResEntry);
+        if (Id & 0xFFFF0000) {
+            /* Resource name is a unicode string */
+            DPRINT("ResEntry %x - Resource name is a unicode string\n", (ULONG)ResEntry);
+            DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+            for (; EntryCount--; ResEntry++) {
+                /* Scan entries for equal name */
+                if (ResEntry->Name & 0x80000000) {
+                    ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
+                    if (!wcsncmp((PWCHAR)Id, ws + 1, *ws) &&
+                          wcslen((PWCHAR)Id) == (int)*ws) {
+                        goto found;
+                    }
+                }
+            }
+        } else {
+            /* We use ID number instead of string */
+            DPRINT("ResEntry %x - Resource ID number instead of string\n", (ULONG)ResEntry);
+            DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+            ResEntry += EntryCount;
+            EntryCount = ResDir->NumberOfIdEntries;
+            DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+            for (; EntryCount--; ResEntry++) {
+                /* Scan entries for equal name */
+                DPRINT("EntryCount %d  ResEntry %x\n", (ULONG)EntryCount, ResEntry);
+                DPRINT("ResEntry->Name %x  Id %x\n", (ULONG)ResEntry->Name, Id);
+                if (ResEntry->Name == Id) {
+                    DPRINT("ID entry found %x\n", Id);
+                    goto found;
+                }
+            }
+        }
+
+        //DPRINT("Error %lu\n", i);
+
+        switch (i) {
+        case 0:
+            DPRINT("Error %lu - STATUS_RESOURCE_TYPE_NOT_FOUND\n", i);
+            return STATUS_RESOURCE_TYPE_NOT_FOUND;
+        case 1:
+            DPRINT("Error %lu - STATUS_RESOURCE_NAME_NOT_FOUND\n", i);
+            return STATUS_RESOURCE_NAME_NOT_FOUND;
+        case 2:
+            if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
+                /* Use the first available language */
+                ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
+                break;
+            }
+            DPRINT("Error %lu - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
+            return STATUS_RESOURCE_LANG_NOT_FOUND;
+         case 3:
+            DPRINT("Error %lu - STATUS_RESOURCE_DATA_NOT_FOUND\n", i);
+            return STATUS_RESOURCE_DATA_NOT_FOUND;
+         default:
+            DPRINT("Error %lu - STATUS_INVALID_PARAMETER\n", i);
+            return STATUS_INVALID_PARAMETER;
+        }
+found:;
+        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
+                     (ResEntry->OffsetToData & 0x7FFFFFFF));
+    }
+    DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
+
+    if (ResourceDataEntry) {
+        *ResourceDataEntry = (PVOID)ResDir;
+    }
+    return Status;
+}
+
+
+NTSTATUS STDCALL
+LdrAccessResource(IN  PVOID BaseAddress,
+                  IN  PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
+                  OUT PVOID* Resource OPTIONAL,
+                  OUT PULONG Size OPTIONAL)
+{
+    PIMAGE_SECTION_HEADER Section;
+    PIMAGE_NT_HEADERS NtHeader;
+    ULONG SectionRva;
+    ULONG SectionVa;
+    ULONG DataSize;
+    ULONG Offset = 0;
+    ULONG Data;
+
+    Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress,
+                           TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize);
+    if (Data == 0) {
+        return STATUS_RESOURCE_DATA_NOT_FOUND;
+    }
+    if ((ULONG)BaseAddress & 1) {
+        /* loaded as ordinary file */
+        NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
+        Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+        Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
+        if (Section == NULL) {
+            return STATUS_RESOURCE_DATA_NOT_FOUND;
+        }
+        if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) {
+            SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
+            SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
+            Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
+        }
+    }
+    if (Resource) {
+        *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
+    }
+    if (Size) {
+        *Size = ResourceDataEntry->Size;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+LdrFindResourceDirectory_U(IN PVOID BaseAddress,
+                           WCHAR** name,
+                           DWORD level,
+                           OUT PVOID* addr)
+{
+    PIMAGE_RESOURCE_DIRECTORY ResDir;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
+    ULONG EntryCount;
+    ULONG i;
+    NTSTATUS Status = STATUS_SUCCESS;
+    WCHAR* ws;
+
+    /* Get the pointer to the resource directory */
+    ResDir = (PIMAGE_RESOURCE_DIRECTORY)
+    RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
+    if (ResDir == NULL) {
+        return STATUS_RESOURCE_DATA_NOT_FOUND;
+    }
+
+    /* Let's go into resource tree */
+    for (i = 0; i < level; i++, name++) {
+        EntryCount = ResDir->NumberOfNamedEntries;
+        ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
+        if ((ULONG)(*name) & 0xFFFF0000) {
+            /* Resource name is a unicode string */
+            for (; EntryCount--; ResEntry++) {
+                /* Scan entries for equal name */
+                if (ResEntry->Name & 0x80000000) {
+                    ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
+                    if (!wcsncmp(*name, ws + 1, *ws) && wcslen(*name) == (int)*ws) {
+                        goto found;
+                    }
+                }
+            }
+        } else {
+            /* We use ID number instead of string */
+            ResEntry += EntryCount;
+            EntryCount = ResDir->NumberOfIdEntries;
+            for (; EntryCount--; ResEntry++) {
+                /* Scan entries for equal name */
+                if (ResEntry->Name == (ULONG)(*name))
+                    goto found;
+            }
+        }
+        switch (i) {
+        case 0:
+            return STATUS_RESOURCE_TYPE_NOT_FOUND;
+        case 1:
+            return STATUS_RESOURCE_NAME_NOT_FOUND;
+        case 2:
+            Status = STATUS_RESOURCE_LANG_NOT_FOUND;
+            /* Just use first language entry */
+            if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
+                ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
+                break;
+            }
+            return Status;
+        case 3:
+            return STATUS_RESOURCE_DATA_NOT_FOUND;
+        default:
+            return STATUS_INVALID_PARAMETER;
+        }
+found:;
+        ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
+    }
+    if (addr) {
+        *addr = (PVOID)ResDir;
+    }
+    return Status;
+}
+
+/* EOF */
diff --git a/lib/ntdll/rtl/i386/.cvsignore b/lib/ntdll/rtl/i386/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/shell32/control/.cvsignore b/lib/shell32/control/.cvsignore
new file mode 100644 (file)
index 0000000..33df5bf
--- /dev/null
@@ -0,0 +1,6 @@
+control.exe
+control.coff
+control.sym
+control.dsp
+control.dsw
+*.o
diff --git a/lib/shell32/control/makefile b/lib/shell32/control/makefile
new file mode 100644 (file)
index 0000000..f25a88f
--- /dev/null
@@ -0,0 +1,64 @@
+#
+#  ReactOS control
+#
+#  Makefile
+#
+#  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program 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 General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+       
+PATH_TO_TOP = ..
+
+TARGET = control
+
+BASE_CFLAGS = -DGCC -D_WIN32_IE=0x0400 -DUNICODE -D_UNICODE
+
+RCFLAGS = -DGCC -D_WIN32_IE=0x0400
+
+
+OBJS = framewnd.o \
+        listview.o \
+        main.o
+
+LIBS = -lgdi32 -luser32 -lkernel32 -lcomctl32
+
+all:   $(TARGET).exe
+
+$(TARGET).res: $(TARGET).rc
+
+$(TARGET).exe: $(OBJS) $(TARGET).coff
+       $(CC) -Wl,--subsystem,windows -o $(TARGET).exe $(OBJS) $(TARGET).coff $(LIBS)
+       $(NM) --numeric-sort $(TARGET).exe > $(TARGET).sym
+
+
+main.h:                resource.h
+
+main.o:                main.c main.h framewnd.h
+
+framewnd.o:    framewnd.c framewnd.h listview.h main.h
+
+listview.o:    listview.c listview.h main.h 
+
+about.o:       about.c about.h main.h
+
+
+clean:
+       - $(RM) $(OBJS)
+       - $(RM) $(TARGET).exe
+       - $(RM) $(TARGET).sym
+       - $(RM) $(TARGET).coff
+
+include $(PATH_TO_TOP)/rules.mak
diff --git a/lib/version/misc/.cvsignore b/lib/version/misc/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/winedbgc/.cvsignore b/lib/winedbgc/.cvsignore
new file mode 100644 (file)
index 0000000..08743c3
--- /dev/null
@@ -0,0 +1,4 @@
+*.sym
+*.coff
+*.dll
+*.o
diff --git a/lib/winedbgc/Makefile b/lib/winedbgc/Makefile
new file mode 100644 (file)
index 0000000..057066d
--- /dev/null
@@ -0,0 +1,35 @@
+# $Id$
+
+PATH_TO_TOP = ../..
+
+TARGET_DEFONLY = yes
+
+TARGET_TYPE = dynlink
+
+TARGET_NAME = winedbgc
+
+#TARGET_CFLAGS = -fno-rtti -D_ROS_ -D__WINE__
+
+#TARGET_CFLAGS = -g -D__NTDLL__
+TARGET_CFLAGS = -D__NTDLL__
+
+TARGET_LFLAGS = -Wl,--file-alignment,0x1000 \
+  -Wl,--section-alignment,0x1000 \
+  -nostartfiles
+
+TARGET_BASE = 0x77a90000
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = \
+       debug.o \
+       libmain.o \
+       porting.o \
+       winedbgc.o \
+       winedbgc.dll.dbg.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
diff --git a/lib/winedbgc/debug.c b/lib/winedbgc/debug.c
new file mode 100644 (file)
index 0000000..9dff056
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Management of the debugging channels
+ *
+ * Copyright 2000 Alexandre Julliard
+ *
+ * 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
+ */
+/*
+#include <ntddk.h>
+#include <wine/debugtools.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+ */
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "porting.h"
+/*
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "wine/debug.h"
+#include "wine/library.h"
+#include "wine/unicode.h"
+ */
+struct dll
+{
+    struct dll   *next;        /* linked list of dlls */
+    struct dll   *prev;
+    char * const *channels;    /* array of channels */
+    int           nb_channels; /* number of channels in array */
+};
+
+static struct dll *first_dll;
+
+struct debug_option
+{
+    struct debug_option *next;       /* next option in list */
+    unsigned char        set;        /* bits to set */
+    unsigned char        clear;      /* bits to clear */
+    char                 name[14];   /* channel name, or empty for "all" */
+};
+
+static struct debug_option *first_option;
+static struct debug_option *last_option;
+
+static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
+
+static int cmp_name( const void *p1, const void *p2 )
+{
+    const char *name = p1;
+    const char * const *chan = p2;
+    return strcmp( name, *chan + 1 );
+}
+
+/* apply a debug option to the channels of a given dll */
+static void apply_option( struct dll *dll, const struct debug_option *opt )
+{
+    if (opt->name[0])
+    {
+        char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
+                               sizeof(*dll->channels), cmp_name );
+        if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
+    }
+    else /* all */
+    {
+        int i;
+        for (i = 0; i < dll->nb_channels; i++)
+            dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
+    }
+}
+
+/* register a new set of channels for a dll */
+void *__wine_dbg_register( char * const *channels, int nb )
+{
+    struct debug_option *opt = first_option;
+    struct dll *dll = malloc( sizeof(*dll) );
+    if (dll)
+    {
+        dll->channels = channels;
+        dll->nb_channels = nb;
+        dll->prev = NULL;
+        if ((dll->next = first_dll)) dll->next->prev = dll;
+        first_dll = dll;
+
+        /* apply existing options to this dll */
+        while (opt)
+        {
+            apply_option( dll, opt );
+            opt = opt->next;
+        }
+    }
+    return dll;
+}
+
+
+/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
+void __wine_dbg_unregister( void *channel )
+{
+    struct dll *dll = channel;
+    if (dll)
+    {
+        if (dll->next) dll->next->prev = dll->prev;
+        if (dll->prev) dll->prev->next = dll->next;
+        else first_dll = dll->next;
+        free( dll );
+    }
+}
+
+
+/* add a new debug option at the end of the option list */
+void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
+{
+    struct dll *dll = first_dll;
+    struct debug_option *opt;
+
+    if (!(opt = malloc( sizeof(*opt) ))) return;
+    opt->next  = NULL;
+    opt->set   = set;
+    opt->clear = clear;
+    strncpy( opt->name, name, sizeof(opt->name) );
+    opt->name[sizeof(opt->name)-1] = 0;
+    if (last_option) last_option->next = opt;
+    else first_option = opt;
+    last_option = opt;
+
+    /* apply option to all existing dlls */
+    while (dll)
+    {
+        apply_option( dll, opt );
+        dll = dll->next;
+    }
+}
+
+/* parse a set of debugging option specifications and add them to the option list */
+int wine_dbg_parse_options( const char *str )
+{
+    char *p, *opt, *next, *options;
+    int i, errors = 0;
+
+    if (!(options = strdup(str))) return -1;
+    for (opt = options; opt; opt = next)
+    {
+        unsigned char set = 0, clear = 0;
+
+        if ((next = strchr( opt, ',' ))) *next++ = 0;
+
+        p = opt + strcspn( opt, "+-" );
+        if (!p[0] || !p[1])  /* bad option, skip it */
+        {
+            errors++;
+            continue;
+        }
+
+        if (p > opt)
+        {
+            for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
+            {
+                int len = strlen(debug_classes[i]);
+                if (len != (p - opt)) continue;
+                if (!memcmp( opt, debug_classes[i], len ))  /* found it */
+                {
+                    if (*p == '+') set |= 1 << i;
+                    else clear |= 1 << i;
+                    break;
+                }
+            }
+            if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
+            {
+                errors++;
+                continue;
+            }
+        }
+        else
+        {
+            if (*p == '+') set = ~0;
+            else clear = ~0;
+        }
+        p++;
+        if (!strcmp( p, "all" )) p = "";  /* empty string means all */
+        wine_dbg_add_option( p, set, clear );
+    }
+    free( options );
+    return errors;
+}
+
+#ifdef __WINE__
+
+/* varargs wrapper for __wine_dbg_vprintf */
+int wine_dbg_printf( const char *format, ... )
+{
+    int ret;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = __wine_dbg_vprintf( format, valist );
+    va_end(valist);
+    return ret;
+}
+
+
+/* varargs wrapper for __wine_dbg_vlog */
+int wine_dbg_log( int cls, const char *channel, const char *func, const char *format, ... )
+{
+    int ret;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = __wine_dbg_vlog( cls, channel, func, format, valist );
+    va_end(valist);
+    return ret;
+}
+
+#endif /*__WINE__*/
+
+/* allocate some tmp string space */
+/* FIXME: this is not 100% thread-safe */
+static char *get_tmp_space( int size )
+{
+    static char *list[32];
+    static long pos;
+    char *ret;
+    int idx;
+
+    idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
+    if ((ret = realloc( list[idx], size ))) list[idx] = ret;
+    return ret;
+}
+
+
+/* default implementation of wine_dbgstr_an */
+static const char *default_dbgstr_an( const char *str, int n )
+{
+    char *dst, *res;
+
+    if (!HIWORD(str))
+    {
+        if (!str) return "(null)";
+        res = get_tmp_space( 6 );
+        sprintf( res, "#%04x", LOWORD(str) );
+        return res;
+    }
+    if (n == -1) n = strlen(str);
+    if (n < 0) n = 0;
+    else if (n > 200) n = 200;
+    dst = res = get_tmp_space( n * 4 + 6 );
+    *dst++ = '"';
+    while (n-- > 0)
+    {
+        unsigned char c = *str++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"':  *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                *dst++ = '0' + ((c >> 6) & 7);
+                *dst++ = '0' + ((c >> 3) & 7);
+                *dst++ = '0' + ((c >> 0) & 7);
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*str)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst = 0;
+    return res;
+}
+
+
+/* default implementation of wine_dbgstr_wn */
+static const char *default_dbgstr_wn( const WCHAR *str, int n )
+{
+    char *dst, *res;
+
+    if (!HIWORD(str))
+    {
+        if (!str) return "(null)";
+        res = get_tmp_space( 6 );
+        sprintf( res, "#%04x", LOWORD(str) );
+        return res;
+    }
+    if (n == -1) n = strlenW(str);
+    if (n < 0) n = 0;
+    else if (n > 200) n = 200;
+    dst = res = get_tmp_space( n * 5 + 7 );
+    *dst++ = 'L';
+    *dst++ = '"';
+    while (n-- > 0)
+    {
+        WCHAR c = *str++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"':  *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                sprintf(dst,"%04x",c);
+                dst+=4;
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*str)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst = 0;
+    return res;
+}
+
+
+/* default implementation of wine_dbgstr_guid */
+static const char *default_dbgstr_guid( const struct _GUID *id )
+{
+    char *str;
+
+    if (!id) return "(null)";
+    if (!((int)id >> 16))
+    {
+        str = get_tmp_space( 12 );
+        sprintf( str, "<guid-0x%04x>", (int)id & 0xffff );
+    }
+    else
+    {
+        str = get_tmp_space( 40 );
+        sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+                 id->Data1, id->Data2, id->Data3,
+                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+    }
+    return str;
+}
+
+
+/* default implementation of wine_dbg_vprintf */
+static int default_dbg_vprintf( const char *format, va_list args )
+{
+    return vfprintf( stderr, format, args );
+}
+
+
+/* default implementation of wine_dbg_vlog */
+static int default_dbg_vlog( int cls, const char *channel, const char *func,
+                             const char *format, va_list args )
+{
+    int ret = 0;
+
+    if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
+        ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
+    if (format)
+        ret += __wine_dbg_vprintf( format, args );
+    return ret;
+}
+
+
+/* exported function pointers so that debugging functions can be redirected at run-time */
+
+const char * (*__wine_dbgstr_an)( const char * s, int n ) = default_dbgstr_an;
+const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n ) = default_dbgstr_wn;
+const char * (*__wine_dbgstr_guid)( const struct _GUID *id ) = default_dbgstr_guid;
+int (*__wine_dbg_vprintf)( const char *format, va_list args ) = default_dbg_vprintf;
+int (*__wine_dbg_vlog)( int cls, const char *channel, const char *function,
+                        const char *format, va_list args ) = default_dbg_vlog;
+
+/* wrappers to use the function pointers */
+
+#ifdef __WINE__
+
+const char *wine_dbgstr_guid( const struct _GUID *id )
+{
+    return __wine_dbgstr_guid(id);
+}
+
+const char *wine_dbgstr_an( const char * s, int n )
+{
+    return __wine_dbgstr_an(s, n);
+}
+
+const char *wine_dbgstr_wn( const WCHAR *s, int n )
+{
+    return __wine_dbgstr_wn(s, n);
+}
+
+const char *wine_dbgstr_a( const char *s )
+{
+    return __wine_dbgstr_an( s, -1 );
+}
+
+const char *wine_dbgstr_w( const WCHAR *s )
+{
+    return __wine_dbgstr_wn( s, -1 );
+}
+
+#endif /*__WINE__*/
diff --git a/lib/winedbgc/libmain.c b/lib/winedbgc/libmain.c
new file mode 100644 (file)
index 0000000..f9fd854
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Win32 winedbgc functions
+ *
+ *
+ * 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
+ */
+
+#include <windows.h>
+//#include <ntddk.h>
+//#include <wine/debugtools.h>
+//#include <stdlib.h>
+//#include <stdio.h>
+//#include <stdarg.h>
+//#include <string.h>
+//#include <ctype.h>
+/*
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "winbase.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+
+#include "proxywinedbgc.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winedbgc);
+ */
+
+/***********************************************************************
+ * DllMain [Internal] Initializes the internal 'winedbgc32.DLL'.
+ *
+ * PARAMS
+ *     hinstDLL    [I] handle to the DLL's instance
+ *     fdwReason   [I]
+ *     lpvReserved [I] reserved, must be NULL
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
+ */
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+//    TRACE("Initializing or Finalizing winedbgc: %p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
+    if (fdwReason == DLL_PROCESS_ATTACH)
+    {
+//       TRACE("Loading winedbgc...\n");
+/*
+#ifndef __REACTOS__
+       if (winedbgc_LoadDriverManager())
+          winedbgc_LoadDMFunctions();
+#endif
+ */
+    }
+    else if (fdwReason == DLL_PROCESS_DETACH)
+    {
+//      TRACE("Unloading winedbgc...\n");
+/*
+#ifndef __REACTOS__
+      if (gProxyHandle.bFunctionReady)
+      {
+         int i;
+         for ( i = 0; i < NUM_SQLFUNC; i ++ )
+         {
+            gProxyHandle.functions[i].func = SQLDummyFunc;
+         }
+      }
+      if (gProxyHandle.dmHandle)
+      {
+         wine_dlclose(gProxyHandle.dmHandle,NULL,0);
+         gProxyHandle.dmHandle = NULL;
+      }
+#endif
+ */
+    }
+    return TRUE;
+}
+
+
+/* EOF */
diff --git a/lib/winedbgc/porting.c b/lib/winedbgc/porting.c
new file mode 100644 (file)
index 0000000..18b84f6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Porting wine comtrl32 to ReactOS comctrl32 support functions
+ *
+ * Copyright 2002 Robert Dickenson
+ *
+ * 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
+ */
+
+#include <windows.h>
+#include "porting.h"
+
+
+static int interlocked_mutex;
+void _lwp_mutex_lock(int* interlocked_mutex) {}
+void _lwp_mutex_unlock(int* interlocked_mutex) {}
+
+long interlocked_xchg_add( long *dest, long incr )
+{
+    long retv;
+    _lwp_mutex_lock( &interlocked_mutex );
+    retv = *dest;
+    *dest += incr;
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return retv;
+}
+
diff --git a/lib/winedbgc/porting.h b/lib/winedbgc/porting.h
new file mode 100644 (file)
index 0000000..bc03379
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Porting from wine to ReactOS definitions
+ *
+ * Copyright 2002 Robert Dickenson
+ *
+ * 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
+ */
+
+#ifndef __PORTING_WINE2ROS_H
+#define __PORTING_WINE2ROS_H
+
+
+#ifndef __GNUC__
+#define inline _inline
+#endif
+
+long interlocked_xchg_add(long *dest, long incr);
+
+#define strlenW wcslen
+
+#define strstrW wcsstr
+#define strtolW wcstol
+#define strncasecmp strncmp
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+
+
+#endif  /* __PORTING_WINE2ROS_H */
diff --git a/lib/winedbgc/winedbgc.c b/lib/winedbgc/winedbgc.c
new file mode 100644 (file)
index 0000000..f382f3d
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Debugging channels functions for WINE
+ */
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "porting.h"
+
+//#include <ntddk.h>
+#include <wine/debugtools.h>
+
+//DECLARE_DEBUG_CHANNEL(tid);
+DECLARE_DEBUG_CHANNEL(winedbgc);
+
+
+/* ---------------------------------------------------------------------- */
+
+struct debug_info
+{
+    char *str_pos;       /* current position in strings buffer */
+    char *out_pos;       /* current position in output buffer */
+    char  strings[1024]; /* buffer for temporary strings */
+    char  output[1024];  /* current output line */
+};
+
+static struct debug_info tmp;
+
+/* get the debug info pointer for the current thread */
+static inline struct debug_info *get_info(void)
+{
+    struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
+    if (!info)
+    {
+        if (!tmp.str_pos)
+        {
+            tmp.str_pos = tmp.strings;
+            tmp.out_pos = tmp.output;
+        }
+        if (!RtlGetProcessHeap()) return &tmp;
+        /* setup the temp structure in case HeapAlloc wants to print something */
+        NtCurrentTeb()->WineDebugInfo = &tmp;
+        info = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*info) );
+        info->str_pos = info->strings;
+        info->out_pos = info->output;
+        NtCurrentTeb()->WineDebugInfo = info;
+    }
+    return info;
+}
+
+/* allocate some tmp space for a string */
+static void *gimme1(int n)
+{
+    struct debug_info *info = get_info();
+    char *res = info->str_pos;
+
+    if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
+    info->str_pos = res + n;
+    return res;
+}
+
+/* release extra space that we requested in gimme1() */
+static inline void release( void *ptr )
+{
+    struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
+    info->str_pos = ptr;
+}
+
+/***********************************************************************
+ *             wine_dbgstr_an (NTDLL.@)
+ */
+const char *wine_dbgstr_an( const char *src, int n )
+{
+    char *dst, *res;
+
+    if (!((WORD)(DWORD)(src) >> 16))
+    {
+        if (!src) return "(null)";
+        res = gimme1(6);
+        sprintf(res, "#%04x", (WORD)(DWORD)(src) );
+        return res;
+    }
+    if (n < 0) n = 0;
+    else if (n > 200) n = 200;
+    dst = res = gimme1 (n * 4 + 6);
+    *dst++ = '"';
+    while (n-- > 0 && *src)
+    {
+        unsigned char c = *src++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"': *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                *dst++ = '0' + ((c >> 6) & 7);
+                *dst++ = '0' + ((c >> 3) & 7);
+                *dst++ = '0' + ((c >> 0) & 7);
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*src)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = '\0';
+    release( dst );
+    return res;
+}
+
+/***********************************************************************
+ *             wine_dbgstr_wn (NTDLL.@)
+ */
+const char *wine_dbgstr_wn( const WCHAR *src, int n )
+{
+    char *dst, *res;
+
+    if (!((WORD)(DWORD)(src) >> 16))
+    {
+        if (!src) return "(null)";
+        res = gimme1(6);
+        sprintf(res, "#%04x", (WORD)(DWORD)(src) );
+        return res;
+    }
+    if (n < 0) n = 0;
+    else if (n > 200) n = 200;
+    dst = res = gimme1 (n * 5 + 7);
+    *dst++ = 'L';
+    *dst++ = '"';
+    while (n-- > 0 && *src)
+    {
+        WCHAR c = *src++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"': *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                sprintf(dst,"%04x",c);
+                dst+=4;
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*src)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = '\0';
+    release( dst );
+    return res;
+}
+
+/***********************************************************************
+ *             wine_dbgstr_guid (NTDLL.@)
+ */
+const char *wine_dbgstr_guid( const GUID *id )
+{
+    char *str;
+
+    if (!id) return "(null)";
+    if (!((WORD)(DWORD)(id) >> 16))
+    {
+        str = gimme1(12);
+        sprintf( str, "<guid-0x%04x>", (WORD)(DWORD)(id) );
+    }
+    else
+    {
+        str = gimme1(40);
+        sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+                 id->Data1, id->Data2, id->Data3,
+                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+    }
+    return str;
+}
+
+/***********************************************************************
+ *             wine_dbg_vprintf (NTDLL.@)
+ */
+int wine_dbg_vprintf( const char *format, va_list args )
+{
+    struct debug_info *info = get_info();
+    char *p;
+
+    int ret = _vsnprintf( info->out_pos, sizeof(info->output) - (info->out_pos - info->output),
+                         format, args );
+
+    p = strrchr( info->out_pos, '\n' );
+    if (!p) info->out_pos += ret;
+    else
+    {
+        char *pos = info->output;
+       char saved_ch;
+        p++;
+       saved_ch = *p;
+       *p = 0;
+        DbgPrint(pos);
+       *p = saved_ch;
+        /* move beginning of next line to start of buffer */
+        while ((*pos = *p++)) pos++;
+        info->out_pos = pos;
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *             wine_dbg_printf (NTDLL.@)
+ */
+int wine_dbg_printf(const char *format, ...)
+{
+    int ret;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = wine_dbg_vprintf( format, valist );
+    va_end(valist);
+    return ret;
+}
+
+/***********************************************************************
+ *             wine_dbg_log (NTDLL.@)
+ */
+int wine_dbg_log(enum __DEBUG_CLASS cls, const char *channel,
+                 const char *function, const char *format, ... )
+{
+    static const char *classes[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
+    va_list valist;
+    int ret = 0;
+
+    va_start(valist, format);
+    if (TRACE_ON(winedbgc))
+        ret = wine_dbg_printf( "%08lx:", NtCurrentTeb()->Cid.UniqueThread);
+    if (cls < __DBCL_COUNT)
+        ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, function );
+    if (format)
+        ret += wine_dbg_vprintf( format, valist );
+    va_end(valist);
+    return ret;
+}
diff --git a/lib/winedbgc/winedbgc.def b/lib/winedbgc/winedbgc.def
new file mode 100644 (file)
index 0000000..4b86134
--- /dev/null
@@ -0,0 +1,37 @@
+; $Id$
+;
+; ReactOS Operating System
+;
+LIBRARY winedbgc.dll
+
+EXPORTS
+
+wine_dbg_log
+wine_dbg_printf
+wine_dbgstr_an
+wine_dbgstr_guid
+wine_dbgstr_wn
+__wine_dbg_register
+__wine_dbg_unregister
+__wine_dbg_vlog DATA 
+__wine_dbg_vprintf DATA 
+__wine_dbgstr_an DATA 
+__wine_dbgstr_guid DATA 
+__wine_dbgstr_wn DATA 
+
+
+;
+;wine_dbg_log @1 
+;__wine_dbg_register @2 
+;__wine_dbg_unregister @3 
+;__wine_dbg_vlog @4 DATA 
+;__wine_dbg_vprintf @5 DATA 
+;__wine_dbgstr_an @6 DATA 
+;__wine_dbgstr_guid @7 DATA 
+;__wine_dbgstr_wn @8 DATA 
+;
+;wine_dbg_printf @34 
+;wine_dbgstr_an @36 
+;wine_dbgstr_guid @37 
+;wine_dbgstr_wn @39 
+;
\ No newline at end of file
diff --git a/lib/winedbgc/winedbgc.dll.dbg.c b/lib/winedbgc/winedbgc.dll.dbg.c
new file mode 100644 (file)
index 0000000..8273668
--- /dev/null
@@ -0,0 +1,42 @@
+/* File generated automatically; do not edit! */
+/* This file can be copied, modified and distributed without restriction. */
+
+char __wine_dbch_winedbgc[] = "\003winedbgc";
+
+static char * const debug_channels[4] =
+{
+    __wine_dbch_winedbgc
+};
+
+static void *debug_registration;
+
+#ifdef __GNUC__
+static void __wine_dbg_winedbgc32_init(void) __attribute__((constructor));
+static void __wine_dbg_winedbgc32_fini(void) __attribute__((destructor));
+#else
+static void __asm__dummy_dll_init(void) {
+asm("\t.section\t\".init\" ,\"ax\"\n"
+    "\tcall ___wine_dbg_winedbgc32_init\n"
+    "\t.section\t\".fini\" ,\"ax\"\n"
+    "\tcall ___wine_dbg_winedbgc32_fini\n"
+    "\t.section\t\".text\"\n");
+}
+#endif /* defined(__GNUC__) */
+
+#ifdef __GNUC__
+static
+#endif
+void __wine_dbg_winedbgc32_init(void)
+{
+//    extern void *__wine_dbg_register( char * const *, int );
+//    debug_registration = __wine_dbg_register( debug_channels, 4 );
+}
+
+#ifdef __GNUC__
+static
+#endif
+void __wine_dbg_winedbgc32_fini(void)
+{
+//    extern void __wine_dbg_unregister( void* );
+//    __wine_dbg_unregister( debug_registration );
+}
diff --git a/lib/winedbgc/winedbgc.edf b/lib/winedbgc/winedbgc.edf
new file mode 100644 (file)
index 0000000..7f5eddb
--- /dev/null
@@ -0,0 +1,81 @@
+; $Id$
+;
+; ReactOS Operating System
+;
+LIBRARY winedbgc.dll
+
+EXPORTS
+
+wine_dbg_log
+wine_dbg_printf
+wine_dbgstr_an
+wine_dbgstr_guid
+wine_dbgstr_wn
+__wine_dbg_register
+__wine_dbg_unregister
+__wine_dbg_vlog DATA 
+__wine_dbg_vprintf DATA 
+__wine_dbgstr_an DATA 
+__wine_dbgstr_guid DATA 
+__wine_dbgstr_wn DATA 
+
+
+
+;wine_dbgstr_an
+;wine_dbgstr_wn
+;wine_dbgstr_guid
+;wine_dbg_vprintf
+;wine_dbg_printf
+;wine_dbg_log
+
+;  wine_dbg_log @1 
+;  __wine_dbg_register @2 
+;  __wine_dbg_unregister @3 
+;  __wine_dbg_vlog @4 DATA 
+;  __wine_dbg_vprintf @5 DATA 
+;  __wine_dbgstr_an @6 DATA 
+;  __wine_dbgstr_guid @7 DATA 
+;  __wine_dbgstr_wn @8 DATA 
+;__wine_dll_register @9 
+;__wine_main_argc @10 DATA 
+;__wine_main_argv @11 DATA 
+;__wine_main_wargv @12 DATA 
+
+
+;interlocked_cmpxchg @20 
+;interlocked_cmpxchg_ptr @21 
+;interlocked_xchg @22 
+;interlocked_xchg_add @23 
+;interlocked_xchg_ptr @24 
+;wine_anon_mmap @30 
+;wine_dbg_add_option @31 
+;wine_dbg_parse_options @33 
+;  wine_dbg_printf @34 
+;wine_dbgstr_a @35 
+;  wine_dbgstr_an @36 
+;  wine_dbgstr_guid @37 
+;wine_dbgstr_w @38 
+;  wine_dbgstr_wn @39 
+;wine_dlclose @40 
+;wine_dll_load @41 
+;wine_dll_load_main_exe @42 
+;wine_dll_set_callback @43 
+;wine_dll_unload @44 
+;wine_dlopen @45 
+;wine_dlsym @46 
+;wine_errno_location @47 DATA 
+;wine_get_config_dir @48 
+;wine_get_cs @49 
+;wine_get_ds @50 
+;wine_get_es @51 
+;wine_get_fs @52 
+;wine_get_gs @53 
+;wine_get_server_dir @54 
+;wine_get_ss @55 
+;wine_h_errno_location @56 DATA 
+;wine_ldt_copy @57 DATA 
+;wine_ldt_get_entry @58 
+;wine_ldt_set_entry @59 
+;wine_rewrite_s4tos2 @60 
+;wine_set_fs @61 
+;wine_set_gs @62 
diff --git a/lib/winedbgc/winedbgc.rc b/lib/winedbgc/winedbgc.rc
new file mode 100644 (file)
index 0000000..061cc81
--- /dev/null
@@ -0,0 +1,38 @@
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+       FILEVERSION     RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+       PRODUCTVERSION  RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD      
+       FILEFLAGSMASK   0x3fL
+#ifdef _DEBUG
+       FILEFLAGS       0x1L
+#else
+       FILEFLAGS       0x0L
+#endif
+       FILEOS          0x40004L
+       FILETYPE        0x2L
+       FILESUBTYPE     0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName",       RES_STR_COMPANY_NAME
+            VALUE "FileDescription",   "WINE debug channels for ReactOS\0"
+            VALUE "FileVersion",       RES_STR_FILE_VERSION
+            VALUE "InternalName",      "winedbgc\0"
+            VALUE "LegalCopyright",    RES_STR_LEGAL_COPYRIGHT
+            VALUE "OriginalFilename",  "winedbgc.dll\0"
+            VALUE "ProductName",       RES_STR_PRODUCT_NAME
+            VALUE "ProductVersion",    RES_STR_PRODUCT_VERSION
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
diff --git a/lib/winmm/misc/.cvsignore b/lib/winmm/misc/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/lib/ws2_32/misc/.cvsignore b/lib/ws2_32/misc/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
diff --git a/loaders/dos/.cvsignore b/loaders/dos/.cvsignore
new file mode 100644 (file)
index 0000000..ed6fe06
--- /dev/null
@@ -0,0 +1 @@
+*.com
diff --git a/ntoskrnl/dbg/profile.c b/ntoskrnl/dbg/profile.c
new file mode 100755 (executable)
index 0000000..89b3c0c
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 1998-2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ *
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/dbg/profile.c
+ * PURPOSE:         Kernel profiling
+ * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *                  Created 12/01/2003
+ */
+
+/* INCLUDES *****************************************************************/
+
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
+#include <internal/ldr.h>
+#include "kdb.h"
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+#define PROFILE_SESSION_LENGTH 30 /* Session length in seconds */
+
+typedef struct _PROFILE_DATABASE_ENTRY
+{
+  ULONG_PTR Address;
+} PROFILE_DATABASE_ENTRY, *PPROFILE_DATABASE_ENTRY;
+
+#define PDE_BLOCK_ENTRIES ((PAGE_SIZE - (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(PROFILE_DATABASE_ENTRY))
+
+typedef struct _PROFILE_DATABASE_BLOCK
+{
+   LIST_ENTRY ListEntry;
+   ULONG UsedEntries;
+   PROFILE_DATABASE_ENTRY Entries[PDE_BLOCK_ENTRIES];
+} PROFILE_DATABASE_BLOCK, *PPROFILE_DATABASE_BLOCK;
+
+typedef struct _PROFILE_DATABASE
+{
+  LIST_ENTRY ListHead;
+} PROFILE_DATABASE, *PPROFILE_DATABASE;
+
+typedef struct _SAMPLE_GROUP_INFO
+{
+  ULONG_PTR Address;
+  ULONG Count;
+  CHAR Description[128];
+  LIST_ENTRY ListEntry;
+} SAMPLE_GROUP_INFO, *PSAMPLE_GROUP_INFO;
+
+static volatile BOOLEAN KdbProfilingInitialized = FALSE;
+static volatile BOOLEAN KdbProfilingEnabled = FALSE;
+static volatile BOOLEAN KdbProfilingSuspended = FALSE;
+static PPROFILE_DATABASE KdbProfileDatabase = NULL;
+static KDPC KdbProfilerCollectorDpc;
+static HANDLE KdbProfilerThreadHandle;
+static CLIENT_ID KdbProfilerThreadCid;
+static HANDLE KdbProfilerLogFile;
+static KTIMER KdbProfilerTimer;
+static KMUTEX KdbProfilerLock;
+static BOOLEAN KdbEnableProfiler = FALSE;
+
+VOID
+KdbDeleteProfileDatabase(PPROFILE_DATABASE ProfileDatabase)
+{
+  PLIST_ENTRY current = NULL;
+
+  current = RemoveHeadList(&ProfileDatabase->ListHead);
+  while (current != &ProfileDatabase->ListHead)
+    {
+      PPROFILE_DATABASE_BLOCK block = CONTAINING_RECORD(
+               current, PROFILE_DATABASE_BLOCK, ListEntry);
+         ExFreePool(block);
+         current = RemoveHeadList(&ProfileDatabase->ListHead);
+    }
+}
+
+VOID
+KdbAddEntryToProfileDatabase(PPROFILE_DATABASE ProfileDatabase, ULONG_PTR Address)
+{
+  PPROFILE_DATABASE_BLOCK block;
+
+  if (IsListEmpty(&ProfileDatabase->ListHead))
+    {
+      block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK));
+      assert(block);
+      block->UsedEntries = 0;
+      InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry);
+      block->Entries[block->UsedEntries++].Address = Address;
+      return;
+    }
+
+  block = CONTAINING_RECORD(ProfileDatabase->ListHead.Blink, PROFILE_DATABASE_BLOCK, ListEntry);
+  if (block->UsedEntries >= PDE_BLOCK_ENTRIES)
+    {
+      block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK));
+      assert(block);
+      block->UsedEntries = 0;
+      InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry);
+    }
+  block->Entries[block->UsedEntries++].Address = Address;
+}
+
+VOID
+KdbInitProfiling()
+{
+  KdbEnableProfiler = TRUE;
+}
+
+VOID
+KdbInitProfiling2()
+{
+  if (KdbEnableProfiler)
+    {
+      KdbEnableProfiling();
+      KdbProfilingInitialized = TRUE;
+    }
+}
+
+VOID
+KdbSuspendProfiling()
+{
+  KdbProfilingSuspended = TRUE;
+}
+
+VOID
+KdbResumeProfiling()
+{
+  KdbProfilingSuspended = FALSE;
+}
+
+BOOLEAN
+KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer)
+{
+   PLIST_ENTRY current_entry;
+   MODULE_TEXT_SECTION* current;
+   extern LIST_ENTRY ModuleTextListHead;
+   ULONG_PTR RelativeAddress;
+   NTSTATUS Status;
+   ULONG LineNumber;
+   CHAR FileName[256];
+   CHAR FunctionName[256];
+
+   current_entry = ModuleTextListHead.Flink;
+   
+   while (current_entry != &ModuleTextListHead &&
+         current_entry != NULL)
+     {
+       current = 
+         CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+
+       if (address >= (PVOID)current->Base &&
+           address < (PVOID)(current->Base + current->Length))
+         {
+            RelativeAddress = (ULONG_PTR) address - current->Base;
+            Status = LdrGetAddressInformation(&current->SymbolInfo,
+              RelativeAddress,
+              &LineNumber,
+              FileName,
+              FunctionName);
+            if (NT_SUCCESS(Status))
+              {
+                sprintf(NameBuffer, "%s (%s)", FileName, FunctionName);
+                return(TRUE);
+              }
+            return(TRUE);
+         }
+       current_entry = current_entry->Flink;
+     }
+   return(FALSE);
+}
+
+PLIST_ENTRY
+KdbProfilerLargestSampleGroup(PLIST_ENTRY SamplesListHead)
+{
+  PLIST_ENTRY current;
+  PLIST_ENTRY largest;
+  ULONG count;
+
+  count = 0;
+  largest = SamplesListHead->Flink;
+  current = SamplesListHead->Flink;
+  while (current != SamplesListHead)
+    {
+      PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD(
+               current, SAMPLE_GROUP_INFO, ListEntry);
+
+      if (sgi->Count > count)
+        {
+          largest = current;
+          count = sgi->Count;
+        }
+
+         current = current->Flink;
+    }
+  if (count == 0)
+    {
+      return NULL;
+    }
+  return largest;
+}
+
+VOID
+KdbProfilerWriteString(PCH String)
+{
+  IO_STATUS_BLOCK Iosb;
+  NTSTATUS Status;
+  ULONG Length;
+
+  Length = strlen(String);
+  Status = NtWriteFile(KdbProfilerLogFile,
+    NULL,
+    NULL,
+    NULL,
+    &Iosb,
+    String,
+    Length,
+    NULL,
+    NULL);
+
+ if (!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtWriteFile() failed with status 0x%.08x\n", Status);
+   }
+}
+
+NTSTATUS
+KdbProfilerWriteSampleGroups(PLIST_ENTRY SamplesListHead)
+{
+  CHAR Buffer[256];
+  PLIST_ENTRY current = NULL;
+  PLIST_ENTRY Largest;
+
+  KdbProfilerWriteString("\r\n\r\n");
+  KdbProfilerWriteString("Count     Symbol\n");
+  KdbProfilerWriteString("--------------------------------------------------\r\n");
+
+  current = SamplesListHead->Flink;
+  while (current != SamplesListHead)
+    {
+      Largest = KdbProfilerLargestSampleGroup(SamplesListHead);
+      if (Largest != NULL)
+        {
+          PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD(
+                   Largest, SAMPLE_GROUP_INFO, ListEntry);
+
+                 //DbgPrint("%.08d  %s\n", sgi->Count, sgi->Description);
+
+                 sprintf(Buffer, "%.08d  %s\r\n", sgi->Count, sgi->Description);
+          KdbProfilerWriteString(Buffer);
+
+          RemoveEntryList(Largest);
+          ExFreePool(sgi);
+        }
+      else
+        {
+          break;
+        }
+
+         current = SamplesListHead->Flink;
+    }
+
+  return STATUS_SUCCESS;
+}
+
+LONG STDCALL
+KdbProfilerKeyCompare(IN PVOID  Key1,
+  IN PVOID  Key2)
+{
+  int value = strcmp(Key1, Key2);
+
+  if (value == 0)
+    return 0;
+
+  return (value < 0) ? -1 : 1;
+}
+
+
+NTSTATUS
+KdbProfilerAnalyzeSamples()
+{
+  CHAR NameBuffer[512];
+  ULONG KeyLength;
+  PLIST_ENTRY current = NULL;
+  HASH_TABLE Hashtable;
+  LIST_ENTRY SamplesListHead;
+  ULONG Index;
+  ULONG_PTR Address;
+
+  if (!ExInitializeHashTable(&Hashtable, 17, KdbProfilerKeyCompare, TRUE))
+    {
+      DPRINT1("ExInitializeHashTable() failed.");
+      KeBugCheck(0);
+    }
+
+  InitializeListHead(&SamplesListHead);
+
+  current = RemoveHeadList(&KdbProfileDatabase->ListHead);
+  while (current != &KdbProfileDatabase->ListHead)
+    {
+      PPROFILE_DATABASE_BLOCK block;
+
+      block = CONTAINING_RECORD(current, PROFILE_DATABASE_BLOCK, ListEntry);
+
+      for (Index = 0; Index < block->UsedEntries; Index++)
+        {
+          PSAMPLE_GROUP_INFO sgi;
+          Address = block->Entries[Index].Address;
+             if (KdbProfilerGetSymbolInfo((PVOID) Address, (PCH) &NameBuffer))
+               {
+               }
+             else
+                   {
+                 sprintf(NameBuffer, "(0x%.08x)", (ULONG) Address);
+                   }
+
+             KeyLength = strlen(NameBuffer);
+             if (!ExSearchHashTable(&Hashtable, (PVOID) NameBuffer, KeyLength, (PVOID *) &sgi))
+               {
+                 sgi = ExAllocatePool(NonPagedPool, sizeof(SAMPLE_GROUP_INFO));
+                 assert(sgi);
+              sgi->Address = Address;
+                 sgi->Count = 1;
+                 strcpy(sgi->Description, NameBuffer);
+                 InsertTailList(&SamplesListHead, &sgi->ListEntry);
+                 ExInsertHashTable(&Hashtable, sgi->Description, KeyLength, (PVOID) sgi);
+               }
+             else
+               {
+                 sgi->Count++;
+               }
+        }
+
+      ExFreePool(block);
+
+      current = RemoveHeadList(&KdbProfileDatabase->ListHead);
+    }
+
+  KdbProfilerWriteSampleGroups(&SamplesListHead);
+
+  ExDeleteHashTable(&Hashtable);
+
+  KdbDeleteProfileDatabase(KdbProfileDatabase);
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS STDCALL
+KdbProfilerThreadMain(PVOID Context)
+{
+  for (;;)
+    {
+      KeWaitForSingleObject(&KdbProfilerTimer, Executive, KernelMode, TRUE, NULL);
+
+      KeWaitForSingleObject(&KdbProfilerLock, Executive, KernelMode, FALSE, NULL);
+
+         KdbSuspendProfiling();
+
+      KdbProfilerAnalyzeSamples();
+
+         KdbResumeProfiling();
+
+         KeReleaseMutex(&KdbProfilerLock, FALSE);
+       }
+}
+
+VOID
+KdbDisableProfiling()
+{
+  if (KdbProfilingEnabled == TRUE)
+    {
+      /* FIXME: Implement */
+#if 0
+      KdbProfilingEnabled = FALSE;
+      /* Stop timer */
+      /* Close file */
+      if (KdbProfileDatabase != NULL)
+        {
+          KdbDeleteProfileDatabase(KdbProfileDatabase);
+          ExFreePool(KdbProfileDatabase);
+          KdbProfileDatabase = NULL;
+        }
+#endif
+    }
+}
+
+/*
+ * SystemArgument1 = EIP
+ */
+static VOID STDCALL
+KdbProfilerCollectorDpcRoutine(PKDPC Dpc, PVOID DeferredContext,
+  PVOID SystemArgument1, PVOID SystemArgument2)
+{
+  ULONG_PTR address = (ULONG_PTR) SystemArgument1;
+
+  KdbAddEntryToProfileDatabase(KdbProfileDatabase, address);
+}
+
+VOID
+KdbEnableProfiling()
+{
+  if (KdbProfilingEnabled == FALSE)
+    {
+         NTSTATUS Status;
+         OBJECT_ATTRIBUTES ObjectAttributes;
+         UNICODE_STRING FileName;
+         IO_STATUS_BLOCK Iosb;
+      LARGE_INTEGER DueTime;
+
+         RtlInitUnicodeString(&FileName, L"\\SystemRoot\\profiler.log");
+         InitializeObjectAttributes(&ObjectAttributes,
+               &FileName,
+               0,
+               NULL,
+               NULL);
+       
+         Status = NtCreateFile(&KdbProfilerLogFile,
+               FILE_ALL_ACCESS,
+               &ObjectAttributes,
+               &Iosb,
+               NULL,
+               FILE_ATTRIBUTE_NORMAL,
+               0,
+               FILE_SUPERSEDE,
+               FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
+               NULL,
+               0);
+         if (!NT_SUCCESS(Status))
+           {
+             DPRINT1("Failed to create profiler log file\n");
+             return;
+           }
+
+         Status = PsCreateSystemThread(&KdbProfilerThreadHandle,
+               THREAD_ALL_ACCESS,
+               NULL,
+               NULL,
+               &KdbProfilerThreadCid,
+               KdbProfilerThreadMain,
+               NULL);
+         if (!NT_SUCCESS(Status))
+           {
+             DPRINT1("Failed to create profiler thread\n");
+             return;
+           }
+
+      KeInitializeMutex(&KdbProfilerLock, 0);
+
+      KdbProfileDatabase = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE));
+      assert(KdbProfileDatabase);
+      InitializeListHead(&KdbProfileDatabase->ListHead);
+      KeInitializeDpc(&KdbProfilerCollectorDpc, KdbProfilerCollectorDpcRoutine, NULL);
+
+         /* Initialize our periodic timer and its associated DPC object. When the timer
+            expires, the KdbProfilerSessionEndDpc deferred procedure call (DPC) is queued */
+         KeInitializeTimerEx(&KdbProfilerTimer, SynchronizationTimer);
+
+         /* Start the periodic timer with an initial and periodic
+            relative expiration time of PROFILE_SESSION_LENGTH seconds */
+         DueTime.QuadPart = -(LONGLONG) PROFILE_SESSION_LENGTH * 1000 * 10000;
+         KeSetTimerEx(&KdbProfilerTimer, DueTime, PROFILE_SESSION_LENGTH * 1000, NULL);
+
+      KdbProfilingEnabled = TRUE;
+    }
+}
+
+VOID
+KdbProfileInterrupt(ULONG_PTR Address)
+{
+  assert(KeGetCurrentIrql() == PROFILE_LEVEL);
+
+  if (KdbProfilingInitialized != TRUE)
+    {
+      return;
+    }
+
+  if ((KdbProfilingEnabled) && (!KdbProfilingSuspended))
+    {
+      (BOOLEAN) KeInsertQueueDpc(&KdbProfilerCollectorDpc, (PVOID) Address, NULL);
+    }
+}
diff --git a/ntoskrnl/rtl/math.c b/ntoskrnl/rtl/math.c
new file mode 100644 (file)
index 0000000..b9deb34
--- /dev/null
@@ -0,0 +1,332 @@
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            kernel/rtl/math.c
+ * PURPOSE:         
+ * UPDATE HISTORY:
+ *                  Created 20/12/2002
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+
+/* FUNCTIONS *****************************************************************/
+
+LARGE_INTEGER
+STDCALL
+_alldiv(ULONG  UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allmul(ULONG  UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allrem(ULONG  UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allshl(ULONG  UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allshr(ULONG  UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aulldiv(ULONG UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aullrem(ULONG UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aullshr(ULONG UnsignedInteger)
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = 0;
+       return RC;
+}
+
+
+/*
+LARGE_INTEGER
+STDCALL
+RtlConvertLongToLargeInteger (
+       LONG    SignedInteger
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = SignedInteger;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlConvertUlongToLargeInteger (
+       ULONG   UnsignedInteger
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = UnsignedInteger;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedIntegerMultiply (
+       LONG    Multiplicand,
+       LONG    Multiplier
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
+
+       return RC;
+}
+
+ULONG
+STDCALL
+RtlEnlargedUnsignedDivide (
+       ULARGE_INTEGER  Dividend,
+       ULONG           Divisor,
+       PULONG          Remainder
+       )
+{
+       if (Remainder)
+               *Remainder = Dividend.QuadPart % Divisor;
+
+       return (ULONG)(Dividend.QuadPart / Divisor);
+}
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedUnsignedMultiply (
+       ULONG   Multiplicand,
+       ULONG   Multiplier
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedIntegerMultiply (
+       LARGE_INTEGER   Multiplicand,
+       LONG            Multiplier
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = Multiplicand.QuadPart * Multiplier;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedLargeIntegerDivide (
+       LARGE_INTEGER   Dividend,
+       ULONG           Divisor,
+       PULONG          Remainder
+       )
+{
+       LARGE_INTEGER RC;
+
+       if (Remainder)
+               *Remainder = Dividend.QuadPart % Divisor;
+
+       RC.QuadPart = Dividend.QuadPart / Divisor;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedMagicDivide (LARGE_INTEGER  Dividend,
+                       LARGE_INTEGER   MagicDivisor,
+                       CCHAR           ShiftCount)
+{
+  LARGE_INTEGER Result;
+
+  Result.QuadPart = (Dividend.QuadPart * MagicDivisor.QuadPart) >> ShiftCount;
+  return(Result);
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerAdd (
+       LARGE_INTEGER   Addend1,
+       LARGE_INTEGER   Addend2
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerArithmeticShift (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR           ShiftCount
+       )
+{
+       LARGE_INTEGER RC;
+       CHAR Shift;
+
+       Shift = ShiftCount % 64;
+
+       if (Shift < 32)
+       {
+               RC.QuadPart = LargeInteger.QuadPart >> Shift;
+       }
+       else
+       {
+               // copy the sign bit
+               RC.u.HighPart |= (LargeInteger.u.HighPart & 0x80000000);
+               RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
+       }
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerDivide (
+       LARGE_INTEGER   Dividend,
+       LARGE_INTEGER   Divisor,
+       PLARGE_INTEGER  Remainder
+       )
+{
+       LARGE_INTEGER RC;
+
+       if (Remainder)
+               Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
+
+       RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerNegate (
+       LARGE_INTEGER   Subtrahend
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = - Subtrahend.QuadPart;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftLeft (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR           ShiftCount
+       )
+{
+       LARGE_INTEGER RC;
+       CHAR Shift;
+
+       Shift = ShiftCount % 64;
+       RC.QuadPart = LargeInteger.QuadPart << Shift;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftRight (
+       LARGE_INTEGER   LargeInteger,
+       CCHAR           ShiftCount
+       )
+{
+       LARGE_INTEGER RC;
+       CHAR Shift;
+
+       Shift = ShiftCount % 64;
+       RC.QuadPart = LargeInteger.QuadPart >> ShiftCount;
+
+       return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerSubtract (
+       LARGE_INTEGER   Minuend,
+       LARGE_INTEGER   Subtrahend
+       )
+{
+       LARGE_INTEGER RC;
+
+       RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
+
+       return RC;
+}
+ */
+/* EOF */
diff --git a/subsys/csrss/csrss.def b/subsys/csrss/csrss.def
new file mode 100644 (file)
index 0000000..292c1aa
--- /dev/null
@@ -0,0 +1,8 @@
+; $Id$
+;
+
+LIBRARY csrss.exe
+
+EXPORTS
+
+CsrServerInitialization
diff --git a/subsys/csrss/csrss.edf b/subsys/csrss/csrss.edf
new file mode 100644 (file)
index 0000000..ce21b2f
--- /dev/null
@@ -0,0 +1,9 @@
+; $Id$
+;
+;
+
+LIBRARY csrss.exe
+
+EXPORTS
+
+CsrServerInitialization=CsrServerInitialization@8
diff --git a/subsys/system/usetup/bootsup.c b/subsys/system/usetup/bootsup.c
new file mode 100644 (file)
index 0000000..77edba3
--- /dev/null
@@ -0,0 +1,1492 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/bootsup.c
+ * PURPOSE:         Bootloader support functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "inicache.h"
+#include "bootsup.h"
+
+
+#define SECTORSIZE 512
+
+/* FUNCTIONS ****************************************************************/
+
+
+static VOID
+CreateCommonFreeLoaderSections(PINICACHE IniCache)
+{
+  PINICACHESECTION IniSection;
+
+  /* Create "FREELOADER" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"FREELOADER");
+
+  /* DefaultOS=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"DefaultOS",
+                   L"ReactOS");
+
+#if 0
+  /* Timeout=10 */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"TimeOut",
+                   L"10");
+#endif
+
+  /* Create "Display" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"Display");
+
+  /* TitleText=ReactOS Boot Manager */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"TitleText",
+                   L"ReactOS Boot Manager");
+
+  /* StatusBarColor=Cyan */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"StatusBarColor",
+                   L"Cyan");
+
+  /* StatusBarTextColor=Black */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"StatusBarTextColor",
+                   L"Black");
+
+  /* BackdropTextColor=White */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BackdropTextColor",
+                   L"White");
+
+  /* BackdropColor=Blue */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BackdropColor",
+                   L"Blue");
+
+  /* BackdropFillStyle=Medium */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BackdropFillStyle",
+                   L"Medium");
+
+  /* TitleBoxTextColor=White */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"TitleBoxTextColor",
+                   L"White");
+
+  /* TitleBoxColor=Red */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"TitleBoxColor",
+                   L"Red");
+
+  /* MessageBoxTextColor=White */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"MessageBoxTextColor",
+                   L"White");
+
+  /* MessageBoxColor=Blue */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"MessageBoxColor",
+                   L"Blue");
+
+  /* MenuTextColor=White */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"MenuTextColor",
+                   L"White");
+
+  /* MenuColor=Blue */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"MenuColor",
+                   L"Blue");
+
+  /* TextColor=Yellow */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"TextColor",
+                   L"Yellow");
+
+  /* SelectedTextColor=Black */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SelectedTextColor",
+                   L"Black");
+
+  /* SelectedColor=Gray */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SelectedColor",
+                   L"Gray");
+}
+
+
+NTSTATUS
+CreateFreeLoaderIniForDos(PWCHAR IniPath,
+                         PWCHAR ArcPath)
+{
+  PINICACHE IniCache;
+  PINICACHESECTION IniSection;
+
+  IniCache = IniCacheCreate();
+
+  CreateCommonFreeLoaderSections(IniCache);
+
+  /* Create "Operating Systems" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"Operating Systems");
+
+  /* REACTOS=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"ReactOS",
+                   L"\"ReactOS\"");
+
+  /* ReactOS_Debug="ReactOS (Debug)" */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"ReactOS_Debug",
+                   L"\"ReactOS (Debug)\"");
+
+  /* DOS=Dos/Windows */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"DOS",
+                   L"\"DOS/Windows\"");
+
+  /* Create "ReactOS" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"ReactOS");
+
+  /* BootType=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"ReactOS");
+
+  /* SystemPath=<ArcPath> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SystemPath",
+                   ArcPath);
+
+  /* Create "ReactOS_Debug" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"ReactOS_Debug");
+
+  /* BootType=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"ReactOS");
+
+  /* SystemPath=<ArcPath> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SystemPath",
+                   ArcPath);
+
+  /* Options=/DEBUGPORT=SCREEN */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"Options",
+                   L"/DEBUGPORT=SCREEN");
+
+  /* Create "DOS" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"DOS");
+
+  /* BootType=BootSector */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"BootSector");
+
+  /* BootDrive=hd0 */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootDrive",
+                   L"hd0");
+
+  /* BootPartition=1 */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootPartition",
+                   L"1");
+
+  /* BootSector=BOOTSECT.DOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootSectorFile",
+                   L"BOOTSECT.DOS");
+
+  IniCacheSave(IniCache, IniPath);
+  IniCacheDestroy(IniCache);
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+CreateFreeLoaderIniForReactos(PWCHAR IniPath,
+                             PWCHAR ArcPath)
+{
+  PINICACHE IniCache;
+  PINICACHESECTION IniSection;
+
+  IniCache = IniCacheCreate();
+
+  CreateCommonFreeLoaderSections(IniCache);
+
+  /* Create "Operating Systems" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"Operating Systems");
+
+  /* ReactOS="ReactOS" */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"ReactOS",
+                   L"\"ReactOS\"");
+
+  /* ReactOS_Debug="ReactOS (Debug)" */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"ReactOS_Debug",
+                   L"\"ReactOS (Debug)\"");
+
+  /* Create "ReactOS" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"ReactOS");
+
+  /* BootType=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"ReactOS");
+
+  /* SystemPath=<ArcPath> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SystemPath",
+                   ArcPath);
+
+  /* Create "ReactOS_Debug" section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    L"ReactOS_Debug");
+
+  /* BootType=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"ReactOS");
+
+  /* SystemPath=<ArcPath> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SystemPath",
+                   ArcPath);
+
+  /* Options=/DEBUGPORT=SCREEN */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"Options",
+                   L"/DEBUGPORT=SCREEN");
+
+  /* Save the ini file */
+  IniCacheSave(IniCache, IniPath);
+  IniCacheDestroy(IniCache);
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+UpdateFreeLoaderIni(PWCHAR IniPath,
+                   PWCHAR ArcPath)
+{
+  UNICODE_STRING Name;
+  PINICACHE IniCache;
+  PINICACHESECTION IniSection;
+  WCHAR SectionName[80];
+  WCHAR OsName[80];
+  PWCHAR KeyData;
+  ULONG i;
+  NTSTATUS Status;
+
+  RtlInitUnicodeString(&Name,
+                      IniPath);
+
+  Status = IniCacheLoad(&IniCache,
+                       &Name,
+                       FALSE);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  /* Get "Operating Systems" section */
+  IniSection = IniCacheGetSection(IniCache,
+                                 L"Operating Systems");
+  if (IniSection == NULL)
+    return(STATUS_UNSUCCESSFUL);
+
+  /* Find an unused section name */
+  i = 1;
+  wcscpy(SectionName, L"ReactOS");
+  wcscpy(OsName, L"\"ReactOS\"");
+  while(TRUE)
+  {
+    Status = IniCacheGetKey(IniSection,
+                           SectionName,
+                           &KeyData);
+    if (!NT_SUCCESS(Status))
+      break;
+
+    swprintf(SectionName, L"ReactOS_%lu", i);
+    swprintf(OsName, L"\"ReactOS %lu\"", i);
+    i++;
+  }
+
+  /* <SectionName>=<OsName> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   SectionName,
+                   OsName);
+
+  /* Create <SectionName> section */
+  IniSection = IniCacheAppendSection(IniCache,
+                                    SectionName);
+
+  /* BootType=ReactOS */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"BootType",
+                   L"ReactOS");
+
+  /* SystemPath=<ArcPath> */
+  IniCacheInsertKey(IniSection,
+                   NULL,
+                   INSERT_LAST,
+                   L"SystemPath",
+                   ArcPath);
+
+  IniCacheSave(IniCache, IniPath);
+  IniCacheDestroy(IniCache);
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+SaveCurrentBootSector(PWSTR RootPath,
+                     PWSTR DstPath)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PUCHAR BootSector;
+
+  /* Allocate buffer for bootsector */
+  BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                      0,
+                                      SECTORSIZE);
+  if (BootSector == NULL)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  /* Read current boot sector into buffer */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, BootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     BootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, BootSector);
+    return(Status);
+  }
+
+  /* Write bootsector to DstPath */
+  RtlInitUnicodeString(&Name,
+                      DstPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandle,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_SUPERSEDE,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, BootSector);
+    return(Status);
+  }
+
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      BootSector,
+                      SECTORSIZE,
+                      NULL,
+                      NULL);
+  NtClose(FileHandle);
+
+  /* Free the new boot sector */
+  RtlFreeHeap(ProcessHeap, 0, BootSector);
+
+  return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToFile(PWSTR SrcPath,
+                          PWSTR DstPath,
+                          PWSTR RootPath)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PUCHAR OrigBootSector;
+  PUCHAR NewBootSector;
+
+  /* Allocate buffer for original bootsector */
+  OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                          0,
+                                          SECTORSIZE);
+  if (OrigBootSector == NULL)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  /* Read current boot sector into buffer */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     OrigBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+
+  /* Allocate buffer for new bootsector */
+  NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         SECTORSIZE);
+  if (NewBootSector == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(STATUS_INSUFFICIENT_RESOURCES);
+  }
+
+  /* Read new bootsector from SrcPath */
+  RtlInitUnicodeString(&Name,
+                      SrcPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     NewBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Adjust bootsector (copy a part of the FAT BPB) */
+  memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
+
+  /* Free the original boot sector */
+  RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+  /* Write new bootsector to DstPath */
+  RtlInitUnicodeString(&Name,
+                      DstPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandle,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_OVERWRITE_IF,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+#if 0
+  FilePosition.QuadPart = 0;
+#endif
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      NewBootSector,
+                      SECTORSIZE,
+                      NULL,
+                      NULL);
+  NtClose(FileHandle);
+
+  /* Free the new boot sector */
+  RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+  return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToFile(PWSTR SrcPath,
+                          PWSTR DstPath,
+                          PWSTR RootPath)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PUCHAR OrigBootSector;
+  PUCHAR NewBootSector;
+  LARGE_INTEGER FileOffset;
+
+  /* Allocate buffer for original bootsector */
+  OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                          0,
+                                          SECTORSIZE);
+  if (OrigBootSector == NULL)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  /* Read current boot sector into buffer */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     OrigBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+CHECKPOINT1;
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+  /* Allocate buffer for new bootsector (2 sectors) */
+  NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         2 * SECTORSIZE);
+  if (NewBootSector == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(STATUS_INSUFFICIENT_RESOURCES);
+  }
+
+  /* Read new bootsector from SrcPath */
+  RtlInitUnicodeString(&Name,
+                      SrcPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     NewBootSector,
+                     2 * SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Adjust bootsector (copy a part of the FAT32 BPB) */
+  memcpy((NewBootSector + 3),
+        (OrigBootSector + 3),
+        87); /* FAT32 BPB length */
+
+  /* Disable the backup boot sector */
+  NewBootSector[0x32] = 0xFF;
+  NewBootSector[0x33] = 0xFF;
+
+  /* Free the original boot sector */
+  RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+  /* Write the first sector of the new bootcode to DstPath */
+  RtlInitUnicodeString(&Name,
+                      DstPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandle,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_SUPERSEDE,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      NewBootSector,
+                      SECTORSIZE,
+                      NULL,
+                      NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Write the second sector of the new bootcode to boot disk sector 14 */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_WRITE_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      (NewBootSector + SECTORSIZE),
+                      SECTORSIZE,
+                      &FileOffset,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+  {
+  }
+  NtClose(FileHandle);
+
+  /* Free the new boot sector */
+  RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+  return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToDisk(PWSTR SrcPath,
+                          PWSTR RootPath)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PUCHAR OrigBootSector;
+  PUCHAR NewBootSector;
+
+  /* Allocate buffer for original bootsector */
+  OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                          0,
+                                          SECTORSIZE);
+  if (OrigBootSector == NULL)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  /* Read current boot sector into buffer */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     OrigBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+
+  /* Allocate buffer for new bootsector */
+  NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         SECTORSIZE);
+  if (NewBootSector == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(STATUS_INSUFFICIENT_RESOURCES);
+  }
+
+  /* Read new bootsector from SrcPath */
+  RtlInitUnicodeString(&Name,
+                      SrcPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     NewBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Adjust bootsector (copy a part of the FAT BPB) */
+  memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
+
+  /* Free the original boot sector */
+  RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+  /* Write new bootsector to RootPath */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandle,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_OVERWRITE_IF,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+#if 0
+  FilePosition.QuadPart = 0;
+#endif
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      NewBootSector,
+                      SECTORSIZE,
+                      NULL,
+                      NULL);
+  NtClose(FileHandle);
+
+  /* Free the new boot sector */
+  RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+  return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToDisk(PWSTR SrcPath,
+                          PWSTR RootPath)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PUCHAR OrigBootSector;
+  PUCHAR NewBootSector;
+  LARGE_INTEGER FileOffset;
+  USHORT BackupBootSector;
+
+  /* Allocate buffer for original bootsector */
+  OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                          0,
+                                          SECTORSIZE);
+  if (OrigBootSector == NULL)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  /* Read current boot sector into buffer */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     OrigBootSector,
+                     SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(Status);
+  }
+
+
+  /* Allocate buffer for new bootsector (2 sectors) */
+  NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         2 * SECTORSIZE);
+  if (NewBootSector == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    return(STATUS_INSUFFICIENT_RESOURCES);
+  }
+
+  /* Read new bootsector from SrcPath */
+  RtlInitUnicodeString(&Name,
+                      SrcPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     NewBootSector,
+                     2 * SECTORSIZE,
+                     NULL,
+                     NULL);
+  NtClose(FileHandle);
+  if (!NT_SUCCESS(Status))
+  {
+    RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Adjust bootsector (copy a part of the FAT32 BPB) */
+  memcpy((NewBootSector + 3),
+        (OrigBootSector + 3),
+        87); /* FAT32 BPB length */
+
+  /* Get the location of the backup boot sector */
+  BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x33];
+
+  /* Free the original boot sector */
+  RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+  /* Write the first sector of the new bootcode to DstPath */
+  RtlInitUnicodeString(&Name,
+                      RootPath);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Write sector 0 */
+  FileOffset.QuadPart = 0ULL;
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      NewBootSector,
+                      SECTORSIZE,
+                      &FileOffset,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+    NtClose(FileHandle);
+    RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+    return(Status);
+  }
+
+  /* Write backup boot sector */
+  if (BackupBootSector != 0xFFFF)
+  {
+    FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
+    Status = NtWriteFile(FileHandle,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &IoStatusBlock,
+                        NewBootSector,
+                        SECTORSIZE,
+                        &FileOffset,
+                        NULL);
+    if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+      NtClose(FileHandle);
+      RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+      return(Status);
+    }
+  }
+
+  /* Write sector 14 */
+  FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      (NewBootSector + SECTORSIZE),
+                      SECTORSIZE,
+                      &FileOffset,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+  }
+  NtClose(FileHandle);
+
+  /* Free the new boot sector */
+  RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+  return(Status);
+}
+
+
+static NTSTATUS
+UnprotectBootIni(PWSTR FileName,
+                PULONG Attributes)
+{
+  UNICODE_STRING Name;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  FILE_BASIC_INFORMATION FileInfo;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+
+  RtlInitUnicodeString(&Name,
+                      FileName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (Status == STATUS_NO_SUCH_FILE)
+  {
+    DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+    *Attributes = 0;
+    return(STATUS_SUCCESS);
+  }
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+    return(Status);
+  }
+
+  Status = NtQueryInformationFile(FileHandle,
+                                 &IoStatusBlock,
+                                 &FileInfo,
+                                 sizeof(FILE_BASIC_INFORMATION),
+                                 FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
+    NtClose(FileHandle);
+    return(Status);
+  }
+
+  *Attributes = FileInfo.FileAttributes;
+
+  /* Delete attributes SYSTEM, HIDDEN and READONLY */
+  FileInfo.FileAttributes = FileInfo.FileAttributes &
+    ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
+
+  Status = NtSetInformationFile(FileHandle,
+                               &IoStatusBlock,
+                               &FileInfo,
+                               sizeof(FILE_BASIC_INFORMATION),
+                               FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
+  }
+
+  NtClose(FileHandle);
+  return(Status);
+}
+
+
+static NTSTATUS
+ProtectBootIni(PWSTR FileName,
+              ULONG Attributes)
+{
+  UNICODE_STRING Name;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  FILE_BASIC_INFORMATION FileInfo;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+
+  RtlInitUnicodeString(&Name,
+                      FileName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+    return(Status);
+  }
+
+  Status = NtQueryInformationFile(FileHandle,
+                                 &IoStatusBlock,
+                                 &FileInfo,
+                                 sizeof(FILE_BASIC_INFORMATION),
+                                 FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
+    NtClose(FileHandle);
+    return(Status);
+  }
+
+  FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
+
+  Status = NtSetInformationFile(FileHandle,
+                               &IoStatusBlock,
+                               &FileInfo,
+                               sizeof(FILE_BASIC_INFORMATION),
+                               FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
+  }
+
+  NtClose(FileHandle);
+  return(Status);
+}
+
+
+NTSTATUS
+UpdateBootIni(PWSTR BootIniPath,
+             PWSTR EntryName,
+             PWSTR EntryValue)
+{
+  UNICODE_STRING Name;
+  PINICACHE Cache = NULL;
+  PINICACHESECTION Section = NULL;
+  NTSTATUS Status;
+  ULONG FileAttribute;
+
+  RtlInitUnicodeString(&Name,
+                      BootIniPath);
+
+  Status = IniCacheLoad(&Cache,
+                       &Name,
+                       FALSE);
+  if (!NT_SUCCESS(Status))
+  {
+CHECKPOINT1;
+    return(Status);
+  }
+
+  Section = IniCacheGetSection(Cache,
+                              L"operating systems");
+  if (Section == NULL)
+  {
+CHECKPOINT1;
+    IniCacheDestroy(Cache);
+    return(STATUS_UNSUCCESSFUL);
+  }
+
+  IniCacheInsertKey(Section,
+                   NULL,
+                   INSERT_LAST,
+                   EntryName,
+                   EntryValue);
+
+  Status = UnprotectBootIni(BootIniPath,
+                           &FileAttribute);
+  if (!NT_SUCCESS(Status))
+  {
+CHECKPOINT1;
+    IniCacheDestroy(Cache);
+    return(Status);
+  }
+
+  Status = IniCacheSave(Cache,
+                       BootIniPath);
+  if (!NT_SUCCESS(Status))
+  {
+CHECKPOINT1;
+    IniCacheDestroy(Cache);
+    return(Status);
+  }
+
+  FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
+  Status = ProtectBootIni(BootIniPath,
+                         FileAttribute);
+
+  IniCacheDestroy(Cache);
+
+  return(Status);
+}
+
+/* EOF */
diff --git a/subsys/system/usetup/bootsup.h b/subsys/system/usetup/bootsup.h
new file mode 100644 (file)
index 0000000..2bf1180
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/bootsup.h
+ * PURPOSE:         Bootloader support functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+#ifndef __BOOTSUP_H__
+#define __BOOTSUP_H__
+
+NTSTATUS
+CreateFreeLoaderIniForDos(PWCHAR IniPath,
+                         PWCHAR ArcPath);
+
+NTSTATUS
+CreateFreeLoaderIniForReactos(PWCHAR IniPath,
+                             PWCHAR ArcPath);
+
+NTSTATUS
+UpdateFreeLoaderIni(PWCHAR IniPath,
+                   PWCHAR ArcPath);
+
+NTSTATUS
+SaveCurrentBootSector(PWSTR RootPath,
+                     PWSTR DstPath);
+
+NTSTATUS
+InstallFat16BootCodeToFile(PWSTR SrcPath,
+                          PWSTR DstPath,
+                          PWSTR RootPath);
+
+NTSTATUS
+InstallFat32BootCodeToFile(PWSTR SrcPath,
+                          PWSTR DstPath,
+                          PWSTR RootPath);
+
+NTSTATUS
+InstallFat16BootCodeToDisk(PWSTR SrcPath,
+                          PWSTR RootPath);
+
+NTSTATUS
+InstallFat32BootCodeToDisk(PWSTR SrcPath,
+                          PWSTR RootPath);
+
+
+NTSTATUS
+UpdateBootIni(PWSTR BootIniPath,
+             PWSTR EntryName,
+             PWSTR EntryValue);
+
+#endif /* __BOOTSUP_H__ */
+
+/* EOF */
diff --git a/subsys/system/usetup/filequeue.c b/subsys/system/usetup/filequeue.c
new file mode 100644 (file)
index 0000000..5b2ae96
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/filequeue.c
+ * PURPOSE:         File queue functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "filesup.h"
+#include "filequeue.h"
+
+
+/* INCLUDES *****************************************************************/
+
+
+typedef struct _QUEUEENTRY
+{
+  struct _QUEUEENTRY *Prev;
+  struct _QUEUEENTRY *Next;
+
+  PWSTR SourceRootPath;
+  PWSTR SourcePath;
+  PWSTR SourceFilename;
+  PWSTR TargetDirectory;
+  PWSTR TargetFilename;
+
+} QUEUEENTRY, *PQUEUEENTRY;
+
+
+typedef struct _FILEQUEUEHEADER
+{
+  PQUEUEENTRY CopyHead;
+  PQUEUEENTRY CopyTail;
+  ULONG CopyCount;
+} FILEQUEUEHEADER, *PFILEQUEUEHEADER;
+
+
+/* FUNCTIONS ****************************************************************/
+
+HSPFILEQ
+SetupOpenFileQueue(VOID)
+{
+  PFILEQUEUEHEADER QueueHeader;
+
+  /* Allocate queue header */
+  QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
+                                                 0,
+                                                 sizeof(FILEQUEUEHEADER));
+  if (QueueHeader == NULL)
+    return(NULL);
+
+  /* Initialize queue header */
+  RtlZeroMemory(QueueHeader,
+               sizeof(FILEQUEUEHEADER));
+
+
+  return((HSPFILEQ)QueueHeader);
+}
+
+
+BOOL
+SetupCloseFileQueue(HSPFILEQ QueueHandle)
+{
+  PFILEQUEUEHEADER QueueHeader;
+  PQUEUEENTRY Entry;
+
+  if (QueueHandle == NULL)
+    return(FALSE);
+
+  QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+  /* Delete copy queue */
+  Entry = QueueHeader->CopyHead;
+  while (Entry != NULL)
+    {
+      /* Delete all strings */
+      if (Entry->SourceRootPath != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+      if (Entry->SourcePath != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+      if (Entry->SourceFilename != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+      if (Entry->TargetDirectory != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
+      if (Entry->TargetFilename != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename);
+
+      /* Unlink current queue entry */
+      if (Entry->Next != NULL)
+      {
+       QueueHeader->CopyHead = Entry->Next;
+       QueueHeader->CopyHead->Prev = NULL;
+      }
+      else
+      {
+       QueueHeader->CopyHead = NULL;
+       QueueHeader->CopyTail = NULL;
+      }
+
+      /* Delete queue entry */
+      RtlFreeHeap(ProcessHeap, 0, Entry);
+
+      /* Get next queue entry */
+      Entry = QueueHeader->CopyHead;
+    }
+
+  /* Delete queue header */
+  RtlFreeHeap(ProcessHeap,
+             0,
+             QueueHeader);
+
+  return(TRUE);
+}
+
+
+BOOL
+SetupQueueCopy(HSPFILEQ QueueHandle,
+              PCWSTR SourceRootPath,
+              PCWSTR SourcePath,
+              PCWSTR SourceFilename,
+              PCWSTR TargetDirectory,
+              PCWSTR TargetFilename)
+{
+  PFILEQUEUEHEADER QueueHeader;
+  PQUEUEENTRY Entry;
+  ULONG Length;
+
+  if (QueueHandle == NULL ||
+      SourceRootPath == NULL ||
+      SourceFilename == NULL ||
+      TargetDirectory == NULL)
+    return(FALSE);
+
+  QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+  /* Allocate new queue entry */
+  Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
+                                      0,
+                                      sizeof(QUEUEENTRY));
+  if (Entry == NULL)
+    return(FALSE);
+
+  RtlZeroMemory(Entry,
+               sizeof(QUEUEENTRY));
+
+  /* Copy source root path */
+  Length = wcslen(SourceRootPath);
+  Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         (Length + 1) * sizeof(WCHAR));
+  if (Entry->SourceRootPath == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, Entry);
+    return(FALSE);
+  }
+  wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
+  Entry->SourceRootPath[Length] = (WCHAR)0;
+
+  /* Copy source path */
+  if (SourcePath != NULL)
+  {
+    Length = wcslen(SourcePath);
+    Entry->SourcePath = RtlAllocateHeap(ProcessHeap,
+                                       0,
+                                       (Length + 1) * sizeof(WCHAR));
+    if (Entry->SourcePath == NULL)
+    {
+      RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+      RtlFreeHeap(ProcessHeap, 0, Entry);
+      return(FALSE);
+    }
+    wcsncpy(Entry->SourcePath, SourcePath, Length);
+    Entry->SourcePath[Length] = (WCHAR)0;
+  }
+
+  /* Copy source file name */
+  Length = wcslen(SourceFilename);
+  Entry->SourceFilename = RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         (Length + 1) * sizeof(WCHAR));
+  if (Entry->SourceFilename == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+    RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+    RtlFreeHeap(ProcessHeap, 0, Entry);
+    return(FALSE);
+  }
+  wcsncpy(Entry->SourceFilename, SourceFilename, Length);
+  Entry->SourceFilename[Length] = (WCHAR)0;
+
+  /* Copy target directory */
+  Length = wcslen(TargetDirectory);
+  if (TargetDirectory[Length] == '\\')
+    Length--;
+  Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap,
+                                          0,
+                                          (Length + 1) * sizeof(WCHAR));
+  if (Entry->TargetDirectory == NULL)
+  {
+    RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+    RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+    RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+    RtlFreeHeap(ProcessHeap, 0, Entry);
+    return(FALSE);
+  }
+  wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
+  Entry->TargetDirectory[Length] = (WCHAR)0;
+
+  /* Copy optional target filename */
+  if (TargetFilename != NULL)
+  {
+    Length = wcslen(TargetFilename);
+    Entry->TargetFilename = RtlAllocateHeap(ProcessHeap,
+                                           0,
+                                           (Length + 1) * sizeof(WCHAR));
+    if (Entry->TargetFilename == NULL)
+    {
+      RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+      RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+      RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+      RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
+      RtlFreeHeap(ProcessHeap, 0, Entry);
+      return(FALSE);
+    }
+    wcsncpy(Entry->TargetFilename, TargetFilename, Length);
+    Entry->TargetFilename[Length] = (WCHAR)0;
+  }
+
+  /* Append queue entry */
+  if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL)
+  {
+    Entry->Prev = NULL;
+    Entry->Next = NULL;
+    QueueHeader->CopyHead = Entry;
+    QueueHeader->CopyTail = Entry;
+  }
+  else
+  {
+    Entry->Prev = QueueHeader->CopyTail;
+    Entry->Next = NULL;
+    QueueHeader->CopyTail->Next = Entry;
+    QueueHeader->CopyTail = Entry;
+  }
+  QueueHeader->CopyCount++;
+
+  return(TRUE);
+}
+
+
+BOOL
+SetupCommitFileQueue(HSPFILEQ QueueHandle,
+                    PCWSTR TargetRootPath,
+                    PCWSTR TargetPath,
+                    PSP_FILE_CALLBACK MsgHandler,
+                    PVOID Context)
+{
+  PFILEQUEUEHEADER QueueHeader;
+  PQUEUEENTRY Entry;
+  NTSTATUS Status;
+
+  WCHAR FileSrcPath[MAX_PATH];
+  WCHAR FileDstPath[MAX_PATH];
+
+  if (QueueHandle == NULL)
+    return(FALSE);
+
+  QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+  MsgHandler(Context,
+            SPFILENOTIFY_STARTQUEUE,
+            NULL,
+            NULL);
+
+  MsgHandler(Context,
+            SPFILENOTIFY_STARTSUBQUEUE,
+            (PVOID)FILEOP_COPY,
+            (PVOID)QueueHeader->CopyCount);
+
+  /* Commit copy queue */
+  Entry = QueueHeader->CopyHead;
+  while (Entry != NULL)
+  {
+    /* Build the full source path */
+    wcscpy(FileSrcPath, Entry->SourceRootPath);
+    if (Entry->SourcePath != NULL)
+      wcscat(FileSrcPath, Entry->SourcePath);
+    wcscat(FileSrcPath, L"\\");
+    wcscat(FileSrcPath, Entry->SourceFilename);
+
+    /* Build the full target path */
+    wcscpy(FileDstPath, TargetRootPath);
+    if (Entry->TargetDirectory[0] == L'\\')
+    {
+      wcscat(FileDstPath, Entry->TargetDirectory);
+    }
+    else
+    {
+      if (TargetPath != NULL)
+      {
+       if (TargetPath[0] != L'\\')
+         wcscat(FileDstPath, L"\\");
+       wcscat(FileDstPath, TargetPath);
+      }
+      wcscat(FileDstPath, L"\\");
+      wcscat(FileDstPath, Entry->TargetDirectory);
+    }
+    wcscat(FileDstPath, L"\\");
+    if (Entry->TargetFilename != NULL)
+      wcscat(FileDstPath, Entry->TargetFilename);
+    else
+      wcscat(FileDstPath, Entry->SourceFilename);
+
+    /* FIXME: Do it! */
+    DPRINT("'%S' ==> '%S'\n",
+          FileSrcPath,
+          FileDstPath);
+
+    MsgHandler(Context,
+              SPFILENOTIFY_STARTCOPY,
+              (PVOID)Entry->SourceFilename,
+              (PVOID)FILEOP_COPY);
+
+    /* Copy the file */
+    Status = SetupCopyFile(FileSrcPath, FileDstPath);
+    if (!NT_SUCCESS(Status))
+    {
+      MsgHandler(Context,
+                SPFILENOTIFY_COPYERROR,
+                (PVOID)Entry->SourceFilename,
+                (PVOID)FILEOP_COPY);
+
+    }
+    else
+    {
+      MsgHandler(Context,
+                SPFILENOTIFY_ENDCOPY,
+                (PVOID)Entry->SourceFilename,
+                (PVOID)FILEOP_COPY);
+    }
+
+    Entry = Entry->Next;
+  }
+
+  MsgHandler(Context,
+            SPFILENOTIFY_ENDSUBQUEUE,
+            (PVOID)FILEOP_COPY,
+            NULL);
+
+  MsgHandler(Context,
+            SPFILENOTIFY_ENDQUEUE,
+            NULL,
+            NULL);
+
+  return(TRUE);
+}
+
+/* EOF */
diff --git a/subsys/system/usetup/filequeue.h b/subsys/system/usetup/filequeue.h
new file mode 100644 (file)
index 0000000..591adfa
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/filequeue.h
+ * PURPOSE:         File queue functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+#ifndef __FILEQUEUE_H__
+#define __FILEQUEUE_H__
+
+
+#define SPFILENOTIFY_STARTQUEUE       0x1
+#define SPFILENOTIFY_ENDQUEUE         0x2
+#define SPFILENOTIFY_STARTSUBQUEUE    0x3
+#define SPFILENOTIFY_ENDSUBQUEUE      0x4
+
+#define SPFILENOTIFY_STARTCOPY        0xb
+#define SPFILENOTIFY_ENDCOPY          0xc
+#define SPFILENOTIFY_COPYERROR        0xd
+
+#define FILEOP_COPY                   0x0
+#define FILEOP_RENAME                 0x1
+#define FILEOP_DELETE                 0x2
+#define FILEOP_BACKUP                 0x3
+
+#define FILEOP_ABORT                  0x0
+#define FILEOP_DOIT                   0x1
+#define FILEOP_SKIP                   0x2
+#define FILEOP_RETRY                  FILEOP_DOIT
+#define FILEOP_NEWPATH                0x4
+
+
+/* TYPES ********************************************************************/
+
+typedef PVOID HSPFILEQ;
+
+typedef ULONG (*PSP_FILE_CALLBACK)(PVOID Context,
+                                  ULONG Notification,
+                                  PVOID Param1,
+                                  PVOID Param2);
+
+
+/* FUNCTIONS ****************************************************************/
+
+HSPFILEQ
+SetupOpenFileQueue(VOID);
+
+BOOL
+SetupCloseFileQueue(HSPFILEQ QueueHandle);
+
+BOOL
+SetupQueueCopy(HSPFILEQ QueueHandle,
+              PCWSTR SourceRootPath,
+              PCWSTR SourcePath,
+              PCWSTR SourceFilename,
+              PCWSTR TargetDirectory,
+              PCWSTR TargetFilename);
+
+BOOL
+SetupCommitFileQueue(HSPFILEQ QueueHandle,
+                    PCWSTR TargetRootPath,
+                    PCWSTR TargetPath,
+                    PSP_FILE_CALLBACK MsgHandler,
+                    PVOID Context);
+
+#endif /* __FILEQUEUE_H__ */
+
+/* EOF */
diff --git a/subsys/system/usetup/filesup.c b/subsys/system/usetup/filesup.c
new file mode 100644 (file)
index 0000000..f735dc0
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/filesup.c
+ * PURPOSE:         File support functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "filesup.h"
+
+
+/* FUNCTIONS ****************************************************************/
+
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING PathName;
+  HANDLE DirectoryHandle;
+  NTSTATUS Status;
+
+  RtlCreateUnicodeString(&PathName,
+                        DirectoryName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &PathName,
+                            OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&DirectoryHandle,
+                       DIRECTORY_ALL_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_DIRECTORY,
+                       0,
+                       FILE_CREATE,
+                       FILE_DIRECTORY_FILE,
+                       NULL,
+                       0);
+  if (NT_SUCCESS(Status))
+    {
+      NtClose(DirectoryHandle);
+    }
+
+  RtlFreeUnicodeString(&PathName);
+
+  return(Status);
+}
+
+
+NTSTATUS
+SetupCopyFile(PWCHAR SourceFileName,
+             PWCHAR DestinationFileName)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  HANDLE FileHandleSource;
+  HANDLE FileHandleDest;
+  IO_STATUS_BLOCK IoStatusBlock;
+  FILE_STANDARD_INFORMATION FileStandard;
+  FILE_BASIC_INFORMATION FileBasic;
+  FILE_POSITION_INFORMATION FilePosition;
+  PUCHAR Buffer;
+  ULONG RegionSize;
+  UNICODE_STRING FileName;
+  NTSTATUS Status;
+
+  Buffer = NULL;
+
+  RtlInitUnicodeString(&FileName,
+                      SourceFileName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &FileName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandleSource,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     FILE_SHARE_READ,
+                     FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      return(Status);
+    }
+
+  Status = NtQueryInformationFile(FileHandleSource,
+                                 &IoStatusBlock,
+                                 &FileStandard,
+                                 sizeof(FILE_STANDARD_INFORMATION),
+                                 FileStandardInformation);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+     NtClose(FileHandleSource);
+     return(Status);
+    }
+
+  Status = NtQueryInformationFile(FileHandleSource,
+                                 &IoStatusBlock,&FileBasic,
+                                 sizeof(FILE_BASIC_INFORMATION),
+                                 FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      NtClose(FileHandleSource);
+      return(Status);
+    }
+
+  RtlInitUnicodeString(&FileName,
+                      DestinationFileName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &FileName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandleDest,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_OVERWRITE_IF,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      NtClose(FileHandleSource);
+      return(Status);
+    }
+
+  FilePosition.CurrentByteOffset.QuadPart = 0;
+
+  Status = NtSetInformationFile(FileHandleSource,
+                               &IoStatusBlock,
+                               &FilePosition,
+                               sizeof(FILE_POSITION_INFORMATION),
+                               FilePositionInformation);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      NtClose(FileHandleSource);
+      NtClose(FileHandleDest);
+      return(Status);
+    }
+
+  Status = NtSetInformationFile(FileHandleDest,
+                               &IoStatusBlock,
+                               &FilePosition,
+                               sizeof(FILE_POSITION_INFORMATION),
+                               FilePositionInformation);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      NtClose(FileHandleSource);
+      NtClose(FileHandleDest);
+      return(Status);
+    }
+
+  RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
+  if (RegionSize > 0x100000)
+    {
+      RegionSize = 0x100000;
+    }
+  Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+                                  (PVOID *)&Buffer,
+                                  2,
+                                  &RegionSize,
+                                  MEM_RESERVE | MEM_COMMIT,
+                                  PAGE_READWRITE);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      NtClose(FileHandleSource);
+      NtClose(FileHandleDest);
+      return(Status);
+    }
+
+  while (TRUE)
+    {
+      Status = NtReadFile(FileHandleSource,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         Buffer,
+                         RegionSize,
+                         NULL,
+                         NULL);
+      if (!NT_SUCCESS(Status))
+       {
+         NtFreeVirtualMemory(NtCurrentProcess(),
+                             (PVOID *)&Buffer,
+                             &RegionSize,
+                             MEM_RELEASE);
+         if (Status == STATUS_END_OF_FILE)
+           {
+             DPRINT("STATUS_END_OF_FILE\n");
+             break;
+           }
+CHECKPOINT1;
+         NtClose(FileHandleSource);
+         NtClose(FileHandleDest);
+         return(Status);
+       }
+
+      DPRINT("Bytes read %lu\n", IoStatusBlock.Information);
+
+      Status = NtWriteFile(FileHandleDest,
+                          NULL,
+                          NULL,
+                          NULL,
+                          &IoStatusBlock,
+                          Buffer,
+                          IoStatusBlock.Information,
+                          NULL,
+                          NULL);
+      if (!NT_SUCCESS(Status))
+       {
+CHECKPOINT1;
+         NtFreeVirtualMemory(NtCurrentProcess(),
+                             (PVOID *)&Buffer,
+                             &RegionSize,
+                             MEM_RELEASE);
+         NtClose(FileHandleSource);
+         NtClose(FileHandleDest);
+         return(Status);
+       }
+    }
+
+
+  /* Copy file date/time from source file */
+  Status = NtSetInformationFile(FileHandleDest,
+                               &IoStatusBlock,
+                               &FileBasic,
+                               sizeof(FILE_BASIC_INFORMATION),
+                               FileBasicInformation);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+    }
+
+  NtClose(FileHandleSource);
+  NtClose(FileHandleDest);
+
+  return(Status);
+}
+
+
+BOOLEAN
+DoesFileExist(PWSTR PathName,
+             PWSTR FileName)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  UNICODE_STRING Name;
+  WCHAR FullName[MAX_PATH];
+  HANDLE FileHandle;
+  NTSTATUS Status;
+
+  wcscpy(FullName, PathName);
+  if (FileName != NULL)
+    {
+      if (FileName[0] != L'\\')
+       wcscat(FullName, L"\\");
+      wcscat(FullName, FileName);
+    }
+
+  RtlInitUnicodeString(&Name,
+                      FullName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     FILE_READ_ACCESS,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     0,
+                     FILE_SYNCHRONOUS_IO_ALERT);
+  if (!NT_SUCCESS(Status))
+    {
+CHECKPOINT1;
+      return(FALSE);
+    }
+
+  NtClose(FileHandle);
+
+  return(TRUE);
+}
+
+/* EOF */
diff --git a/subsys/system/usetup/filesup.h b/subsys/system/usetup/filesup.h
new file mode 100644 (file)
index 0000000..949c75e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/filesup.h
+ * PURPOSE:         File support functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+#ifndef __FILESUP_H__
+#define __FILESUP_H__
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName);
+
+NTSTATUS
+SetupCopyFile(PWCHAR SourceFileName,
+             PWCHAR DestinationFileName);
+
+BOOLEAN
+DoesFileExist(PWSTR PathName,
+             PWSTR FileName);
+
+
+#endif /* __FILESUP_H__ */
+
+/* EOF */
diff --git a/subsys/system/usetup/inicache.c b/subsys/system/usetup/inicache.c
new file mode 100644 (file)
index 0000000..6c90eed
--- /dev/null
@@ -0,0 +1,1202 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/inicache.c
+ * PURPOSE:         INI file parser that caches contents of INI file in memory
+ * PROGRAMMER:      Royce Mitchell III
+ *                  Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include "usetup.h"
+#include "inicache.h"
+
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static PINICACHEKEY
+IniCacheFreeKey(PINICACHEKEY Key)
+{
+  PINICACHEKEY Next;
+
+  if (Key == NULL)
+    {
+      return(NULL);
+    }
+
+  Next = Key->Next;
+  if (Key->Name != NULL)
+    {
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key->Name);
+      Key->Name = NULL;
+    }
+
+  if (Key->Data != NULL)
+    {
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key->Data);
+      Key->Data = NULL;
+    }
+
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Key);
+
+  return(Next);
+}
+
+
+static PINICACHESECTION
+IniCacheFreeSection(PINICACHESECTION Section)
+{
+  PINICACHESECTION Next;
+
+  if (Section == NULL)
+    {
+      return(NULL);
+    }
+
+  Next = Section->Next;
+  while (Section->FirstKey != NULL)
+    {
+      Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
+    }
+  Section->LastKey = NULL;
+
+  if (Section->Name != NULL)
+    {
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Section->Name);
+      Section->Name = NULL;
+    }
+
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Section);
+
+  return(Next);
+}
+
+
+static PINICACHEKEY
+IniCacheFindKey(PINICACHESECTION Section,
+               PWCHAR Name,
+               ULONG NameLength)
+{
+  PINICACHEKEY Key;
+
+  Key = Section->FirstKey;
+  while (Key != NULL)
+    {
+      if (NameLength == wcslen(Key->Name))
+       {
+         if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
+           break;
+       }
+
+      Key = Key->Next;
+    }
+
+  return(Key);
+}
+
+
+static PINICACHEKEY
+IniCacheAddKey(PINICACHESECTION Section,
+              PCHAR Name,
+              ULONG NameLength,
+              PCHAR Data,
+              ULONG DataLength)
+{
+  PINICACHEKEY Key;
+  ULONG i;
+
+  Key = NULL;
+
+  if (Section == NULL ||
+      Name == NULL ||
+      NameLength == 0 ||
+      Data == NULL ||
+      DataLength == 0)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+                                     0,
+                                     sizeof(INICACHEKEY));
+  if (Key == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+
+  RtlZeroMemory(Key,
+               sizeof(INICACHEKEY));
+
+
+  Key->Name = RtlAllocateHeap(ProcessHeap,
+                             0,
+                             (NameLength + 1) * sizeof(WCHAR));
+  if (Key->Name == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key);
+      return(NULL);
+    }
+
+  /* Copy value name */
+  for (i = 0; i < NameLength; i++)
+    {
+      Key->Name[i] = (WCHAR)Name[i];
+    }
+  Key->Name[NameLength] = 0;
+
+
+  Key->Data = RtlAllocateHeap(ProcessHeap,
+                             0,
+                             (DataLength + 1) * sizeof(WCHAR));
+  if (Key->Data == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key->Name);
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key);
+      return(NULL);
+    }
+
+  /* Copy value data */
+  for (i = 0; i < DataLength; i++)
+    {
+      Key->Data[i] = (WCHAR)Data[i];
+    }
+  Key->Data[DataLength] = 0;
+
+
+  if (Section->FirstKey == NULL)
+    {
+      Section->FirstKey = Key;
+      Section->LastKey = Key;
+    }
+  else
+    {
+      Section->LastKey->Next = Key;
+      Key->Prev = Section->LastKey;
+      Section->LastKey = Key;
+    }
+
+  return(Key);
+}
+
+
+static PINICACHESECTION
+IniCacheFindSection(PINICACHE Cache,
+                   PWCHAR Name,
+                   ULONG NameLength)
+{
+  PINICACHESECTION Section = NULL;
+
+  if (Cache == NULL || Name == NULL || NameLength == 0)
+    {
+      return(NULL);
+    }
+
+  Section = Cache->FirstSection;
+
+  /* iterate through list of sections */
+  while (Section != NULL)
+    {
+      if (NameLength == wcslen(Section->Name))
+       {
+         /* are the contents the same too? */
+         if (_wcsnicmp(Section->Name, Name, NameLength) == 0)
+           break;
+       }
+
+      /* get the next section*/
+      Section = Section->Next;
+    }
+
+  return(Section);
+}
+
+
+static PINICACHESECTION
+IniCacheAddSection(PINICACHE Cache,
+                  PCHAR Name,
+                  ULONG NameLength)
+{
+  PINICACHESECTION Section = NULL;
+  ULONG i;
+
+  if (Cache == NULL || Name == NULL || NameLength == 0)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+                                             0,
+                                             sizeof(INICACHESECTION));
+  if (Section == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+  RtlZeroMemory(Section,
+               sizeof(INICACHESECTION));
+
+  /* Allocate and initialize section name */
+  Section->Name = RtlAllocateHeap(ProcessHeap,
+                                 0,
+                                 (NameLength + 1) * sizeof(WCHAR));
+  if (Section->Name == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Section);
+      return(NULL);
+    }
+
+  /* Copy section name */
+  for (i = 0; i < NameLength; i++)
+    {
+      Section->Name[i] = (WCHAR)Name[i];
+    }
+  Section->Name[NameLength] = 0;
+
+  /* Append section */
+  if (Cache->FirstSection == NULL)
+    {
+      Cache->FirstSection = Section;
+      Cache->LastSection = Section;
+    }
+  else
+    {
+      Cache->LastSection->Next = Section;
+      Section->Prev = Cache->LastSection;
+      Cache->LastSection = Section;
+    }
+
+  return(Section);
+}
+
+
+static PCHAR
+IniCacheSkipWhitespace(PCHAR Ptr)
+{
+  while (*Ptr != 0 && isspace(*Ptr))
+    Ptr++;
+
+  return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheSkipToNextSection(PCHAR Ptr)
+{
+  while (*Ptr != 0 && *Ptr != '[')
+    {
+      while (*Ptr != 0 && *Ptr != L'\n')
+       {
+         Ptr++;
+       }
+      Ptr++;
+    }
+
+  return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheGetSectionName(PCHAR Ptr,
+                      PCHAR *NamePtr,
+                      PULONG NameSize)
+{
+  ULONG Size = 0;
+  CHAR Name[256];
+
+  *NamePtr = NULL;
+  *NameSize = 0;
+
+  /* skip whitespace */
+  while (*Ptr != 0 && isspace(*Ptr))
+    {
+      Ptr++;
+    }
+
+  *NamePtr = Ptr;
+
+  while (*Ptr != 0 && *Ptr != ']')
+    {
+      Size++;
+      Ptr++;
+    }
+
+  Ptr++;
+
+  while (*Ptr != 0 && *Ptr != L'\n')
+    {
+      Ptr++;
+    }
+  Ptr++;
+
+  *NameSize = Size;
+
+  strncpy(Name, *NamePtr, Size);
+  Name[Size] = 0;
+
+  DPRINT("SectionName: '%s'\n", Name);
+
+  return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyName(PCHAR Ptr,
+                  PCHAR *NamePtr,
+                  PULONG NameSize)
+{
+  ULONG Size = 0;
+
+  *NamePtr = NULL;
+  *NameSize = 0;
+
+  while(Ptr && *Ptr)
+  {
+    *NamePtr = NULL;
+    *NameSize = 0;
+    Size = 0;
+
+    /* skip whitespace and empty lines */
+    while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r')
+    {
+      Ptr++;
+    }
+    if (*Ptr == 0)
+    {
+      continue;
+    }
+
+    *NamePtr = Ptr;
+
+    while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';')
+    {
+      Size++;
+      Ptr++;
+    }
+    if (*Ptr == ';')
+    {
+      while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n')
+      {
+       Ptr++;
+      }
+    }
+    else
+    {
+      *NameSize = Size;
+      break;
+    }
+  }
+
+  return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyValue(PCHAR Ptr,
+                   PCHAR *DataPtr,
+                   PULONG DataSize,
+                   BOOL String)
+{
+  ULONG Size = 0;
+
+  *DataPtr = NULL;
+  *DataSize = 0;
+
+  /* Skip whitespace */
+  while (*Ptr != 0 && isspace(*Ptr))
+    {
+      Ptr++;
+    }
+
+  /* Check and skip '=' */
+  if (*Ptr != '=')
+    {
+      return(NULL);
+    }
+  Ptr++;
+
+  /* Skip whitespace */
+  while (*Ptr != 0 && isspace(*Ptr))
+    {
+      Ptr++;
+    }
+
+  if (*Ptr == '"' && String)
+    {
+      Ptr++;
+
+      /* Get data */
+      *DataPtr = Ptr;
+      while (*Ptr != '"')
+       {
+         Ptr++;
+         Size++;
+       }
+      Ptr++;
+      while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
+       {
+         Ptr++;
+       }
+    }
+  else
+    {
+      /* Get data */
+      *DataPtr = Ptr;
+      while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
+       {
+         Ptr++;
+         Size++;
+       }
+    }
+
+  /* Skip to next line */
+  if (*Ptr == '\r')
+    Ptr++;
+  if (*Ptr == '\n')
+    Ptr++;
+
+  *DataSize = Size;
+
+  return(Ptr);
+}
+
+
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+            PUNICODE_STRING FileName,
+            BOOL String)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  FILE_STANDARD_INFORMATION FileInfo;
+  IO_STATUS_BLOCK IoStatusBlock;
+  HANDLE FileHandle;
+  NTSTATUS Status;
+  PCHAR FileBuffer;
+  ULONG FileLength;
+  PCHAR Ptr;
+  LARGE_INTEGER FileOffset;
+
+  ULONG i;
+  PINICACHESECTION Section;
+  PINICACHEKEY Key;
+
+  PCHAR SectionName;
+  ULONG SectionNameSize;
+
+  PCHAR KeyName;
+  ULONG KeyNameSize;
+
+  PCHAR KeyValue;
+  ULONG KeyValueSize;
+
+  *Cache = NULL;
+
+  /* Open ini file */
+  InitializeObjectAttributes(&ObjectAttributes,
+                            FileName,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenFile(&FileHandle,
+                     GENERIC_READ | SYNCHRONIZE,
+                     &ObjectAttributes,
+                     &IoStatusBlock,
+                     FILE_SHARE_READ,
+                     FILE_NON_DIRECTORY_FILE);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
+      return(Status);
+    }
+
+  DPRINT("NtOpenFile() successful\n");
+
+  /* Query file size */
+  Status = NtQueryInformationFile(FileHandle,
+                                 &IoStatusBlock,
+                                 &FileInfo,
+                                 sizeof(FILE_STANDARD_INFORMATION),
+                                 FileStandardInformation);
+  if (Status == STATUS_PENDING)
+    {
+      DPRINT("NtQueryInformationFile() returns STATUS_PENDING\n");
+
+    }
+  else if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+      NtClose(FileHandle);
+      return(Status);
+    }
+
+  FileLength = FileInfo.EndOfFile.u.LowPart;
+
+  DPRINT("File size: %lu\n", FileLength);
+
+  /* Allocate file buffer */
+  FileBuffer = RtlAllocateHeap(ProcessHeap,
+                              0,
+                              FileLength + 1);
+  if (FileBuffer == NULL)
+    {
+      DPRINT1("RtlAllocateHeap() failed\n");
+      NtClose(FileHandle);
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  /* Read file */
+  FileOffset.QuadPart = 0ULL;
+  Status = NtReadFile(FileHandle,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &IoStatusBlock,
+                     FileBuffer,
+                     FileLength,
+                     &FileOffset,
+                     NULL);
+
+  if (Status == STATUS_PENDING)
+    {
+      DPRINT("NtReadFile() returns STATUS_PENDING\n");
+
+      Status = IoStatusBlock.Status;
+    }
+
+  /* Append string terminator */
+  FileBuffer[FileLength] = 0;
+
+  NtClose(FileHandle);
+
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 FileBuffer);
+      return(Status);
+    }
+
+
+  /* Allocate inicache header */
+  *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+                                     0,
+                                     sizeof(INICACHE));
+  if (*Cache == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  /* Initialize inicache header */
+  RtlZeroMemory(*Cache,
+               sizeof(INICACHE));
+
+  /* Parse ini file */
+  Section = NULL;
+  Ptr = FileBuffer;
+  while (Ptr != NULL && *Ptr != 0)
+    {
+      Ptr = IniCacheSkipWhitespace(Ptr);
+      if (Ptr == NULL)
+       continue;
+
+      if (*Ptr == '[')
+       {
+         Section = NULL;
+         Ptr++;
+
+         Ptr = IniCacheGetSectionName(Ptr,
+                                      &SectionName,
+                                      &SectionNameSize);
+
+         DPRINT1("[%.*s]\n", SectionNameSize, SectionName);
+
+         Section = IniCacheAddSection(*Cache,
+                                      SectionName,
+                                      SectionNameSize);
+         if (Section == NULL)
+           {
+             DPRINT("IniCacheAddSection() failed\n");
+             Ptr = IniCacheSkipToNextSection(Ptr);
+             continue;
+           }
+       }
+      else
+       {
+         if (Section == NULL)
+           {
+             Ptr = IniCacheSkipToNextSection(Ptr);
+             continue;
+           }
+
+         Ptr = IniCacheGetKeyName(Ptr,
+                                  &KeyName,
+                                  &KeyNameSize);
+
+         Ptr = IniCacheGetKeyValue(Ptr,
+                                   &KeyValue,
+                                   &KeyValueSize,
+                                   String);
+
+         DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue);
+
+         Key = IniCacheAddKey(Section,
+                              KeyName,
+                              KeyNameSize,
+                              KeyValue,
+                              KeyValueSize);
+         if (Key == NULL)
+           {
+             DPRINT("IniCacheAddKey() failed\n");
+           }
+       }
+    }
+
+  /* Free file buffer */
+  RtlFreeHeap(ProcessHeap,
+             0,
+             FileBuffer);
+
+  return(Status);
+}
+
+
+VOID
+IniCacheDestroy(PINICACHE Cache)
+{
+  if (Cache == NULL)
+    {
+      return;
+    }
+
+  while (Cache->FirstSection != NULL)
+    {
+      Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
+    }
+  Cache->LastSection = NULL;
+
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Cache);
+}
+
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+                  PWCHAR Name)
+{
+  PINICACHESECTION Section = NULL;
+
+  if (Cache == NULL || Name == NULL)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  /* Iterate through list of sections */
+  Section = Cache->FirstSection;
+  while (Section != NULL)
+    {
+      DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
+
+      /* Are the section names the same? */
+      if (_wcsicmp(Section->Name, Name) == 0)
+       return(Section);
+
+      /* Get the next section */
+      Section = Section->Next;
+    }
+
+  DPRINT("Section not found\n");
+
+  return(NULL);
+}
+
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+              PWCHAR KeyName,
+              PWCHAR *KeyData)
+{
+  PINICACHEKEY Key;
+
+  if (Section == NULL || KeyName == NULL || KeyData == NULL)
+    {
+      DPRINT("Invalid parameter\n");
+      return(STATUS_INVALID_PARAMETER);
+    }
+
+  *KeyData = NULL;
+
+  Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
+  if (Key == NULL)
+    {
+      return(STATUS_INVALID_PARAMETER);
+    }
+
+  *KeyData = Key->Data;
+
+  return(STATUS_SUCCESS);
+}
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+                      PWCHAR *KeyName,
+                      PWCHAR *KeyData)
+{
+  PINICACHEITERATOR Iterator;
+  PINICACHEKEY Key;
+
+  if (Section == NULL || KeyName == NULL || KeyData == NULL)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  Key = Section->FirstKey;
+  if (Key == NULL)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  *KeyName = Key->Name;
+  *KeyData = Key->Data;
+
+  Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
+                                               0,
+                                               sizeof(INICACHEITERATOR));
+  if (Iterator == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+
+  Iterator->Section = Section;
+  Iterator->Key = Key;
+
+  return(Iterator);
+}
+
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+                     PWCHAR *KeyName,
+                     PWCHAR *KeyData)
+{
+  PINICACHEKEY Key;
+
+  if (Iterator == NULL || KeyName == NULL || KeyData == NULL)
+    {
+      DPRINT("Invalid parameter\n");
+      return(FALSE);
+    }
+
+  Key = Iterator->Key->Next;
+  if (Key == NULL)
+    {
+      DPRINT("No more entries\n");
+      return(FALSE);
+    }
+
+  *KeyName = Key->Name;
+  *KeyData = Key->Data;
+
+  Iterator->Key = Key;
+
+  return(TRUE);
+}
+
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator)
+{
+  if (Iterator == NULL)
+    return;
+
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Iterator);
+}
+
+
+PINICACHEKEY
+IniCacheInsertKey(PINICACHESECTION Section,
+                 PINICACHEKEY AnchorKey,
+                 INSERTATION_TYPE InsertationType,
+                 PWCHAR Name,
+                 PWCHAR Data)
+{
+  PINICACHEKEY Key;
+  ULONG i;
+
+  Key = NULL;
+
+  if (Section == NULL ||
+      Name == NULL ||
+      *Name == 0 ||
+      Data == NULL ||
+      *Data == 0)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  /* Allocate key buffer */
+  Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+                                     0,
+                                     sizeof(INICACHEKEY));
+  if (Key == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+  RtlZeroMemory(Key,
+               sizeof(INICACHEKEY));
+
+  /* Allocate name buffer */
+  Key->Name = RtlAllocateHeap(ProcessHeap,
+                             0,
+                             (wcslen(Name) + 1) * sizeof(WCHAR));
+  if (Key->Name == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key);
+      return(NULL);
+    }
+
+  /* Copy value name */
+  wcscpy(Key->Name, Name);
+
+  /* Allocate data buffer */
+  Key->Data = RtlAllocateHeap(ProcessHeap,
+                             0,
+                             (wcslen(Data) + 1) * sizeof(WCHAR));
+  if (Key->Data == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key->Name);
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Key);
+      return(NULL);
+    }
+
+  /* Copy value data */
+  wcscpy(Key->Data, Data);
+
+  /* Insert key into section */
+  if (Section->FirstKey == NULL)
+    {
+      Section->FirstKey = Key;
+      Section->LastKey = Key;
+    }
+  else if ((InsertationType == INSERT_FIRST) ||
+          ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey))))
+    {
+      /* Insert at the head of the list */
+      Section->FirstKey->Prev = Key;
+      Key->Next = Section->FirstKey;
+      Section->FirstKey = Key;
+    }
+  else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL))
+    {
+      /* Insert before the anchor key */
+      Key->Next = AnchorKey;
+      Key->Prev = AnchorKey->Prev;
+      AnchorKey->Prev->Next = Key;
+      AnchorKey->Prev = Key;
+    }
+  else if ((InsertationType == INSERT_LAST) ||
+          ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey))))
+    {
+      Section->LastKey->Next = Key;
+      Key->Prev = Section->LastKey;
+      Section->LastKey = Key;
+    }
+  else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL))
+    {
+      /* Insert before the anchor key */
+      Key->Next = AnchorKey->Next;
+      Key->Prev = AnchorKey;
+      AnchorKey->Next->Prev = Key;
+      AnchorKey->Next = Key;
+    }
+
+  return(Key);
+}
+
+
+PINICACHE
+IniCacheCreate(VOID)
+{
+  PINICACHE Cache;
+
+  /* Allocate inicache header */
+  Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+                                    0,
+                                    sizeof(INICACHE));
+  if (Cache == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+
+  /* Initialize inicache header */
+  RtlZeroMemory(Cache,
+               sizeof(INICACHE));
+
+  return(Cache);
+}
+
+
+NTSTATUS
+IniCacheSave(PINICACHE Cache,
+            PWCHAR FileName)
+{
+  UNICODE_STRING Name;
+  PINICACHESECTION Section;
+  PINICACHEKEY Key;
+  ULONG BufferSize;
+  PCHAR Buffer;
+  PCHAR Ptr;
+  ULONG Len;
+  NTSTATUS Status;
+
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  IO_STATUS_BLOCK IoStatusBlock;
+  LARGE_INTEGER Offset;
+  HANDLE FileHandle;
+
+
+  /* Calculate required buffer size */
+  BufferSize = 0;
+  Section = Cache->FirstSection;
+  while (Section != NULL)
+    {
+      BufferSize += (Section->Name ? wcslen(Section->Name) : 0)
+                   + 4; /* "[]\r\n" */
+
+      Key = Section->FirstKey;
+      while (Key != NULL)
+       {
+         BufferSize += wcslen(Key->Name)
+                       + (Key->Data ? wcslen(Key->Data) : 0)
+                       + 3; /* "=\r\n" */
+         Key = Key->Next;
+       }
+
+      Section = Section->Next;
+      if (Section != NULL)
+       BufferSize += 2; /* extra "\r\n" at end of each section */
+    }
+  BufferSize++; /* Null-terminator */
+
+  DPRINT1("BufferSize: %lu\n", BufferSize);
+
+  /* Allocate file buffer */
+  Buffer = RtlAllocateHeap(ProcessHeap,
+                          0,
+                          BufferSize);
+  if (Buffer == NULL)
+    {
+      DPRINT1("RtlAllocateHeap() failed\n");
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+  RtlZeroMemory(Buffer, BufferSize);
+
+  /* Fill file buffer */
+  Ptr = Buffer;
+  Section = Cache->FirstSection;
+  while (Section != NULL)
+    {
+      Len = sprintf(Ptr, "[%S]\r\n", Section->Name);
+      Ptr += Len;
+
+      Key = Section->FirstKey;
+      while (Key != NULL)
+       {
+         Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data);
+         Ptr += Len;
+         Key = Key->Next;
+       }
+
+      Section = Section->Next;
+      if (Section != NULL)
+       {
+         Len = sprintf(Ptr, "\r\n");
+         Ptr += Len;
+       }
+    }
+
+  /* Create ini file */
+  RtlInitUnicodeString(&Name,
+                      FileName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &Name,
+                            0,
+                            NULL,
+                            NULL);
+
+  Status = NtCreateFile(&FileHandle,
+                       FILE_WRITE_ACCESS,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       FILE_SUPERSEDE,
+                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Buffer);
+      return(Status);
+    }
+
+  Offset.QuadPart = 0LL;
+  Status = NtWriteFile(FileHandle,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &IoStatusBlock,
+                      Buffer,
+                      BufferSize,
+                      &Offset,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+      NtClose(FileHandle);
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Buffer);
+      return(Status);
+    }
+
+  NtClose(FileHandle);
+
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Buffer);
+
+  return(STATUS_SUCCESS);
+}
+
+
+PINICACHESECTION
+IniCacheAppendSection(PINICACHE Cache,
+                     PWCHAR Name)
+{
+  PINICACHESECTION Section = NULL;
+  ULONG i;
+
+  if (Cache == NULL || Name == NULL || *Name == 0)
+    {
+      DPRINT("Invalid parameter\n");
+      return(NULL);
+    }
+
+  Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+                                             0,
+                                             sizeof(INICACHESECTION));
+  if (Section == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      return(NULL);
+    }
+  RtlZeroMemory(Section,
+               sizeof(INICACHESECTION));
+
+  /* Allocate and initialize section name */
+  Section->Name = RtlAllocateHeap(ProcessHeap,
+                                 0,
+                                 (wcslen(Name) + 1) * sizeof(WCHAR));
+  if (Section->Name == NULL)
+    {
+      DPRINT("RtlAllocateHeap() failed\n");
+      RtlFreeHeap(ProcessHeap,
+                 0,
+                 Section);
+      return(NULL);
+    }
+
+  /* Copy section name */
+  wcscpy(Section->Name, Name);
+
+  /* Append section */
+  if (Cache->FirstSection == NULL)
+    {
+      Cache->FirstSection = Section;
+      Cache->LastSection = Section;
+    }
+  else
+    {
+      Cache->LastSection->Next = Section;
+      Section->Prev = Cache->LastSection;
+      Cache->LastSection = Section;
+    }
+
+  return(Section);
+}
+
+/* EOF */
diff --git a/subsys/system/usetup/inicache.h b/subsys/system/usetup/inicache.h
new file mode 100644 (file)
index 0000000..e22a8ac
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/inicache.h
+ * PURPOSE:         INI file parser that caches contents of INI file in memory
+ * PROGRAMMER:      Royce Mitchell III
+ *                  Eric Kohl
+ */
+
+#ifndef __INICACHE_H__
+#define __INICACHE_H__
+
+
+typedef struct _INICACHEKEY
+{
+  PWCHAR Name;
+  PWCHAR Data;
+
+  struct _INICACHEKEY *Next;
+  struct _INICACHEKEY *Prev;
+} INICACHEKEY, *PINICACHEKEY;
+
+
+typedef struct _INICACHESECTION
+{
+  PWCHAR Name;
+
+  PINICACHEKEY FirstKey;
+  PINICACHEKEY LastKey;
+
+  struct _INICACHESECTION *Next;
+  struct _INICACHESECTION *Prev;
+} INICACHESECTION, *PINICACHESECTION;
+
+
+typedef struct _INICACHE
+{
+  PINICACHESECTION FirstSection;
+  PINICACHESECTION LastSection;
+} INICACHE, *PINICACHE;
+
+
+typedef struct _PINICACHEITERATOR
+{
+  PINICACHESECTION Section;
+  PINICACHEKEY Key;
+} INICACHEITERATOR, *PINICACHEITERATOR;
+
+
+typedef enum
+{
+  INSERT_FIRST,
+  INSERT_BEFORE,
+  INSERT_AFTER,
+  INSERT_LAST
+} INSERTATION_TYPE;
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+            PUNICODE_STRING FileName,
+            BOOL String);
+
+VOID
+IniCacheDestroy(PINICACHE Cache);
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+                  PWCHAR Name);
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+              PWCHAR KeyName,
+              PWCHAR *KeyData);
+
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+                      PWCHAR *KeyName,
+                      PWCHAR *KeyData);
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+                     PWCHAR *KeyName,
+                     PWCHAR *KeyData);
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator);
+
+
+PINICACHEKEY
+IniCacheInsertKey(PINICACHESECTION Section,
+                 PINICACHEKEY AnchorKey,
+                 INSERTATION_TYPE InsertationType,
+                 PWCHAR Name,
+                 PWCHAR Data);
+
+PINICACHE
+IniCacheCreate(VOID);
+
+NTSTATUS
+IniCacheSave(PINICACHE Cache,
+            PWCHAR FileName);
+
+PINICACHESECTION
+IniCacheAppendSection(PINICACHE Cache,
+                     PWCHAR Name);
+
+
+#endif /* __INICACHE_H__ */
+
+/* EOF */
diff --git a/subsys/system/usetup/progress.c b/subsys/system/usetup/progress.c
new file mode 100644 (file)
index 0000000..9049692
--- /dev/null
@@ -0,0 +1,246 @@
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "progress.h"
+
+/* FUNCTIONS ****************************************************************/
+
+
+static VOID
+DrawBorder(PPROGRESS Bar)
+{
+  COORD coPos;
+  ULONG Written;
+  SHORT i;
+
+  /* draw upper left corner */
+  coPos.X = Bar->Left;
+  coPos.Y = Bar->Top + 1;
+  FillConsoleOutputCharacter(0xDA, // '+',
+                            1,
+                            coPos,
+                            &Written);
+
+  /* draw upper edge */
+  coPos.X = Bar->Left + 1;
+  coPos.Y = Bar->Top + 1;
+  FillConsoleOutputCharacter(0xC4, // '-',
+                            Bar->Right - Bar->Left - 1,
+                            coPos,
+                            &Written);
+
+  /* draw upper right corner */
+  coPos.X = Bar->Right;
+  coPos.Y = Bar->Top + 1;
+  FillConsoleOutputCharacter(0xBF, // '+',
+                            1,
+                            coPos,
+                            &Written);
+
+  /* draw left and right edge */
+  for (i = Bar->Top + 2; i < Bar->Bottom; i++)
+    {
+      coPos.X = Bar->Left;
+      coPos.Y = i;
+      FillConsoleOutputCharacter(0xB3, // '|',
+                                1,
+                                coPos,
+                                &Written);
+
+      coPos.X = Bar->Right;
+      FillConsoleOutputCharacter(0xB3, //'|',
+                                1,
+                                coPos,
+                                &Written);
+    }
+
+  /* draw lower left corner */
+  coPos.X = Bar->Left;
+  coPos.Y = Bar->Bottom;
+  FillConsoleOutputCharacter(0xC0, // '+',
+                            1,
+                            coPos,
+                            &Written);
+
+  /* draw lower edge */
+  coPos.X = Bar->Left + 1;
+  coPos.Y = Bar->Bottom;
+  FillConsoleOutputCharacter(0xC4, // '-',
+                            Bar->Right - Bar->Left - 1,
+                            coPos,
+                            &Written);
+
+  /* draw lower right corner */
+  coPos.X = Bar->Right;
+  coPos.Y = Bar->Bottom;
+  FillConsoleOutputCharacter(0xD9, // '+',
+                            1,
+                            coPos,
+                            &Written);
+}
+
+
+static VOID
+DrawProgressBar(PPROGRESS Bar)
+{
+  CHAR TextBuffer[8];
+  COORD coPos;
+  ULONG Written;
+  SHORT i;
+
+  /* Print percentage */
+  sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+
+  coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+  coPos.Y = Bar->Top;
+  WriteConsoleOutputCharacters(TextBuffer,
+                              4,
+                              coPos);
+
+  DrawBorder(Bar);
+
+  /* Draw the bar */
+  coPos.X = Bar->Left + 1;
+  for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+    {
+      FillConsoleOutputAttribute(0x1E, /* Yellow on blue */
+                                Bar->Width - 2,
+                                coPos,
+                                &Written);
+
+      FillConsoleOutputCharacter(' ',
+                                Bar->Width - 2,
+                                coPos,
+                                &Written);
+    }
+
+}
+
+
+
+PPROGRESS
+CreateProgressBar(SHORT Left,
+                 SHORT Top,
+                 SHORT Right,
+                 SHORT Bottom)
+{
+  PPROGRESS Bar;
+
+  Bar = (PPROGRESS)RtlAllocateHeap(ProcessHeap,
+                                  0,
+                                  sizeof(PROGRESS));
+  if (Bar == NULL)
+    return(NULL);
+
+  Bar->Left = Left;
+  Bar->Top = Top;
+  Bar->Right = Right;
+  Bar->Bottom = Bottom;
+
+  Bar->Width = Bar->Right - Bar->Left + 1;
+
+  Bar->Percent = 0;
+  Bar->Pos = 0;
+
+  Bar->StepCount = 0;
+  Bar->CurrentStep = 0;
+
+  DrawProgressBar(Bar);
+
+  return(Bar);
+}
+
+
+VOID
+DestroyProgressBar(PPROGRESS Bar)
+{
+  RtlFreeHeap(ProcessHeap,
+             0,
+             Bar);
+}
+
+VOID
+ProgressSetStepCount(PPROGRESS Bar,
+                    ULONG StepCount)
+{
+  Bar->CurrentStep = 0;
+  Bar->StepCount = StepCount;
+
+  DrawProgressBar(Bar);
+}
+
+
+VOID
+ProgressNextStep(PPROGRESS Bar)
+{
+  CHAR TextBuffer[8];
+  COORD coPos;
+  ULONG Written;
+  ULONG NewPercent;
+  ULONG NewPos;
+
+  if ((Bar->StepCount == 0) ||
+      (Bar->CurrentStep == Bar->StepCount))
+    return;
+
+  Bar->CurrentStep++;
+
+  /* Calculate new percentage */
+  NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+
+  /* Redraw precentage if changed */
+  if (Bar->Percent != NewPercent)
+    {
+      Bar->Percent = NewPercent;
+
+      sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+
+      coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+      coPos.Y = Bar->Top;
+      WriteConsoleOutputCharacters(TextBuffer,
+                                  4,
+                                  coPos);
+    }
+
+  /* Calculate bar position */
+  NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+
+  /* Redraw bar if changed */
+  if (Bar->Pos != NewPos)
+    {
+      Bar->Pos = NewPos;
+
+      for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+       {
+         coPos.X = Bar->Left + 1;
+         FillConsoleOutputCharacter(0xDB,
+                                    Bar->Pos / 2,
+                                    coPos,
+                                    &Written);
+         coPos.X += Bar->Pos/2;
+
+         if (Pos & 1)
+           {
+             FillConsoleOutputCharacter(0xDD,
+                                        1,
+                                        coPos,
+                                        &Written);
+             coPos.X++;
+           }
+
+         if (coPos.X <= Bar->Right - 1)
+           {
+             FillConsoleOutputCharacter(' ',
+                                        Bar->Right - coPos.X,
+                                        coPos,
+                                        &Written);
+           }
+       }
+    }
+}
+
+/* EOF */
diff --git a/subsys/system/usetup/progress.h b/subsys/system/usetup/progress.h
new file mode 100644 (file)
index 0000000..45d1ed2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2002 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS text-mode setup
+ * FILE:            subsys/system/usetup/partlist.h
+ * PURPOSE:         Partition list functions
+ * PROGRAMMER:      Eric Kohl
+ */
+
+#ifndef __PROGRESS_H__
+#define __PROGRESS_H__
+
+
+typedef struct _PROGRESS
+{
+  SHORT Left;
+  SHORT Top;
+  SHORT Right;
+  SHORT Bottom;
+
+  SHORT Width;
+
+  ULONG Percent;
+  ULONG Pos;
+
+  ULONG StepCount;
+  ULONG CurrentStep;
+} PROGRESS, *PPROGRESS;
+
+/* FUNCTIONS ****************************************************************/
+
+PPROGRESS
+CreateProgressBar(SHORT Left,
+                 SHORT Top,
+                 SHORT Right,
+                 SHORT Bottom);
+
+VOID
+DestroyProgressBar(PPROGRESS Bar);
+
+VOID
+ProgressSetStepCount(PPROGRESS Bar,
+                    ULONG StepCount);
+
+VOID
+ProgressNextStep(PPROGRESS Bar);
+
+#endif /* __PROGRESS_H__ */
+
+/* EOF */
\ No newline at end of file
diff --git a/subsys/win32k/ntuser/scrollbar.c b/subsys/win32k/ntuser/scrollbar.c
new file mode 100644 (file)
index 0000000..42d0874
--- /dev/null
@@ -0,0 +1,309 @@
+/* $Id$
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          Scrollbars
+ * FILE:             subsys/win32k/ntuser/scrollbar.c
+ * PROGRAMER:        Jason Filby (jasonfilby@yahoo.com)
+ * REVISION HISTORY:
+ *       16-11-2002  Jason Filby  Created
+ */
+/* INCLUDES ******************************************************************/
+
+#include <ddk/ntddk.h>
+#include <win32k/win32k.h>
+#include <include/object.h>
+#include <include/window.h>
+#include <include/class.h>
+#include <include/error.h>
+#include <include/winsta.h>
+#include <include/winpos.h>
+#include <include/rect.h>
+
+//#define NDEBUG
+#include <debug.h>
+
+#define SCROLL_MIN_RECT  4               /* Minimum size of the rectangle between the arrows */
+#define SCROLL_ARROW_THUMB_OVERLAP 0     /* Overlap between arrows and thumb */
+
+/* FUNCTIONS *****************************************************************/
+
+/* Ported from WINE20020904 */
+/* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
+ * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
+ * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
+ * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
+ */
+static BOOL
+SCROLL_GetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
+{
+  SCROLLBARINFO info;
+  INT pixels, thumbSize, arrowSize;
+  BOOL vertical;
+  RECT ClientRect = Window->ClientRect;
+  RECT WindowRect = Window->WindowRect;
+  ULONG Style;
+
+  switch (nBar)
+    {
+    case SB_HORZ:
+      lprect->left = ClientRect.left - WindowRect.left;
+      lprect->top = ClientRect.bottom - WindowRect.top;
+      lprect->right = ClientRect.right - WindowRect.left;
+      lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
+      if (Window->Style & WS_BORDER)
+       {
+         lprect->left--;
+         lprect->right++;
+       }
+      else if (Window->Style & WS_VSCROLL)
+       lprect->right++;
+      vertical = FALSE;
+      break;
+
+    case SB_VERT:
+      lprect->left = ClientRect.right - WindowRect.left;
+      lprect->top = ClientRect.top - WindowRect.top;
+      lprect->right = lprect->left + NtUserGetSystemMetrics (SM_CXVSCROLL);
+      lprect->bottom = ClientRect.bottom - WindowRect.top;
+      if (Window->Style & WS_BORDER)
+       {
+         lprect->top--;
+         lprect->bottom++;
+       }
+      else if (Window->Style & WS_HSCROLL)
+       lprect->bottom++;
+      vertical = TRUE;
+      break;
+
+    case SB_CTL:
+      W32kGetClientRect (Window, lprect);
+      vertical = ((Window->Style & SBS_VERT) != 0);
+      break;
+
+    default:
+      W32kReleaseWindowObject(Window);
+      return FALSE;
+    }
+
+  if (vertical)
+    pixels = lprect->bottom - lprect->top;
+  else
+    pixels = lprect->right - lprect->left;
+
+  info.cbSize = sizeof(SCROLLBARINFO);
+  SCROLL_GetScrollBarInfo (Window, nBar, &info);
+
+  if (pixels <= 2 * NtUserGetSystemMetrics (SM_CXVSCROLL) + SCROLL_MIN_RECT)
+    {
+      info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
+    }
+  else
+    {
+      arrowSize = NtUserGetSystemMetrics (SM_CXVSCROLL);
+      pixels -= (2 * (NtUserGetSystemMetrics (SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
+
+      /* Temporary initialization - to be removed once proper code is in */
+      info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
+
+/*        if (info->Page)
+        {
+           thumbSize = MulDiv(pixels,info->Page,(info->MaxVal-info->MinVal+1));
+            if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
+        }
+        else *thumbSize = NtUserGetSystemMetrics(SM_CXVSCROLL); */
+/*
+        if (((pixels -= *thumbSize ) < 0) ||
+            ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
+        { */
+      /* Rectangle too small or scrollbar disabled -> no thumb */
+/*            *thumbPos = *thumbSize = 0;
+        }
+        else
+        { */
+/*            INT max = info->MaxVal - max( info->Page-1, 0 );
+            if (info->MinVal >= max)
+                *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+            else
+                *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
+                 + MulDiv(pixels, (info->CurVal-info->MinVal),(max - info->MinVal));
+        } */
+  }
+
+  return vertical;
+}
+
+DWORD SCROLL_CreateScrollBar(PWINDOW_OBJECT Window, LONG idObject)
+{
+  PSCROLLBARINFO psbi;
+  LRESULT Result;
+  INT i;
+
+  Result = WinPosGetNonClientSize(Window->Self,
+                                 &Window->WindowRect,
+                                 &Window->ClientRect);
+
+  psbi = ExAllocatePool(NonPagedPool, sizeof(SCROLLBARINFO));
+
+  for (i=0; i<CCHILDREN_SCROLLBAR+1; i++)
+    psbi->rgstate[i] = 0;
+
+  switch(idObject)
+  {
+    case SB_HORZ:
+      Window->pHScroll = psbi;
+      break;
+    case SB_VERT:
+      Window->pVScroll = psbi;
+      break;
+    case SB_CTL:
+      Window->wExtra = psbi;
+      break;
+    default:
+      return FALSE;
+  }
+
+  SCROLL_GetScrollBarRect (Window, idObject, &(psbi->rcScrollBar));
+
+  return 0;
+}
+
+DWORD SCROLL_GetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
+{
+  switch(idObject)
+  {
+    case SB_HORZ:
+      memcpy(psbi, Window->pHScroll, psbi->cbSize);
+      break;
+    case SB_VERT:
+      memcpy(psbi, Window->pVScroll, psbi->cbSize);
+      break;
+    case SB_CTL:
+      memcpy(psbi, Window->wExtra, psbi->cbSize);
+      break;
+    default:
+      W32kReleaseWindowObject(Window);
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+DWORD
+STDCALL
+NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
+{
+  PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
+
+  if (!Window) return FALSE;
+
+  SCROLL_GetScrollBarInfo(Window, idObject, psbi);
+
+  W32kReleaseWindowObject(Window);
+
+  return TRUE;
+}
+
+DWORD
+STDCALL
+NtUserEnableScrollBar(
+  DWORD Unknown0,
+  DWORD Unknown1,
+  DWORD Unknown2)
+{
+  return 0;
+}
+
+DWORD
+STDCALL
+NtUserScrollDC(
+  DWORD Unknown0,
+  DWORD Unknown1,
+  DWORD Unknown2,
+  DWORD Unknown3,
+  DWORD Unknown4,
+  DWORD Unknown5,
+  DWORD Unknown6)
+
+{
+  UNIMPLEMENTED
+
+  return 0;
+}
+
+DWORD
+STDCALL
+NtUserSetScrollInfo(
+  DWORD Unknown0,
+  DWORD Unknown1,
+  DWORD Unknown2,
+  DWORD Unknown3)
+{
+  UNIMPLEMENTED
+
+  return 0;
+}
+
+/* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
+DWORD
+STDCALL
+NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
+{
+  BOOL fShowV = (wBar == SB_VERT) ? 0 : bShow;
+  BOOL fShowH = (wBar == SB_HORZ) ? 0 : bShow;
+  PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
+
+  switch (wBar)
+    {
+    case SB_CTL:
+      NtUserShowWindow (hWnd, fShowH ? SW_SHOW : SW_HIDE);
+      return TRUE;
+
+    case SB_BOTH:
+    case SB_HORZ:
+      if (fShowH)
+       {
+         fShowH = !(Window->Style & WS_HSCROLL);
+         Window->Style |= WS_HSCROLL;
+       }
+      else                     /* hide it */
+       {
+         fShowH = (Window->Style & WS_HSCROLL);
+         Window->Style &= ~WS_HSCROLL;
+       }
+      if (wBar == SB_HORZ)
+       {
+         fShowV = FALSE;
+         break;
+       }
+      /* fall through */
+
+    case SB_VERT:
+      if (fShowV)
+       {
+         fShowV = !(Window->Style & WS_VSCROLL);
+         Window->Style |= WS_VSCROLL;
+       }
+      else                     /* hide it */
+       {
+         fShowV = (Window->Style & WS_VSCROLL);
+         Window->Style &= ~WS_VSCROLL;
+       }
+      if (wBar == SB_VERT)
+       fShowH = FALSE;
+      break;
+
+    default:
+      return FALSE;            /* Nothing to do! */
+    }
+
+  if (fShowH || fShowV)                /* frame has been changed, let the window redraw itself */
+  {
+    NtUserSetWindowPos (hWnd, 0, 0, 0, 0, 0,
+                        SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
+    return TRUE;
+  }
+  return FALSE;                        /* no frame changes */
+}
+
+/* EOF */
diff --git a/tools/rtouch.c b/tools/rtouch.c
new file mode 100755 (executable)
index 0000000..ce1773c
--- /dev/null
@@ -0,0 +1,81 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <sys/utime.h>
+#else
+#include <sys/time.h>
+#include <stdlib.h>
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+
+char* convert_path(char* origpath)
+{
+  char* newpath;
+  int i;
+   
+  newpath = (char *)strdup(origpath);
+   
+  i = 0;
+  while (newpath[i] != 0)
+    {
+#ifdef UNIX_PATHS
+      if (newpath[i] == '\\')
+        {
+          newpath[i] = '/';
+        }
+#else
+#ifdef DOS_PATHS
+      if (newpath[i] == '/')
+        {
+          newpath[i] = '\\';
+        }
+#endif 
+#endif 
+      i++;
+    }
+  return(newpath);
+}
+
+int main(int argc, char* argv[])
+{
+  char* path;
+  FILE* file;
+#ifdef WIN32
+  time_t now;
+  struct utimbuf fnow;
+#endif
+
+  if (argc != 2)
+    {
+      fprintf(stderr, "Wrong number of arguments.\n");
+      exit(1);
+    }
+
+  path = convert_path(argv[1]);
+  file = (FILE *)open(path, S_IWRITE);
+  if (file == (void*)-1)
+    {
+      file = (FILE *)open(path, S_IWRITE | O_CREAT);
+      if (file == (void*)-1)
+        {
+          fprintf(stderr, "Cannot create file.\n");
+          exit(1);
+        }
+    }
+
+  fclose(file);
+
+#ifdef WIN32
+  now = time();
+  fnow.actime = now;
+  fnow.modtime = now;
+  (int) utime(path, &fnow);
+#else
+  (int) utimes(path, NULL);
+#endif
+
+  exit(0);
+}
diff --git a/txtsetup.sif b/txtsetup.sif
new file mode 100644 (file)
index 0000000..a4eb3f2
--- /dev/null
@@ -0,0 +1,98 @@
+[Version]
+Signature = "$ReactOS$"
+
+[Directories]
+1 = "\"
+2 = system32
+3 = system32\drivers
+4 = system32\config
+5 = media
+6 = media\fonts
+7 = bin
+
+[SourceFiles]
+ntoskrnl.exe = 2
+hal.dll      = 2
+
+acpi.sys     = 3
+isapnp.sys   = 3
+
+beep.sys     = 3
+blue.sys     = 3
+floppy.sys   = 3
+null.sys     = 3
+serial.sys   = 3
+vgaddi.dll   = 3
+vgamp.sys    = 3
+vidport.sys  = 3
+
+cdfs.sys     = 3
+fs_rec.sys   = 3
+msfs.sys     = 3
+mup.sys      = 3
+npfs.sys     = 3
+ntfs.sys     = 3
+vfatfs.sys   = 3
+
+keyboard.sys = 3
+mouclass.sys = 3
+psaux.sys    = 3
+
+unbzip2.sys  = 3
+
+afd.sys      = 3
+ne2000.sys   = 3
+ndis.sys     = 3
+npf.sys      = 3
+;packet.sys   = 3
+tcpip.sys    = 3
+tdi.sys      = 3
+
+atapi.sys    = 3
+cdrom.sys    = 3
+class2.sys   = 3
+disk.sys     = 3
+scsiport.sys = 3
+
+advapi32.dll = 2
+crtdll.dll   = 2
+fmifs.dll    = 2
+gdi32.dll    = 2
+kernel32.dll = 2
+msafd.dll    = 2
+msvcrt.dll   = 2
+ntdll.dll    = 2
+;ole32.dll    = 2
+;oleaut32.dll = 2
+packet.dll   = 2
+secur32.dll  = 2
+;shell32.dll  = 2
+user32.dll   = 2
+version.dll  = 2
+winedbgc.dll = 2
+winmm.dll    = 2
+ws2_32.dll   = 2
+ws2help.dll  = 2
+wshirda.dll  = 2
+
+eventlog.exe = 2
+rpcss.exe    = 2
+csrss.exe    = 2
+ntvdm.exe    = 2
+smss.exe     = 2
+autochk.exe  = 2
+gstart.exe   = 2
+;lsass.exe    = 2
+services.exe = 2
+shell.exe    = 2
+winlogon.exe = 2
+
+win32k.sys   = 3
+
+helb____.ttf = 6
+timr____.ttf = 6
+
+system.hiv   = 4
+
+[SetupData]
+DefaultPath = \reactos