Sync with trunk r63270.
authorDavid Quintana <gigaherz@gmail.com>
Tue, 13 May 2014 12:11:12 +0000 (12:11 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Tue, 13 May 2014 12:11:12 +0000 (12:11 +0000)
svn path=/branches/shell-experiments/; revision=63271

452 files changed:
base/applications/dxdiag/lang/tr-TR.rc
base/applications/games/solitaire/lang/tr-TR.rc
base/applications/msconfig/lang/tr-TR.rc
base/applications/mscutils/devmgmt/lang/cs-CZ.rc
base/applications/mscutils/eventvwr/eventvwr.rc
base/applications/mscutils/eventvwr/lang/cs-CZ.rc [new file with mode: 0644]
base/applications/mscutils/servman/lang/cs-CZ.rc [new file with mode: 0644]
base/applications/mscutils/servman/lang/tr-TR.rc
base/applications/mscutils/servman/servman.rc
base/applications/rapps/lang/cs-CZ.rc
base/applications/rapps/lang/tr-TR.rc
base/applications/rapps/rapps/abiword.txt
base/applications/rapps/rapps/abiword26.txt
base/applications/rapps/rapps/abyss.txt
base/applications/rapps/rapps/ac97forvirtualbox.txt
base/applications/rapps/rapps/alreader.txt
base/applications/rapps/rapps/ants.txt
base/applications/rapps/rapps/audiograbber.txt
base/applications/rapps/rapps/bittorrent.txt
base/applications/rapps/rapps/bochs.txt
base/applications/rapps/rapps/boswars.txt
base/applications/rapps/rapps/boundaround.txt
base/applications/rapps/rapps/christmasbound.txt
base/applications/rapps/rapps/chromium.txt
base/applications/rapps/rapps/cnt.txt
base/applications/rapps/rapps/codeblocks.txt
base/applications/rapps/rapps/codeblocks_gcc.txt
base/applications/rapps/rapps/codeblocks_gcc_2.txt
base/applications/rapps/rapps/comctl32ocx.txt
base/applications/rapps/rapps/devcpp_mingw32.txt
base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt
base/applications/rapps/rapps/diablo2.txt
base/applications/rapps/rapps/dosblaster.txt
base/applications/rapps/rapps/dosbox.txt
base/applications/rapps/rapps/doublecommander.txt
base/applications/rapps/rapps/dplus.txt [new file with mode: 0644]
base/applications/rapps/rapps/dvdwritenow.txt
base/applications/rapps/rapps/excelview.txt
base/applications/rapps/rapps/fap.txt
base/applications/rapps/rapps/fira.txt
base/applications/rapps/rapps/firefox.txt
base/applications/rapps/rapps/firefox2.txt
base/applications/rapps/rapps/firefox3.txt
base/applications/rapps/rapps/firefox36.txt
base/applications/rapps/rapps/freebasic.txt
base/applications/rapps/rapps/glidewrapzbag.txt
base/applications/rapps/rapps/globulation2.txt
base/applications/rapps/rapps/hover.txt
base/applications/rapps/rapps/hxd.txt
base/applications/rapps/rapps/indiftpd.txt
base/applications/rapps/rapps/irfanview.txt
base/applications/rapps/rapps/irfanviewplugins.txt
base/applications/rapps/rapps/kdewin.txt
base/applications/rapps/rapps/kyodai.txt
base/applications/rapps/rapps/lazaruside.txt
base/applications/rapps/rapps/lbreakout2.txt
base/applications/rapps/rapps/lgeneral.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/lmarbles.txt
base/applications/rapps/rapps/mcwin32.txt [new file with mode: 0644]
base/applications/rapps/rapps/mfc40.txt
base/applications/rapps/rapps/mirandaim.txt
base/applications/rapps/rapps/mirc.txt
base/applications/rapps/rapps/mirc6.txt
base/applications/rapps/rapps/mono2.txt
base/applications/rapps/rapps/mpc.txt
base/applications/rapps/rapps/mpxplay.txt
base/applications/rapps/rapps/msxml3.txt
base/applications/rapps/rapps/net11.txt
base/applications/rapps/rapps/net20.txt
base/applications/rapps/rapps/net20sp2.txt
base/applications/rapps/rapps/npp.txt
base/applications/rapps/rapps/offbyone.txt
base/applications/rapps/rapps/opencodecs.txt
base/applications/rapps/rapps/openoffice.txt
base/applications/rapps/rapps/openoffice2.4.txt
base/applications/rapps/rapps/openttd.txt
base/applications/rapps/rapps/opera.txt
base/applications/rapps/rapps/opera9.txt
base/applications/rapps/rapps/peazip.txt
base/applications/rapps/rapps/pengupop.txt
base/applications/rapps/rapps/photofiltre.txt
base/applications/rapps/rapps/pingus.txt
base/applications/rapps/rapps/pptview.txt
base/applications/rapps/rapps/pspad.txt
base/applications/rapps/rapps/ptanks.txt
base/applications/rapps/rapps/putty.txt
base/applications/rapps/rapps/python.txt
base/applications/rapps/rapps/python2.txt
base/applications/rapps/rapps/qb64sdl.txt
base/applications/rapps/rapps/qmmp.txt
base/applications/rapps/rapps/remood.txt
base/applications/rapps/rapps/reshack.txt
base/applications/rapps/rapps/rocks.txt
base/applications/rapps/rapps/rosbe.txt
base/applications/rapps/rapps/rosbeamd64.txt
base/applications/rapps/rapps/rosbearm.txt
base/applications/rapps/rapps/sambatng.txt
base/applications/rapps/rapps/sbforvmware.txt
base/applications/rapps/rapps/scite.txt
base/applications/rapps/rapps/scummvm.txt
base/applications/rapps/rapps/sdl_mixer.txt
base/applications/rapps/rapps/sdl_runtime.txt
base/applications/rapps/rapps/seamonkey.txt
base/applications/rapps/rapps/smplayer.txt
base/applications/rapps/rapps/snoopy.txt
base/applications/rapps/rapps/stamina.txt
base/applications/rapps/rapps/steam.txt
base/applications/rapps/rapps/sumatrapdf.txt
base/applications/rapps/rapps/summerbound.txt
base/applications/rapps/rapps/superdxb.txt
base/applications/rapps/rapps/superfinder.txt
base/applications/rapps/rapps/supertux.txt
base/applications/rapps/rapps/tahoma.txt
base/applications/rapps/rapps/thunderbird.txt
base/applications/rapps/rapps/thunderbird3.txt
base/applications/rapps/rapps/tileworld.txt
base/applications/rapps/rapps/totalcommander.txt
base/applications/rapps/rapps/tuxpaint.txt
base/applications/rapps/rapps/ultravnc.txt
base/applications/rapps/rapps/utorrent.txt
base/applications/rapps/rapps/vb5run.txt
base/applications/rapps/rapps/vb6run.txt
base/applications/rapps/rapps/vc2005sp1run.txt
base/applications/rapps/rapps/vc2008sp1run.txt
base/applications/rapps/rapps/vc2010run.txt
base/applications/rapps/rapps/vc6run.txt
base/applications/rapps/rapps/vlc.txt
base/applications/rapps/rapps/winboard.txt
base/applications/rapps/rapps/wme9.txt
base/applications/rapps/rapps/wordview.txt
base/applications/rapps/rapps/zaz.txt
base/applications/regedit/lang/tr-TR.rc
base/applications/sndvol32/lang/tr-TR.rc
base/applications/taskmgr/lang/tr-TR.rc
base/setup/reactos/lang/tr-TR.rc
base/setup/reactos/reactos.rc
base/setup/usetup/bootsup.c
base/setup/usetup/bootsup.h
base/setup/usetup/chkdsk.c
base/setup/usetup/drivesup.c
base/setup/usetup/drivesup.h
base/setup/usetup/filequeue.c
base/setup/usetup/filequeue.h
base/setup/usetup/filesup.c
base/setup/usetup/filesup.h
base/setup/usetup/format.c
base/setup/usetup/fslist.c
base/setup/usetup/fslist.h
base/setup/usetup/genlist.c
base/setup/usetup/genlist.h
base/setup/usetup/host.h
base/setup/usetup/inffile.c
base/setup/usetup/inffile.h
base/setup/usetup/inicache.c
base/setup/usetup/inicache.h
base/setup/usetup/mui.c
base/setup/usetup/mui.h
base/setup/usetup/muilanguages.h
base/setup/usetup/progress.c
base/setup/usetup/progress.h
base/setup/usetup/registry.c
base/setup/usetup/registry.h
base/setup/usetup/settings.c
base/setup/usetup/settings.h
base/setup/usetup/usetup.h
base/setup/vmwinst/lang/tr-TR.rc
base/setup/vmwinst/vmwinst.rc
base/setup/welcome/lang/tr-TR.rc
base/setup/welcome/welcome.rc
base/shell/cmd/copy.c
base/shell/cmd/replace.c
base/shell/explorer-new/lang/tr-TR.rc
base/shell/explorer/explorer-cz.rc
base/shell/explorer/explorer.rc
base/system/rundll32/lang/tr-TR.rc
base/system/rundll32/rundll32.rc
base/system/runonce/lang/tr-TR.rc
base/system/runonce/runonce.rc
base/system/userinit/lang/tr-TR.rc
base/system/userinit/userinit.rc
base/system/winlogon/lang/tr-TR.rc
base/system/winlogon/winlogon.rc
cmake/msvc.cmake
dll/cpl/access/access.rc
dll/cpl/access/lang/cs-CZ.rc
dll/cpl/hdwwiz/hdwwiz.rc
dll/cpl/hdwwiz/lang/cs-CZ.rc
dll/cpl/inetcpl/inetcpl.rc
dll/cpl/inetcpl/lang/cs-CZ.rc [new file with mode: 0644]
dll/cpl/joy/joy.rc
dll/cpl/joy/lang/cs-CZ.rc
dll/cpl/mmsys/lang/cs-CZ.rc
dll/cpl/mmsys/mmsys.rc
dll/cpl/powercfg/lang/cs-CZ.rc
dll/cpl/powercfg/powercfg.rc
dll/cpl/timedate/lang/cs-CZ.rc
dll/cpl/timedate/timedate.rc
dll/cpl/usrmgr/lang/cs-CZ.rc [new file with mode: 0644]
dll/cpl/usrmgr/usrmgr.rc
dll/directx/wine/msdmo/dmoreg.c
dll/directx/wine/quartz/avisplit.c
dll/ntdll/CMakeLists.txt
dll/ntdll/csr/capture.c
dll/ntdll/def/ntdll.spec
dll/ntdll/rtl/libsupp.c
dll/win32/atl/CMakeLists.txt
dll/win32/comctl32/treeview.c
dll/win32/icmp/icmp_main.c
dll/win32/ieframe/shelluihelper.c
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/client/time.c
dll/win32/kernel32/client/vdm.c
dll/win32/kernel32/include/vdm.h
dll/win32/kernel32/k32.h
dll/win32/kernel32/wine/actctx.c
dll/win32/mshtml/CMakeLists.txt
dll/win32/mshtml/msvc.S
dll/win32/msvcrt/msvcrt.spec
dll/win32/rpcrt4/rpc_transport.c
dll/win32/rpcrt4/rpcrt4_ros.diff
dll/win32/setupapi/CMakeLists.txt
dll/win32/setupapi/install.c
dll/win32/setupapi/misc.c
dll/win32/setupapi/setupapi.spec
dll/win32/setupapi/setupapi_private.h
dll/win32/shell32/folders/cpanel.cpp
dll/win32/shell32/lang/cs-CZ.rc
dll/win32/shell32/shlexec.cpp
dll/win32/shlwapi/path.c
dll/win32/syssetup/lang/cs-CZ.rc
drivers/base/kdcom/kdserial.c
drivers/bus/acpi/compbatt/compmisc.c
drivers/crypto/ksecdd/random.c
drivers/filters/mountmgr/device.c
drivers/ksfilter/ks/api.c
drivers/ksfilter/ks/event.c
drivers/ksfilter/ks/ksfunc.h
drivers/ksfilter/ks/methods.c
drivers/ksfilter/ks/misc.c
drivers/ksfilter/ks/pin.c
drivers/ksfilter/ks/property.c
drivers/ksfilter/ks/swenum.c
drivers/ksfilter/ks/topology.c
drivers/network/afd/afd/bind.c
drivers/network/afd/afd/select.c
drivers/network/afd/afd/tdi.c
drivers/network/tcpip/tcpip/dispatch.c
drivers/storage/floppy/floppy.c
drivers/wdm/audio/legacy/wdmaud/control.c
drivers/wdm/audio/legacy/wdmaud/deviface.c
drivers/wdm/audio/legacy/wdmaud/mmixer.c
drivers/wdm/audio/legacy/wdmaud/sup.c
drivers/wdm/audio/sysaudio/deviface.c
drivers/wdm/audio/sysaudio/pin.c
drivers/wmi/CMakeLists.txt
include/ddk/isvbop.h [new file with mode: 0644]
include/ddk/isvbop.inc [new file with mode: 0644]
include/ddk/nt_vdd.h [new file with mode: 0644]
include/ddk/ntddk.h
include/ddk/ntifs.h
include/ddk/vddsvc.h [new file with mode: 0644]
include/ddk/wdm.h
include/ndk/rtlfuncs.h
include/psdk/ks.h
include/reactos/libs/fast486/fast486.h [new file with mode: 0644]
include/reactos/libs/pseh/pseh3.h
include/reactos/subsys/win/vdm.h [new file with mode: 0644]
include/reactos/wine/port.h
include/xdk/ccfuncs.h
include/xdk/extypes.h
include/xdk/fsrtlfuncs.h
include/xdk/haltypes.h
include/xdk/ia64/ke.h
include/xdk/iotypes.h
include/xdk/kdfuncs.h
include/xdk/ketypes.h
include/xdk/mmtypes.h
include/xdk/ntifs.template.h
include/xdk/obtypes.h
include/xdk/rtltypes.h
include/xdk/sefuncs.h
include/xdk/wdm.template.h
lib/CMakeLists.txt
lib/fast486/CMakeLists.txt [new file with mode: 0644]
lib/fast486/COPYING [new file with mode: 0644]
lib/fast486/common.c [new file with mode: 0644]
lib/fast486/common.h [new file with mode: 0644]
lib/fast486/common.inl [new file with mode: 0644]
lib/fast486/extraops.c [new file with mode: 0644]
lib/fast486/extraops.h [new file with mode: 0644]
lib/fast486/fast486.c [new file with mode: 0644]
lib/fast486/fpu.c [new file with mode: 0644]
lib/fast486/fpu.h [new file with mode: 0644]
lib/fast486/opcodes.c [new file with mode: 0644]
lib/fast486/opcodes.h [new file with mode: 0644]
lib/fast486/opgroups.c [new file with mode: 0644]
lib/fast486/opgroups.h [new file with mode: 0644]
lib/rtl/actctx.c
lib/rtl/nls.c
lib/rtl/rtlp.h
lib/sdk/cpprt/amd64/cpprt.s
lib/sdk/crt/include/internal/safecrt.h
lib/sdk/crt/printf/_sxprintf.c
lib/sdk/crt/stdio/file.c
lib/sdk/crt/stdio/stat64.c
lib/sdk/crt/stdlib/errno.c
lib/sdk/crt/stdlib/senv.c
lib/sdk/crt/string/_tsplitpath_x.h
lib/sdk/crt/string/itoa.c
lib/sdk/crt/string/itow.c
lib/sdk/crt/string/strerror.c
lib/sdk/crt/string/wcs.c
lib/sdk/crt/time/gmtime.c
lib/sdk/crt/wine/heap.c
media/doc/README.WINE
media/inf/audio.inf
media/inf/battery.inf
media/inf/bth.inf
media/inf/cdrom.inf
media/inf/disk.inf
media/inf/display.inf
media/inf/flpydisk.inf
media/inf/hal.inf
media/inf/hdc.inf
media/inf/input.inf
media/inf/keyboard.inf
media/inf/legcydrv.inf
media/inf/machine.inf
media/inf/monitor.inf
media/inf/shortcuts.inf
media/inf/unknown.inf
media/inf/usb.inf
ntoskrnl/ex/event.c
ntoskrnl/ex/sem.c
ntoskrnl/ex/sysinfo.c
ntoskrnl/fsrtl/fsrtlpc.c
ntoskrnl/include/internal/amd64/mm.h
ntoskrnl/include/internal/fsrtl.h
ntoskrnl/include/internal/kd.h
ntoskrnl/include/internal/kd64.h
ntoskrnl/include/ntoskrnl.h
ntoskrnl/kd64/kdapi.c
ntoskrnl/kd64/kddata.c
ntoskrnl/kd64/kdinit.c
ntoskrnl/ke/time.c
ntoskrnl/mm/section.c
ntoskrnl/ntoskrnl.spec
ntoskrnl/ps/quota.c
subsystems/CMakeLists.txt
subsystems/ntvdm/CMakeLists.txt
subsystems/ntvdm/bios/bios.c [new file with mode: 0644]
subsystems/ntvdm/bios/bios.h [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/bios32.c [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/bios32.h [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/bios32p.h [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/kbdbios32.c [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/kbdbios32.h [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/vidbios32.c [new file with mode: 0644]
subsystems/ntvdm/bios/bios32/vidbios32.h [new file with mode: 0644]
subsystems/ntvdm/bios/kbdbios.c [new file with mode: 0644]
subsystems/ntvdm/bios/kbdbios.h [new file with mode: 0644]
subsystems/ntvdm/bios/rom.c [new file with mode: 0644]
subsystems/ntvdm/bios/rom.h [new file with mode: 0644]
subsystems/ntvdm/bios/vidbios.c [new file with mode: 0644]
subsystems/ntvdm/bios/vidbios.h [new file with mode: 0644]
subsystems/ntvdm/bop.c [new file with mode: 0644]
subsystems/ntvdm/bop.h [new file with mode: 0644]
subsystems/ntvdm/callback.c [new file with mode: 0644]
subsystems/ntvdm/callback.h [new file with mode: 0644]
subsystems/ntvdm/clock.c [new file with mode: 0644]
subsystems/ntvdm/clock.h [new file with mode: 0644]
subsystems/ntvdm/dos/dem.c [new file with mode: 0644]
subsystems/ntvdm/dos/dem.h [new file with mode: 0644]
subsystems/ntvdm/dos/dos32krnl/bios.c [new file with mode: 0644]
subsystems/ntvdm/dos/dos32krnl/dos.c [new file with mode: 0644]
subsystems/ntvdm/dos/dos32krnl/dos.h [new file with mode: 0644]
subsystems/ntvdm/dos/dos32krnl/dosfiles.c [new file with mode: 0644]
subsystems/ntvdm/emulator.c [new file with mode: 0644]
subsystems/ntvdm/emulator.h [new file with mode: 0644]
subsystems/ntvdm/hardware/cmos.c [new file with mode: 0644]
subsystems/ntvdm/hardware/cmos.h [new file with mode: 0644]
subsystems/ntvdm/hardware/pic.c [new file with mode: 0644]
subsystems/ntvdm/hardware/pic.h [new file with mode: 0644]
subsystems/ntvdm/hardware/ps2.c [new file with mode: 0644]
subsystems/ntvdm/hardware/ps2.h [new file with mode: 0644]
subsystems/ntvdm/hardware/speaker.c [new file with mode: 0644]
subsystems/ntvdm/hardware/speaker.h [new file with mode: 0644]
subsystems/ntvdm/hardware/timer.c [new file with mode: 0644]
subsystems/ntvdm/hardware/timer.h [new file with mode: 0644]
subsystems/ntvdm/hardware/vga.c [new file with mode: 0644]
subsystems/ntvdm/hardware/vga.h [new file with mode: 0644]
subsystems/ntvdm/int32.c [new file with mode: 0644]
subsystems/ntvdm/int32.h [new file with mode: 0644]
subsystems/ntvdm/io.c [new file with mode: 0644]
subsystems/ntvdm/io.h [new file with mode: 0644]
subsystems/ntvdm/lang/bg-BG.rc [deleted file]
subsystems/ntvdm/lang/cs-CZ.rc
subsystems/ntvdm/lang/de-DE.rc
subsystems/ntvdm/lang/en-US.rc
subsystems/ntvdm/lang/es-ES.rc
subsystems/ntvdm/lang/fr-FR.rc
subsystems/ntvdm/lang/hu-HU.rc [deleted file]
subsystems/ntvdm/lang/id-ID.rc [deleted file]
subsystems/ntvdm/lang/it-IT.rc
subsystems/ntvdm/lang/ja-JP.rc [deleted file]
subsystems/ntvdm/lang/no-NO.rc [deleted file]
subsystems/ntvdm/lang/pl-PL.rc
subsystems/ntvdm/lang/pt-BR.rc [deleted file]
subsystems/ntvdm/lang/ro-RO.rc [deleted file]
subsystems/ntvdm/lang/ru-RU.rc [deleted file]
subsystems/ntvdm/lang/sk-SK.rc [deleted file]
subsystems/ntvdm/lang/th-TH.rc [deleted file]
subsystems/ntvdm/lang/uk-UA.rc [deleted file]
subsystems/ntvdm/lang/zh-CN.rc [deleted file]
subsystems/ntvdm/lang/zh-TW.rc [deleted file]
subsystems/ntvdm/ntvdm.c
subsystems/ntvdm/ntvdm.h [new file with mode: 0644]
subsystems/ntvdm/ntvdm.rc
subsystems/ntvdm/ntvdm.spec [new file with mode: 0644]
subsystems/ntvdm/registers.c [new file with mode: 0644]
subsystems/ntvdm/registers.h [new file with mode: 0644]
subsystems/ntvdm/res/ntvdm.ico [new file with mode: 0644]
subsystems/ntvdm/resource.h
subsystems/ntvdm/utils.c [new file with mode: 0644]
subsystems/ntvdm/utils.h [new file with mode: 0644]
subsystems/ntvdm/vddsup.c [new file with mode: 0644]
subsystems/ntvdm/vddsup.h [new file with mode: 0644]
subsystems/win/basesrv/basesrv.h
subsystems/win/basesrv/init.c
subsystems/win/basesrv/proc.c
subsystems/win/basesrv/vdm.c
subsystems/win/basesrv/vdm.h [new file with mode: 0644]
subsystems/win32/csrsrv/procsup.c
win32ss/drivers/videoprt/child.c
win32ss/gdi/eng/engevent.c
win32ss/gdi/eng/mem.c
win32ss/include/ntuser.h
win32ss/user/ntuser/accelerator.c
win32ss/user/ntuser/main.c
win32ss/user/ntuser/menu.c
win32ss/user/ntuser/menu.h
win32ss/user/ntuser/message.c
win32ss/user/ntuser/misc.c
win32ss/user/ntuser/misc/rtlstr.c
win32ss/user/ntuser/userfuncs.h
win32ss/user/ntuser/window.c
win32ss/user/ntuser/winpos.c
win32ss/user/user32/windows/accel.c
win32ss/user/user32/windows/mdi.c
win32ss/user/user32/windows/menu.c
win32ss/w32ksvc.h

index 39a43a1..9734d84 100644 (file)
@@ -118,7 +118,7 @@ BEGIN
     RTEXT "Sürüm:", -1, 275, 35, 55, 10
     RTEXT "Zaman:", -1, 275, 45, 55, 10
     RTEXT "WHQL İmleği:", -1, 275, 55, 55, 10
-    RTEXT "Diğer Kütükler:", -1, 275, 65, 55, 10
+    RTEXT "Başka Kütükler:", -1, 275, 65, 55, 10
     RTEXT "Sağlayıcı:", -1, 275, 75, 55, 10
     LTEXT "", IDC_STATIC_DSOUND_DRIVER, 335, 25, 100, 10
     LTEXT "", IDC_STATIC_DSOUND_VERSION, 335, 35, 100, 10
index d3c6a86..8ddadb8 100644 (file)
@@ -3,7 +3,7 @@
  * LICENSE:    Freeware, permission to use under Public Domain
  * FILE:       base/applications/games/solitaire/lang/tr-TR.rc
  * PURPOSE:    Turkish Resource File for ReactOS Solitaire
- * TRANSLATOR: 2013 Erdem Ersoy (eersoy93) (erdemersoy@live.com)
+ * TRANSLATOR: 2013, 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com)
  */
 
 LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
@@ -18,13 +18,13 @@ BEGIN
     GROUPBOX "Kâğıtlar", -1, 7, 7, 90, 40
     AUTORADIOBUTTON "&Tekli Çek", IDC_OPT_DRAWONE, 14, 19, 70, 10, WS_GROUP | WS_TABSTOP
     AUTORADIOBUTTON "&Üçlü Çek", IDC_OPT_DRAWTHREE, 14, 32, 70, 10
-    GROUPBOX "Scoring", -1, 100, 7, 75, 53
-    AUTORADIOBUTTON "&Standard", IDC_OPT_STANDARD, 107, 19, 60, 10, WS_GROUP | WS_TABSTOP
+    GROUPBOX "Sayılama", -1, 100, 7, 75, 53
+    AUTORADIOBUTTON "&Ölçünlü", IDC_OPT_STANDARD, 107, 19, 60, 10, WS_GROUP | WS_TABSTOP
     AUTORADIOBUTTON "&Vegas", IDC_OPT_VEGAS, 107, 32, 60, 10
-    AUTORADIOBUTTON "&None", IDC_OPT_NOSCORE, 107, 45, 60, 10
+    AUTORADIOBUTTON "&Yok", IDC_OPT_NOSCORE, 107, 45, 60, 10
     AUTOCHECKBOX "&Süreyi Göster", IDC_OPT_SHOWTIME, 7 ,51 ,65 ,10, WS_TABSTOP
     AUTOCHECKBOX "&Durum Çubuğu", IDC_OPT_STATUSBAR, 7, 66, 64, 10, WS_TABSTOP
-    AUTOCHECKBOX "&Keep Score", IDC_OPT_KEEPSCORE, 100, 66, 65, 10, WS_TABSTOP
+    AUTOCHECKBOX "S&ayıyı Koru", IDC_OPT_KEEPSCORE, 100, 66, 65, 10, WS_TABSTOP
     DEFPUSHBUTTON "Tamam", IDOK, 35, 97, 50, 14
     PUSHBUTTON "İptal", IDCANCEL, 101, 97, 50, 14
 END
@@ -59,8 +59,8 @@ BEGIN
     IDS_SOL_QUIT "Bu oyundan çıkılsın mı?"
     IDS_SOL_WIN "Tebrikler, kazandınız!"
     IDS_SOL_DEAL "Yine dağıtılsın mı?"
-    IDS_SOL_SCORE "Score: %d"
-    IDS_SOL_TIME "Time: %d"
+    IDS_SOL_SCORE "Sayı: %d"
+    IDS_SOL_TIME "Süre: %d"
 END
 
 /* Menus */
index a96b9fb..141d7fc 100644 (file)
@@ -1,4 +1,4 @@
-/* TRANSLATOR: 2013 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */
+/* TRANSLATOR: 2013, 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */
 
 LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
 
index 10464f6..f56d941 100644 (file)
@@ -1,4 +1,4 @@
-LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 IDR_MAINMENU MENU
 BEGIN
@@ -21,7 +21,7 @@ BEGIN
         MENUITEM "Prostředky podle typu", IDC_RESBYTYPE, GRAYED
         MENUITEM "Prostředky podle připojení", IDC_RESBYCONN, GRAYED
         MENUITEM SEPARATOR
-        MENUITEM "Show hidden devices", IDC_SHOWHIDDEN
+        MENUITEM "Zobrazit skrytá zařízení", IDC_SHOWHIDDEN
     END
     POPUP "Nápověda"
     BEGIN
index 2905817..d2c9a69 100644 (file)
@@ -24,6 +24,9 @@ IDI_ERRORICON ICON "res/error.ico"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
diff --git a/base/applications/mscutils/eventvwr/lang/cs-CZ.rc b/base/applications/mscutils/eventvwr/lang/cs-CZ.rc
new file mode 100644 (file)
index 0000000..873bb14
--- /dev/null
@@ -0,0 +1,117 @@
+LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+
+IDC_EVENTVWR MENU
+BEGIN
+    POPUP "&Protokol"
+    BEGIN
+        MENUITEM "&Aplikace", ID_LOG_APPLICATION
+        MENUITEM "&Zabezpečení", ID_LOG_SECURITY
+        MENUITEM "&Systém", ID_LOG_SYSTEM
+        MENUITEM SEPARATOR
+        MENUITEM "&Konec", IDM_EXIT
+    END
+    POPUP "&Zobrazit"
+    BEGIN
+        MENUITEM "&Obnovit", IDM_REFRESH
+    END
+    MENUITEM "&Možnosti", ID_OPTIONS
+    POPUP "&Nápověda"
+    BEGIN
+        MENUITEM "Ná&pověda", IDM_HELP
+        MENUITEM SEPARATOR
+        MENUITEM "&O programu...", IDM_ABOUT
+    END
+END
+
+IDC_EVENTVWR ACCELERATORS
+BEGIN
+    "?", IDM_ABOUT, ASCII, ALT
+    "/", IDM_ABOUT, ASCII, ALT
+END
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 230, 75
+STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU
+CAPTION "O programu"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+    ICON IDI_EVENTVWR, IDC_MYICON, 14, 9, 21, 20
+    LTEXT "ReactOS Prohlížeč událostí 1.0", IDC_STATIC, 49, 10, 119, 8, SS_NOPREFIX
+    LTEXT "Copyright (C) 2007 Marc Piulachs (marc.piulachs@codexchange.net)", IDC_STATIC, 49, 20, 119, 22
+    DEFPUSHBUTTON "OK", IDOK, 90, 48, 42, 16, WS_GROUP
+END
+
+IDD_PROGRESSBOX DIALOGEX 0, 0, 230, 40
+STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER
+CAPTION "Čekejte.."
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+    CTEXT "Načítám protokol událostí. Prosím čekejte ...", IDC_STATIC, 0, 15, 230, 8, SS_NOPREFIX
+END
+
+IDD_EVENTDETAILDIALOG DIALOGEX 0, 0, 276, 282
+STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTEXTHELP
+CAPTION "Podrobnosti události"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    DEFPUSHBUTTON "&Zavřít", IDOK, 12, 258, 50, 14
+    PUSHBUTTON "&Předchozí", IDPREVIOUS, 78, 258, 50, 14
+    PUSHBUTTON "&Další", IDNEXT, 144, 258, 50, 14
+    PUSHBUTTON "&Nápověda", IDHELP, 210, 258, 50, 14
+    EDITTEXT IDC_EVENTTEXTEDIT, 14, 81, 247, 108, ES_MULTILINE | ES_READONLY
+    LTEXT "&Popis:", IDC_STATIC, 15, 70, 39, 8
+    LTEXT "Datum:", IDC_STATIC, 14, 14, 36, 8
+    EDITTEXT IDC_EVENTDATESTATIC, 56, 14, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "Čas:", IDC_STATIC, 14, 27, 36, 8
+    EDITTEXT IDC_EVENTTIMESTATIC, 56, 27, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "&Uživatel:", IDC_STATIC, 14, 41, 36, 8
+    EDITTEXT IDC_EVENTUSERSTATIC, 56, 41, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "P&očítač:", IDC_STATIC, 14, 54, 36, 8
+    EDITTEXT IDC_EVENTCOMPUTERSTATIC, 56, 54, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "ID události:", IDC_STATIC, 133, 15, 36, 8
+    EDITTEXT IDC_EVENTIDSTATIC, 175, 15, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "Zdroj:", IDC_STATIC, 133, 28, 36, 8
+    EDITTEXT IDC_EVENTSOURCESTATIC, 175, 28, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "Typ:", IDC_STATIC, 133, 42, 36, 8
+    EDITTEXT IDC_EVENTTYPESTATIC, 175, 42, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    LTEXT "Kategorie:", IDC_STATIC, 133, 55, 36, 8
+    EDITTEXT IDC_EVENTCATEGORYSTATIC, 175, 55, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL
+    EDITTEXT IDC_EVENTDATAEDIT, 14, 204, 247, 44, ES_MULTILINE | ES_READONLY
+    LTEXT "D&ata", IDC_STATIC, 14, 194, 20, 8
+    CONTROL "&Byty", IDC_BYTESRADIO, "Button", BS_AUTORADIOBUTTON, 39, 194, 34, 8
+    CONTROL "&Word", IDC_WORDRADIO, "Button", BS_AUTORADIOBUTTON, 77, 194, 33, 8
+END
+
+STRINGTABLE
+BEGIN
+    IDS_APP_TITLE "Prohlížeč událostí"
+    IDS_APP_TITLE_EX "%s - Protkol %s na \\\\"
+    IDS_STATUS_MSG "Počet událostí v protokolu %s: %lu"
+    IDS_EVENTSTRINGIDNOTFOUND "Popis ID události ( %lu ) zdroj ( %s ) nebyl nalezen. Místní počítač neobsahuje potřebné informace v registru nebo chybí DLL soubory pro zobrazení zpráv ze vzdáleného počítače."
+    IDS_EVENTLOG_ERROR_TYPE "Chyba"
+    IDS_EVENTLOG_WARNING_TYPE "Upozornění"
+    IDS_EVENTLOG_INFORMATION_TYPE "Informace"
+    IDS_EVENTLOG_AUDIT_SUCCESS "Úspěšný audit"
+    IDS_EVENTLOG_AUDIT_FAILURE "Audit selhal"
+    IDS_EVENTLOG_SUCCESS "Úspěch"
+    IDS_EVENTLOG_UNKNOWN_TYPE "Neznámá událost"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_COLUMNTYPE "Typ"
+    IDS_COLUMNDATE "Datum"
+    IDS_COLUMNTIME "Čas"
+    IDS_COLUMNSOURCE "Zdroj"
+    IDS_COLUMNCATEGORY "Kategorie"
+    IDS_COLUMNEVENT "Událost"
+    IDS_COLUMNUSER "Uživatel"
+    IDS_COLUMNCOMPUTER "Počítač"
+    IDS_COLUMNEVENTDATA "Data události"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_NONE "Žádný"
+    IDS_NOT_AVAILABLE "Není k dispozici"
+END
diff --git a/base/applications/mscutils/servman/lang/cs-CZ.rc b/base/applications/mscutils/servman/lang/cs-CZ.rc
new file mode 100644 (file)
index 0000000..d05c65d
--- /dev/null
@@ -0,0 +1,281 @@
+LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+
+IDR_MAINMENU MENU
+BEGIN
+    POPUP "&Soubor"
+    BEGIN
+        MENUITEM "Exportovat...", ID_EXPORT
+        MENUITEM SEPARATOR
+        MENUITEM "&Konec", ID_EXIT
+    END
+    POPUP "Akce"
+    BEGIN
+        MENUITEM "Připojit k...", ID_CONNECT, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Spustit", ID_START, GRAYED
+        MENUITEM "Zastavit", ID_STOP, GRAYED
+        MENUITEM "Pozastavit", ID_PAUSE, GRAYED
+        MENUITEM "Pokračovat", ID_RESUME, GRAYED
+        MENUITEM "Restartovat", ID_RESTART, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Obnovit", ID_REFRESH
+        MENUITEM SEPARATOR
+        MENUITEM "Upravit...", ID_EDIT, GRAYED
+        MENUITEM "Vytvořit...", ID_CREATE, GRAYED
+        MENUITEM "Odstranit...", ID_DELETE, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Vlastnosti...", ID_PROP, GRAYED
+    END
+    POPUP "Zobrazit"
+    BEGIN
+        MENUITEM "Velké ikony", ID_VIEW_LARGE
+        MENUITEM "Malé ikony", ID_VIEW_SMALL
+        MENUITEM "Seznam", ID_VIEW_LIST
+        MENUITEM "Detaily", ID_VIEW_DETAILS
+        MENUITEM SEPARATOR
+        MENUITEM "Upravit...", ID_VIEW_CUST, GRAYED
+    END
+    POPUP "Nápověda"
+    BEGIN
+        MENUITEM "Nápověda", ID_HELP
+        MENUITEM "O programu", ID_ABOUT
+    END
+END
+
+IDR_POPUP MENU
+BEGIN
+    POPUP "popup"
+    BEGIN
+        MENUITEM "Spustit", ID_START, GRAYED
+        MENUITEM "Zastavit", ID_STOP, GRAYED
+        MENUITEM "Pozastavit", ID_PAUSE, GRAYED
+        MENUITEM "pokračovat", ID_RESUME, GRAYED
+        MENUITEM "Restartovat", ID_RESTART, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Obnovit", ID_REFRESH
+        MENUITEM SEPARATOR
+        MENUITEM "Upravit...", ID_EDIT, GRAYED
+        MENUITEM "Odstranit...", ID_DELETE, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Vlastnosti...", ID_PROP, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Nápověda...", ID_HELP
+    END
+END
+
+IDD_ABOUTBOX DIALOGEX 22, 16, 190, 182
+CAPTION "O správci služeb"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME
+BEGIN
+    LTEXT "Správce služeb v0.8\nCopyright (C) 2005-2007\nGed Murphy (gedmurphy@reactos.org)", IDC_STATIC, 48, 7, 135, 30
+    PUSHBUTTON "Zavřít", IDOK, 75, 162, 44, 15
+    ICON IDI_SM_ICON, IDC_STATIC, 10, 10, 7, 30
+    EDITTEXT IDC_LICENSE_EDIT, 8, 44, 174, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE
+END
+
+IDD_DLG_GENERAL DIALOGEX 6, 6, 253, 232
+CAPTION "General"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP
+BEGIN
+    LTEXT "", IDC_SERV_NAME, 70, 11, 176, 11, WS_CHILD | WS_VISIBLE
+    EDITTEXT IDC_DISP_NAME, 70, 29, 176, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY
+    EDITTEXT IDC_DESCRIPTION, 70, 46, 176, 24, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_MULTILINE | ES_READONLY
+    EDITTEXT IDC_EXEPATH, 6, 86, 240, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY
+    COMBOBOX IDC_START_TYPE, 70, 107, 176, 40, WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST
+    PUSHBUTTON "Spustit", IDC_START, 6, 155, 54, 15, WS_DISABLED
+    PUSHBUTTON "Zastavit", IDC_STOP, 68, 155, 54, 15, WS_DISABLED
+    PUSHBUTTON "Pozastavit", IDC_PAUSE, 130, 155, 54, 15, WS_DISABLED
+    PUSHBUTTON "Pokračovat", IDC_RESUME, 192, 155, 54, 15, WS_DISABLED
+    LTEXT "Název služby:", IDC_STATIC, 4, 11, 53, 11
+    LTEXT "Jméno:", IDC_STATIC, 4, 29, 53, 11
+    LTEXT "Popis:", IDC_STATIC, 4, 51, 53, 11
+    LTEXT "Cesta:", IDC_STATIC, 6, 73, 82, 9
+    LTEXT "Typ spuštění:", IDC_STATIC, 6, 108, 53, 11
+    LTEXT "Stav služby:", IDC_STATIC, 4, 138, 53, 11
+    LTEXT "", IDC_SERV_STATUS, 70, 138, 176, 11, WS_CHILD | WS_VISIBLE
+    LTEXT "Zde můžete upřesnit parametry, které budou použity při spuštění.", IDC_STATIC, 6, 177, 240, 15
+    LTEXT "Parametry:", IDC_STATIC, 6, 200, 58, 11
+    EDITTEXT IDC_START_PARAM, 68, 199, 178, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+    PUSHBUTTON "Upravit", IDC_EDIT, 192, 215, 54, 15, WS_DISABLED
+END
+
+IDD_DLG_DEPEND DIALOGEX 6, 6, 253, 225
+CAPTION "Závislosti"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP
+BEGIN
+    CONTROL "", IDC_DEPEND_TREE1, "SysTreeView32" , WS_BORDER | WS_CHILDWINDOW |
+            WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES |
+            TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 70, 236, 68
+    CONTROL "", IDC_DEPEND_TREE2, "SysTreeView32", WS_BORDER | WS_CHILDWINDOW |
+            WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES |
+            TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 151, 234, 67
+    LTEXT "Některé služby závisí na jiných službách, systémových ovladačích nebo načítají jiné skupiny služeb. Zastavené nebo nesprávně fungující součásti systému mohou ovlivnit závislé služby.", IDC_STATIC, 8, 7, 238, 26
+    LTEXT "Tato služba závisí na následujících součástech:", IDC_STATIC, 8, 57, 236, 9
+    LTEXT "", IDC_DEPEND_SERVICE, 8, 38, 236, 13
+END
+
+IDD_DLG_CREATE DIALOGEX 6, 6, 225, 209
+CAPTION "Vytvořit službu"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP
+BEGIN
+    EDITTEXT IDC_CREATE_SERVNAME, 72, 12, 150, 11, WS_CHILD | WS_VISIBLE | WS_EX_CLIENTEDGE
+    EDITTEXT IDC_CREATE_DISPNAME, 72, 31, 150, 11, WS_CHILD | WS_VISIBLE
+    EDITTEXT IDC_CREATE_PATH, 10, 62, 210, 13, WS_CHILD | WS_VISIBLE
+    EDITTEXT IDC_CREATE_DESC, 10, 97, 210, 48, WS_CHILD | WS_VISIBLE
+    EDITTEXT IDC_CREATE_OPTIONS, 10, 162, 210, 13, WS_CHILD | WS_VISIBLE
+    LTEXT "*Název služby :", IDC_STATIC, 12, 12, 54, 9
+    LTEXT "*Jméno :", IDC_STATIC, 12, 33, 54, 9
+    LTEXT "*Cesta :", IDC_STATIC, 10, 51, 68, 9
+    LTEXT "Popis :", IDC_STATIC, 12, 86, 44, 9
+    PUSHBUTTON "OK", IDOK, 126, 192, 44, 13
+    PUSHBUTTON "Storno", IDCANCEL, 176, 192, 46, 13
+    LTEXT "Další možnosti (viz Nápovědu)", IDC_STATIC, 10, 151, 134, 9
+    PUSHBUTTON "Nápověda", ID_CREATE_HELP, 10, 192, 44, 13
+END
+
+IDD_DLG_DELETE DIALOGEX 6, 6, 185, 148
+CAPTION "Odstranit službu"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME
+BEGIN
+    ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22
+    LTEXT "Opravdu chcete tuto službu odstranit? Tuto akci nelze vrátit!", IDC_STATIC, 50, 6, 125, 25
+    LTEXT "Název služby:", IDC_STATIC, 6, 40, 80, 9
+    LTEXT "", IDC_DEL_NAME, 15, 53, 160, 15
+    EDITTEXT IDC_DEL_DESC, 6, 73, 174, 48, WS_CHILD | WS_VISIBLE | WS_VSCROLL |
+             WS_EX_STATICEDGE | ES_MULTILINE | ES_READONLY
+    PUSHBUTTON "Ano", IDOK, 26, 129, 54, 13
+    DEFPUSHBUTTON "Ne", IDCANCEL, 102, 129, 54, 13
+END
+
+IDD_DLG_DEPEND_STOP DIALOGEX 6, 6, 240, 148
+CAPTION "Zastavit jiné služby"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME
+BEGIN
+    ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22
+    LTEXT "", IDC_STOP_DEPENDS, 40, 8, 170, 25
+    LISTBOX IDC_STOP_DEPENDS_LB, 15, 40, 210, 70, WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE | LBS_NOSEL
+    LTEXT "Chcete zastavit tyto služby?", IDC_STATIC, 15, 110, 150, 10
+    DEFPUSHBUTTON "Ano", IDOK, 60, 129, 54, 14
+    PUSHBUTTON "Ne", IDCANCEL, 120, 129, 54, 14
+END
+
+IDD_DLG_HELP_OPTIONS DIALOGEX 6, 6, 200, 150
+CAPTION "Možnosti"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE 0x10CF0000
+BEGIN
+    LTEXT "", IDC_CREATE_HELP, 6, 5, 200, 150
+    PUSHBUTTON "Ok", IDOK, 75, 130, 44, 13
+END
+
+IDD_DLG_PROGRESS DIALOGEX 6, 6, 255, 89
+CAPTION "Ovldání služeb"
+FONT 8, "MS Shell Dlg", 0, 0
+STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_VISIBLE | DS_MODALFRAME
+EXSTYLE WS_EX_TOOLWINDOW
+BEGIN
+    CONTROL "", IDC_SERVCON_PROGRESS, "msctls_progress32", 0x50000000, 8, 46, 238, 13
+    LTEXT "", IDC_SERVCON_INFO, 8, 5, 236, 11
+    LTEXT "", IDC_SERVCON_NAME, 8, 25, 66, 11
+    PUSHBUTTON "&Zavřít", IDOK, 100, 70, 54, 13
+END
+
+STRINGTABLE
+BEGIN
+    IDS_FIRSTCOLUMN "Název"
+    IDS_SECONDCOLUMN "Popis"
+    IDS_THIRDCOLUMN "Stav"
+    IDS_FOURTHCOLUMN "Typ spuštění"
+    IDS_FITHCOLUMN "Přihlásit jako"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_SERVICES_STARTED "Spuštěno"
+    IDS_SERVICES_STOPPED "Zastaveno"
+    IDS_SERVICES_AUTO "Automaticky"
+    IDS_SERVICES_MAN "Ručně"
+    IDS_SERVICES_DIS "Zakázáno"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_NUM_SERVICES "Počet služeb: %d"
+    IDS_STOP_DEPENDS "Zastavením %s dojde také k zastavení"
+    IDS_NO_DEPENDS "<Žádné závislosti>"
+    IDS_LICENSE "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.\r\n\r\nThis 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.\r\n\r\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
+END
+
+STRINGTABLE
+BEGIN
+    IDS_TOOLTIP_PROP "Vlastnosti"
+    IDS_TOOLTIP_REFRESH "Obnovit"
+    IDS_TOOLTIP_EXPORT "Export seznamu"
+    IDS_TOOLTIP_CREATE "Vytvořit novou službu"
+    IDS_TOOLTIP_DELETE "Odstraní danou službu"
+    IDS_TOOLTIP_START "Spustit službu"
+    IDS_TOOLTIP_STOP "Zastavit službu"
+    IDS_TOOLTIP_PAUSE "Pozastavit službu"
+    IDS_TOOLTIP_RESTART "Restartovat službu"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_PROGRESS_INFO_START "ReactOS se pokouší spustit následující službu"
+    IDS_PROGRESS_INFO_STOP "ReactOS se pokouší zastavit následující službu"
+    IDS_PROGRESS_INFO_PAUSE "ReactOS se pokouší pozastavit následující službu"
+    IDS_PROGRESS_INFO_RESUME "ReactOS se pokouší pokračovat s následující službou"
+    IDS_CREATE_SUCCESS "Služba úspěšně vytvořena"
+    IDS_DELETE_SUCCESS "Služba úspěšně odstraněna"
+    IDS_CREATE_REQ "Položky označené hvězdičkou\njsou povinné"
+    IDS_DELETE_STOP "Před odstraněním musí být služba ručně zastavena!"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_HELP_OPTIONS "MOŽNOSTI VYTVOŘENÍ:\r\nPOZNÁMKA: Jméno parametru zahrnuje i znak rovnítko.\r\n type= <own|share|interact|kernel|filesys|rec>\r\n       (výchozí = own)\r\n start= <boot|system|auto|demand|disabled>\r\n       (výchozí = demand) \r\n error= <normal|severe|critical|ignore>\r\n       (výchozí = normal)\r\n group= <SkupinaPořadíNačtení>\r\n tag= <yes|no>\r\n depend= <Závislosti(oddělené / (lomítko))>\r\n obj= <JménoÚčtu|JménoObjektu>\r\n       (výchozí = LocalSystem)\r\n password= <heslo>\r\n"
+END
+
+/* Hints */
+STRINGTABLE
+BEGIN
+    IDS_HINT_BLANK " "
+    IDS_HINT_EXPORT " Vyexportuje daný seznam do souboru."
+    IDS_HINT_EXIT " Ukončí program."
+    IDS_HINT_CONNECT " Spravovat jiný počítač."
+    IDS_HINT_START " Spustit vybranou službu."
+    IDS_HINT_STOP " Zastavit vybranou službu."
+    IDS_HINT_PAUSE " Pozastavit vybranou službu."
+    IDS_HINT_RESUME " Pokračovat s vybranou službou."
+    IDS_HINT_RESTART " Zastavit a spustit vybranou službu."
+    IDS_HINT_REFRESH " Obnovit seznam služeb."
+    IDS_HINT_EDIT " Upravit vlastnosti vybrané služby."
+    IDS_HINT_CREATE " Vytvořit novou službu."
+    IDS_HINT_DELETE " Odstranit vybranou službu."
+    IDS_HINT_PROP " Zobrazit panel vlastností pro vybranou službu."
+    IDS_HINT_LARGE " Zobrazit služby jako velké ikony."
+    IDS_HINT_SMALL " Zobrazit služby jako malé ikony."
+    IDS_HINT_LIST " Zobrazit služby jako seznam."
+    IDS_HINT_DETAILS " Zobrazit služby jako podrobný seznam."
+    IDS_HINT_CUST " Upravit zobrazení."
+    IDS_HINT_HELP " Zobrazit nápovědu."
+    IDS_HINT_ABOUT " O ReactOS Správci služeb."
+    IDS_HINT_SYS_RESTORE " Obnovit normální velikost tohoto okna."
+    IDS_HINT_SYS_MOVE " Přesunout okno."
+    IDS_HINT_SYS_SIZE " Změnit velikost okna."
+    IDS_HINT_SYS_MINIMIZE " Minimalizovat na panel start."
+    IDS_HINT_SYS_MAXIMIZE " Maximalizovat na celou obrazovku."
+    IDS_HINT_SYS_CLOSE " Zavřít toto okno."
+END
+
+/* Application title */
+STRINGTABLE
+BEGIN
+    IDS_APPNAME "ReactOS Správce služeb"
+END
index 6d90b1c..e9c1274 100644 (file)
@@ -114,7 +114,7 @@ BEGIN
     CONTROL "", IDC_DEPEND_TREE2, "SysTreeView32", WS_BORDER | WS_CHILDWINDOW |
             WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES |
             TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 151, 234, 67
-    LTEXT "Birtakım hizmetler, diğer hizmetlere, dizge sürücülerine ve yükleme sıra öbeklerine bağımlıdır. Eğer bir dizge bileşeni, durdurulmuşsa ya da düzgün bir şekilde çalışmıyorsa bağımlı hizmetler etkilenebilir.", IDC_STATIC, 8, 7, 238, 26
+    LTEXT "Birtakım hizmetler, başka hizmetlere, dizge sürücülerine ve yükleme sıra öbeklerine bağımlıdır. Eğer bir dizge bileşeni, durdurulmuşsa ya da düzgün bir şekilde çalışmıyorsa bağımlı hizmetler etkilenebilir.", IDC_STATIC, 8, 7, 238, 26
     LTEXT "Bu hizmet aşağıdaki bileşenlere bağımlıdır:", IDC_STATIC, 8, 57, 236, 9
     LTEXT "", IDC_DEPEND_SERVICE, 8, 38, 236, 13
 END
@@ -155,7 +155,7 @@ BEGIN
 END
 
 IDD_DLG_DEPEND_STOP DIALOGEX 6, 6, 240, 148
-CAPTION "Diğer Hizmetleri Kapatma"
+CAPTION "Başka Hizmetleri Kapatma"
 FONT 8, "MS Shell Dlg", 0, 0
 STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME
 BEGIN
index 0959200..9c52761 100644 (file)
@@ -36,6 +36,9 @@ IDI_DRIVER ICON "res/driver.ico"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
index 7202c36..3f03736 100644 (file)
@@ -1,6 +1,6 @@
 /* FILE:       applications/rapps/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2010-12-12
+ * UPDATED:    2014-04-20
  */
 
 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
@@ -21,9 +21,9 @@ BEGIN
         MENUITEM SEPARATOR
         MENUITEM "Odstranit z &registru", ID_REGREMOVE
         MENUITEM SEPARATOR
-        MENUITEM "&Obnovit", ID_REFRESH
+        MENUITEM "Ob&novit", ID_REFRESH
         MENUITEM SEPARATOR
-        MENUITEM "Update Da&tabase", ID_RESETDB
+        MENUITEM "&Aktualizovat databázi", ID_RESETDB
     END
     POPUP "Nápověda"
     BEGIN
@@ -51,9 +51,9 @@ BEGIN
         MENUITEM SEPARATOR
         MENUITEM "Odstranit z &registru", ID_REGREMOVE
         MENUITEM SEPARATOR
-        MENUITEM "&Obnovit", ID_REFRESH
+        MENUITEM "Ob&novit", ID_REFRESH
         MENUITEM SEPARATOR
-        MENUITEM "Update Da&tabase", ID_RESETDB
+        MENUITEM "&Aktualizovat databázi", ID_RESETDB
     END
 END
 
@@ -103,7 +103,7 @@ STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME
 CAPTION "O programu"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "ReactOS Manažer aplikací\nCopyright (C) 2009\nby Dmitry Chapyshev (dmitry@reactos.org)", IDC_STATIC, 48, 7, 130, 39
+    LTEXT "ReactOS Správce aplikací\nCopyright (C) 2009\nDmitry Chapyshev (dmitry@reactos.org)", IDC_STATIC, 48, 7, 130, 39
     PUSHBUTTON "Zavřít", IDOK, 133, 46, 50, 14
     ICON IDI_MAIN, IDC_STATIC, 10, 10, 7, 30
 END
@@ -168,7 +168,7 @@ BEGIN
     IDS_CAT_INTERNET "Internet a sítě"
     IDS_CAT_LIBS "Knihovny"
     IDS_CAT_OFFICE "Kancelář"
-    IDS_CAT_OTHER "Jiné"
+    IDS_CAT_OTHER "Ostatní"
     IDS_CAT_SCIENCE "Věda"
     IDS_CAT_TOOLS "Nástroje"
     IDS_CAT_VIDEO "Video"
@@ -176,20 +176,20 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_APPTITLE "ReactOS Manažer aplikací"
+    IDS_APPTITLE "ReactOS Správce aplikací"
     IDS_SEARCH_TEXT "Hledat..."
     IDS_INSTALL "Instalovat"
     IDS_UNINSTALL "Odinstalovat"
     IDS_MODIFY "Změnit"
     IDS_APPS_COUNT "Počet aplikací: %d"
-    IDS_WELCOME_TITLE "Vítejte v ReactOS Manažeru aplikací!\n\n"
+    IDS_WELCOME_TITLE "Vítejte v ReactOS Správci aplikací!\n\n"
     IDS_WELCOME_TEXT "Na levé straně zvolte kategorii, pak vpravo zvolte aplikaci, která bude nainstalována nebo odinstalována.\nWebová stránka ReactOS: "
     IDS_WELCOME_URL "http://www.reactos.org"
     IDS_INSTALLED "Nainstalováno"
-    IDS_AVAILABLEFORINST "Dostupné k instalaci"
+    IDS_AVAILABLEFORINST "Lze instalovat"
     IDS_UPDATES "Aktualizace"
     IDS_APPLICATIONS "Aplikace"
-    IDS_CHOOSE_FOLDER_TEXT "Zvolte složku, do které se budou ukládat stažené soubory:"
+    IDS_CHOOSE_FOLDER_TEXT "Zvolte složku, do které se budou ukládat stažené soubory: "
     IDS_CHOOSE_FOLDER_ERROR "Zvolená složka neexistuje. Vytvořit?"
     IDS_APP_REG_REMOVE "Určitě odstranit data instalovaného programu z registru?"
     IDS_INFORMATION "Informace"
index 7e20c85..bd0a12f 100644 (file)
@@ -165,7 +165,7 @@ BEGIN
     IDS_CAT_INTERNET "Ağ"
     IDS_CAT_LIBS "Kitaplıklar"
     IDS_CAT_OFFICE "Büro"
-    IDS_CAT_OTHER "Diğer"
+    IDS_CAT_OTHER "Başka"
     IDS_CAT_SCIENCE "Bilim"
     IDS_CAT_TOOLS "Araçlar"
     IDS_CAT_VIDEO "Vidyo"
@@ -188,7 +188,7 @@ BEGIN
     IDS_APPLICATIONS "Uygulamalar"
     IDS_CHOOSE_FOLDER_TEXT "İndirilenlerin saklanacağı bir dizin seçiniz:"
     IDS_CHOOSE_FOLDER_ERROR "Belirttiğiniz dizin yok. Belirttiğiniz dizin oluşturulsun mu?"
-    IDS_APP_REG_REMOVE "Kurulan izlencenin girişini Değer Defteri'nden silmeyi doğruluyor musunuz?"
+    IDS_APP_REG_REMOVE "Kurulan izlencenin girişini değer defterinden silmek istemeyi doğruluyor musunuz?"
     IDS_INFORMATION "Bilgi"
-    IDS_UNABLE_TO_REMOVE "İzlencenin girişi Değer Defteri'nden silinemiyor."
+    IDS_UNABLE_TO_REMOVE "İzlencenin girişi değer defterinden silinemiyor."
 END
index 69d4c65..7dfbe6a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Abyss Web server X1\r
index b760df4..cca6ec4 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = AC97 Driver for VirtualBox\r
@@ -20,6 +20,11 @@ Name = AC97 Treiber für VirtualBox
 Licence = Unbekannt\r
 Description = Entpacken in das "ReactOS"-Verzeichnis und ReactOS zweimal neustarten.\r
 \r
+[Section.0410]\r
+Name = Driver AC97 per VirtualBox\r
+License = Sconosciuta\r
+Descrizione = Estrarre nella cartella "ReactOS" e poi riavviare ReactOs due volte.\r
+\r
 [Section.040a]\r
 Name = Driver AC97 para VirtualBox\r
 Licence = Desconocida\r
index 4dd4561..501ff11 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = AlReader
@@ -13,7 +13,7 @@ CDPath = none
 Description = Ein FB2 eBook Reader. Unterstützung für folgende Formate: fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. ZIP und GZ Archive werden ebenfalls unterstützt.
 
 [Section.0410]
-Description = Un eBook Reader.
+Description = Un eBook Reader. Legge i formati fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. Supporta gli archivi ZIP e GZ.
 
 [Section.0415]
 Description = Czytnik eBooków. Obsługuje formaty: fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. Obsługiwane są także pliki w archivach ZIP i GZ.
index 629b548..ac1b79f 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Ants
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Ein strategisches Kartenspiel. Sie bauen Ihr eigenes Schloss und versuchen, die gegnerische Burg zu zerstören. Sie benötigen ein ZIP-Programm, um es zu installieren.
 
+[Section.0410]
+Description = Un gioco di carte strategico. Costruisci il tuo castello e prova a distruggere il castello nemico. Necessita di un programma di estrazione ZIP per essere installato.
+
 [Section.0415]
 Description = Karciana gra strategiczna. Budujesz zamek, przy okazji próbujesz zniszczyć zamek wroga. Wymaga programu archiwizującego do wypakowania.
 
index 6a2d08a..5f59de9 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Audio Grabber\r
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]\r
 Description = Ein sehr guter CD-Ripper/Audio-Datei-Konverter.\r
 \r
+[Section.0410]\r
+Description = Un buon CD Ripper/Convertitore di file Audio.\r
+\r
 [Section.040a]\r
 Description = Un buen CD Ripper/ conversor de archivos de audio.\r
 \r
index 4707c75..84094fc 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -15,6 +15,9 @@ CDPath = none
 [Section.0407]
 Description = Bochs ist ein portabler Open-Source IA-32 (x86) PC-Emulator geschrieben in C++, der auf den meisten populären Plattformen läuft. 
 
+[Section.0410]
+Description = Bochs è un emulatore pc IA-32 (x86) scritto in C++ open source e portatile, che può essere eseguito sulle piattaformi più popolari.
+
 [Section.0415]
 Description = Bochs to przenośny (portable) emulator platformy IA-32 (x86) napisany w C++, działa na wielu popularnych platformach sprzętowych.
 
index dd3435e..58e7b36 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
index 6c50c43..ef5adb3 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Bound Around (Demo)
@@ -13,6 +13,10 @@ CDPath = none
 [Section.0407]
 Description = Ein Spiel, ähnlich zu Frozen Fruits.
 
+[Section.0410]
+Name = Bound Around (Versione di prova)
+Description = Un gioco simile a Frozen Fruits.
+
 [Section.041f]
 Name = Bound Around (Göstermelik)
 Licence = Kısıtlı
index dac37a4..4b6798c 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Christmas Bound
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Ein Spiel, ähnlich zu Frozen Fruits.
 
+[Section.0410]
+Description = Un gioco simile a Frozen Fuits.
+
 [Section.041f]
 Licence = Ücretsiz
 Description = Frozen Fruits'e benzeyen bir oyun.
index 1ebd822..693a588 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Chromium B.S.U.
index cb13c1f..07fdc78 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Click-N-Type Virtual Keyboard
index a21ed29..ac2172c 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Code::Blocks (no compiler)
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthält keinen Compiler.
 
+[Section.0410]
+Description = Un IDE potente, open source, multipiattaforma. Non contiene un compilatore.
+
 [Section.041f]
 Name = Code::Blocks (Derleyicisiz)
 Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. Bir derleyici içermez.
index 8f0f87d..6540578 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Code::Blocks TDM-GCC (version 4.7.1, 32 bit)
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthält den TDM-GCC (version 4.7.1, 32 bit) Compiler.
 
+[Section.0410]
+Description = Un IDE potente, open source, multipiattaforma. Contiene il compilatore TDM-GCC (versione 4.7.1, 32 bit).
+
 [Section.041f]
 Name = Code::Blocks TDM-GCC (sürüm 4.7.1, 32 bitlik)
 Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. TDM-GCC (sürüm 4.7.1, 32 bitlik) derleyicisini içerir.
index 20e15bf..e8fadd4 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Code::Blocks TDM-GCC (version 4.8.1, 32 bit)
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthät den TDM-GCC (version 4.8.1, 32 bit) Compiler.
 
+[Section.0410]
+Description = Un IDE potente, open source, multipiattaforma. Contiene il compilatore TDM-GCC (versione 4.8.1, 32 bit).
+
 [Section.041f]
 Name = Code::Blocks TDM-GCC (sürüm 4.8.1, 32 bitlik)
 Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. TDM-GCC (sürüm 4.8.1, 32 bitlik) derleyicisini içerir.
index b9f10de..b9ea0fd 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual Basic 6.0 Common Controls\r
index de51e04..0db353c 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Orwell Dev-C++ MinGW32
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Eine gepflegte Version von Dev-C++. Der MinGW32 Compiler liegt bei.
 
+[Section.0410]
+Description = Una versione mantenuta di Dev-C++. Contiene il compilatore MinGW32.
+
 [Section.041f]
 Description = Dev-C++'nın sürdürülen bir sürümü. MinGW32 derleyicisini içerir.
 Size = 60,2 MB
index 2761f21..f0f490d 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Orwell Dev-C++ TDM GCC x64
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Eine gepflegte Version von Dev-C++. Der 64 bit TDM-GCC Compiler liegt bei.
 
+[Section.0410]
+Description = Una versione sostenuta di Dev-C++. Contiene il compilatore a 64bit TDM-GCC.
+
 [Section.041f]
 Description = Dev-C++'nın sürdürülen bir sürümü. 64 bitlik TDM-GCC derleyicisini içerir.
 Size = 44,8 MB
index c266f55..5079c79 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Diablo II\r
index 9c5e275..f38620f 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = DOSBox\r
diff --git a/base/applications/rapps/rapps/dplus.txt b/base/applications/rapps/rapps/dplus.txt
new file mode 100644 (file)
index 0000000..2a54a7e
--- /dev/null
@@ -0,0 +1,22 @@
+; UTF-8
+
+[Section]
+Name = D+ Browser
+Version = 0.5b
+Licence = GPLv3
+Description = DPlus is a graphical web browser with an emphasis on security, performance and portability. It is based on Dillo and it is forked from Dillo-Win32 project.
+Size = 1.36 MB
+Category = 5
+URLSite = http://dplus-browser.sourceforge.net/
+URLDownload = http://heanet.dl.sourceforge.net/project/dplus-browser/Releases/dplus-0.5b/dplus-0.5b-setup.exe
+CDPath = none
+
+[Section.0410]
+License = GPL versione 3
+Description = DPlus è un web browser grafico con un accenno alla sicurezza, le prestazioni e portabilità. è basata su Dillo ed è diviso dal progetto Dillo-Win32.
+
+[Section.041f]
+Name = D+ Tarayıcı
+Licence = GPL 3. sürüm
+Description = DPlus; güvenlik, başarım ve taşınabilirlik üzerine bir vurguyla, çizgelik bir Umûmî Ağ tarayıcısıdır. Dillo tabanlıdır ve Dillo-Win32 tasarısından çatallanmıştır.
+Size = 1,36 MB
index c403f52..d2ff196 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = DVD Write Now
index 653e7d0..35e433d 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Microsoft Excel Viewer
index 0c4631a..4990352 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Fox Audio Player\r
index b27dee4..30373c7 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -16,6 +16,10 @@ CDPath = none
 Licence = Unbekannt
 Description = Mozilla Fira Font Pack, Beinhaltet Mono und Sans Schriften. Bitte in den "ReactOS" Ordner entpacken.
 
+[Section.0410]
+Licence = Sconosciuta
+Description = Fira Font Pack di Mozilla, Include i font Mono e Sans. Estrare nella cartella "ReactOS".
+
 [Section.0415]
 Description = Pakiet czcionek Mozilla Fira Font, zawiera czcionki Mono i Sans. Wypakuj do folderu "ReactOS".
 Licence = Nieznana
index 89df72c..038cfe1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Mozilla Firefox 28
index 141348b..ae69982 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mozilla Firefox 2.0\r
index 9477084..e7032cb 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mozilla Firefox 3.0\r
index 74af5cb..4046e9f 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mozilla Firefox 3.6\r
index 4ecca2c..22747ac 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Globulation2
@@ -15,7 +15,7 @@ CDPath = none
 Description = Globulation 2 ist ein Echtzeitstrategiespiel. Das Spiel vereinfacht das Mikromanagement, indem es Einheiten automatisch mit Aufträgen versieht.
 
 [Section.0410]
-Description = Globulation 2 è un gioco di strategia in tempo reale.
+Description = Globulation 2 è un gioco di strategia in tempo reale. Il gioco minimizza la supervisone eccessiva assegnando in automatico compiti alle unità.
 
 [Section.0415]
 Description = Globulation 2 to gra strategiczna czasu rzeczywistego. Gra minimalizuje zarządzanie automatycznie przydzielając zadania jednostkom.
index d2048ce..a43dd0e 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
index 9e54d7a..0faa3bb 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -21,6 +21,9 @@ URLDownload = http://mh-nexus.de/downloads/HxDSetupDE.zip
 [Section.0415]
 Description = Dobry edytor Hex. Do wypakowania pliku potrzebny jest program archiwizujący np. 7-Zip.
 
+[Section.0410]
+Description = Un buon editor hexadecimale. Necessita 7-Zip o un programma simile per estrarlo.
+
 [Section.0418]
 Licence = Gratuită
 Description = Un bun editor hexazecimal. E necesar un utilitar de dezarhivare de tip ZIP.
index 2f71b9a..1f146cb 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
index c78c757..ca9bbe5 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = K Desktop Environment\r
index 9b205d5..2e5e112 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Kyodai Mahjongg
index 19c6e54..6f1aec1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = LBreakout2\r
@@ -22,7 +22,7 @@ Description = Clone de casse-brique utilisant la bibliothèque SDL.
 Size = 3,03 Mo\r
 \r
 [Section.0410]\r
-Description = Clone di Breakout utilizza librerie SDL.\r
+Description = Clone di Breakout che utilizza librerie SDL.\r
 \r
 [Section.0413]\r
 Description = Breakout kloon, gebruikt SDL.\r
index 6b25b91..e70dc80 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = LGeneral\r
@@ -22,7 +22,7 @@ Description = Clone de Pansez General utilisant la bibliothèque SDL.
 Size = 1,92 Mo\r
 \r
 [Section.0410]\r
-Description = Clone di Pansez General utilizza librerie SDL.\r
+Description = Clone di Pansez General che utilizza librerie SDL.\r
 \r
 [Section.0413]\r
 Description = Panzer General kloon, gebruikt SDL.\r
index be06d7c..dac8e7a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = LMarbles\r
@@ -22,7 +22,7 @@ Description = Clone de Atomix utilisant la bibliothèque SDL.
 Size = 1,39 Mo\r
 \r
 [Section.0410]\r
-Description = Clone di Atomix utilizza le librerie SDL.\r
+Description = Clone di Atomix che utilizza le librerie SDL.\r
 \r
 [Section.0413]\r
 Description = Atomix kloon, gebruikt SDL.\r
diff --git a/base/applications/rapps/rapps/mcwin32.txt b/base/applications/rapps/rapps/mcwin32.txt
new file mode 100644 (file)
index 0000000..a77b674
--- /dev/null
@@ -0,0 +1,32 @@
+; UTF-8
+
+[Section]
+Name = Midnight Commander for Windows
+Version = Build 183 (4.8.11)
+Licence = GPLv3
+Description = 32-bit Windows port of GNU Midnight Commander.
+Size = 2.35 MB
+Category = 12
+URLSite = http://sourceforge.net/projects/mcwin32/
+URLDownload = http://optimate.dl.sourceforge.net/project/mcwin32/mcwin32-build183-setup.exe
+CDPath = none
+
+[Section.0410]
+Name = Midnight Commander per Windows
+Version = Revisione 183 (4.8.11)
+Licence = GPL versione 3
+Description = Un porting Windows 32bit di Midnight Commander.
+
+[Section.041f]
+Name = Midnight Commander (Windows için)
+Version = Yapı 183 (4.8.11)
+Licence = GPL 3. sürüm
+Description = GNU Midnight Commander'ın 32 bitlik Windows uyarlamasıdır.
+Size = 2,35 MB
+
+[Section.0415]
+Name = Midnight Commander dla Windows
+Version = Build 183 (4.8.11)
+Licence = GPL wersja 3
+Description = 32-bitowy port GNU Midnight Commander dla Windows.
+Size = 2,35 MB
index fc79d4f..e4e1a5b 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = OLE Viewer and Microsoft Foundation Classes version 4\r
index 68e2478..7bbfff1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = mIRC 7\r
index 874ba2a..3f90e2b 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = mIRC 6\r
index b0112ac..1bb628f 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mono .net Development Framework\r
index 0184f79..5958f33 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Media Player Classic Home Cinema\r
index 6246d0a..9b2cebf 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Mpxplay
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Mpxplay ist ein konsolenbasierter 32-bit Audio Player für Windows. Zum extrahieren wird 7-Zip oder ein ähnliches Tool benötigt.
 
+[Section.0410]
+Description = Mpxplay è una console audio 32-bit per Windows. Necessita 7-Zip o un programma simile per essere estratto.
+
 [Section.0415]
 Description = Mpxplay to 32 bitowy odtwarzacz audio (działający w konsoli) dla Windows. Wymaga programu archiwizującego (np. 7-Zip) do wypakowania.
 
index c7c3cbc..5945a66 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft XML 3\r
index 34eadb6..e7f7d59 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft .NET Framework Version 1.1 Redistributable Package\r
index 1a3dd4c..7827168 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft .NET Framework Version 2.0 Redistributable Package\r
index a6a18a4..cb285f8 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft .NET Framework Version 2.0 Service Pack 2\r
index 50b7a72..31009ed 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Notepad++
index e25a216..7d85199 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Off By One Browser\r
index 63ae765..fd27224 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = OpenOffice 4.0\r
@@ -30,6 +30,7 @@ Size = 127,22 Mo
 URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/fr/Apache_OpenOffice_4.0.1_Win_x86_install_fr.exe\r
 \r
 [Section.0410]\r
+Description = La suite di office Open Source.\r
 URLSite = http://www.openoffice.org/it/\r
 Size = 132.39 MB\r
 URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/it/Apache_OpenOffice_4.0.1_Win_x86_install_it.exe\r
index 2021f27..4ea78aa 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = OpenOffice 2.4\r
@@ -31,6 +31,7 @@ URLSite = http://www.openoffice.org/fr/
 URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/fr/2.4.2/OOo_2.4.2_Win32Intel_install_fr.exe\r
 \r
 [Section.0410]\r
+Description = La suite di office Open Source.\r
 Size = 113.79 MB\r
 URLSite = http://www.openoffice.org/it/\r
 URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/it/2.4.3/OOo_2.4.3_Win32Intel_install_it.exe\r
index cca8069..f48893d 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = OpenTTD\r
@@ -22,7 +22,7 @@ Description = Clone open source du moteur de jeu "Transport Tycoon Deluxe". Vous
 Size = 7,0 Mo\r
 \r
 [Section.0410]\r
-Description = Clone open source del  motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon.\r
+Description = Clone open source del motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon.\r
 \r
 [Section.0413]\r
 Description = Open-bron kloon van de "Transport Tycoon Deluxe" spelletjesmotor. Je hebt een kopij van Transport Tycoon nodig.\r
index c31b64d..8ce86d7 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Opera\r
@@ -25,7 +25,7 @@ Description = Le populaire navigateur Opera avec beaucoup de fonctionnalités av
 Size = 12,56 Mo\r
 \r
 [Section.0410]\r
-Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
+Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
 \r
 [Section.0413]\r
 Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers.\r
index 4378e54..c118ee1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Opera\r
@@ -22,7 +22,7 @@ Description = Le populaire navigateur Opera avec beaucoup de fonctionnalités av
 Size = 7,21 Mo\r
 \r
 [Section.0410]\r
-Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
+Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
 \r
 [Section.0413]\r
 Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers.\r
index 52857bd..7a6def3 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = PeaZip
@@ -14,6 +14,12 @@ CDPath = none
 [Section.0407]
 Description = PeaZip ist ein freier, plattformübergreifender, quelloffener Datei- und Archivmanager. Er unterstützt über 150 Archiv-Formate.
 
+[Section.0410]
+Description = PeaZip è un manager di file e archivi gratis, multipiattaforma e open source. Supporta oltre 150 formati d'archivio.
+
+[Section.0415]
+PeaZip to darmowy, wieloplatformowy menedżer plików i archiwów, o otwartym źródle. Obsługuje ponad 150 formatów archiwów.
+
 [Section.041f]
 Description = PeaZip; ücretsiz, çapraz platform, açık kaynak bir kütük ve belgelik yöneticisidir. 150'den çok belgelikleme biçimini destekler.
 Size = 5,8 MB
index 9804859..b66cffd 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Pengupop
index 174a396..eac3f5e 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -18,6 +18,9 @@ Description = Version mit Layers, aber eingeschänkter als die Studio-X Version.
 [Section.0415]
 Description = Ta wersja obsługuje warstwy, ale ma większe ograniczenia od Studio X. PhotoFiltre Studio to program do retuszu zdjęć.
 
+[Section.0410]
+Description = Questa versione con pannelli ma più limitata della versione Studio X. PhotoFiltre Studio è un programma di fotoritocco completo.
+
 [Section.0418]
 Licence = Gratuită
 Description = PhotoFiltre Studio este o aplicație completă de retușare a imaginilor.
index 6e4208a..2497dae 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
index b5a4988..bab9cb1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Microsoft Powerpoint Viewer
index 1f02aa2..9ab8c66 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
index 220317a..4af5589 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -15,6 +15,9 @@ CDPath = none
 [Section.0407]
 Description = Das schnellste Artillerie-Spiel, das Sie jemals gespielt haben.
 
+[Section.0410]
+Description = Il gioco d'artiglieria più veloce a cui potrai giocare.
+
 [Section.0415]
 Description = Szybka gra artyleryjska 
 
index 7284a2e..5902e63 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = PuTTY\r
index fd9eeea..049cc5b 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Python 2\r
index ef97238..75be165 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = QB64 (SDL version)
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = QB64 ist ein Self-Hosting BASIC-Compiler für Microsoft Windows, Linux und Mac OS X, entwickelt, um mit Microsoft QBasic und Microsoft QuickBASIC kompatibel zu sein. Sie müssen 7-Zip oder ein ähnliches Dienstprogramm installiert haben, um es zu extrahieren.
 
+[Section.0410]
+Description = QB64 è un compilatore auto ospitante per Microsoft Windows, Linux e Mac OS X, progettato per essere compatibile con Microsoft QuickBasic. Necessita di 7-Zip o uno strumento simile per essere estratto.
+
 [Section.0415]
 Description = QB64 to kompilator BASIC zdolny do kompilacji własnego kodu źródłowego. Działa w systemach Windows, Linux i Mac OS X. Jest kompatybilny z Microsoft QBasic i QuickBASIC. Wymaga programu archiwizującego do wypakowania.
 
index a666c72..96bba2a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -15,6 +15,9 @@ CDPath = none
 [Section.0407]
 Description = Qmmp ist ein Audio-Player, der mit Hilfe der Qt Bibliothek geschrieben wurde. Die Benutzeroberfläche ist ähnlich zu WinAMP oder XMMS. Alternative Benutzeroberflächen sind ebenfalls verfügbar.
 
+[Section.0410]
+Description = Qmmp è un lettore multimediale, scritto con l'aiuto della libreria Qt. L'interfaccia grafica è simile a WinAMP o XMMS. Interfaccie utenti alternative sono disponibili.
+
 [Section.0415]
 Description = Gmmp to odtwarzacz audio, napisany z pomocą biblioteki Qt. Interfejs podobny jest do Winampa lub XMMS. Dostępnme są także dodatkowe skórki.
 
index 8a5f1d5..0b2053c 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = ReMooD\r
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]\r
 Description = ReMooD ist ein Port des Doom Legacy Sources. Es versucht das klassische Legacy Erfahrung zusammen mit neuen Features und mehr Stabilität zu bieten.\r
 \r
+[Section.0410]\r
+Description = ReMooD è un porting sorgente di Doom Legacy. Punta a provedere la classica esperienza ereditaria con nuove funzionalità e maggiore stabilità.\r
+\r
 [Section.040a]\r
 Description = ReMood es un port de Doom Legacy. Su fin es proporcionar la clásica experiencia anterior con nuevas características y mayor estabilidad.\r
 \r
index 18e22d6..02fdce2 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -15,6 +15,9 @@ CDPath = none
 [Section.0407]
 Description = Resource Hacker ist ein Freeware-Tool zum anzeigen, ändern, umbenennen, hinzufügen, löschen und extrahieren von Ressourcen in 32-Bit & 64-Bit-Windows Anwendungen und Ressourcen-Dateien (*. Res).
 
+[Section.0410]
+Description = Resource Hacker, è uno strumento freewere per vedere, modificare, rinominare, aggiungere, rimuovere e estrarre risorse in eseguibili Windows 32 e 64 bit e file di risorse (*.res).
+
 [Section.0415]
 Description = Resource Hacker to darmowe narzędzie do podglądu, modyfikacji, zmiany nazw, dodawania, kasowania i wypakowywania zasobów w plikach wykonywalnych 32bit i 64bit, oraz w plikach zasobów (*.res).
 
index 5e8f0b2..b17b529 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -15,6 +15,9 @@ CDPath = none
 [Section.0407]
 Description = Arcade-Style Spiel für UNIX, Mac OS X, Windows und DOS in der Tradition von: "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga / PC), "Sokoban" (PC). Sie benötigen ein ZIP-Programm, um es zu installieren.
 
+[Section.0410]
+Description = Gioco in stile arcade per UNIX, Mac OS X, Windows e DOS nella tradizione di: "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga/PC), "Sokoban" (PC). Necessita di un programma di decompressione di archivi ZIP per essere installato.
+
 Section.0415]
 Description = Gra typu Arcade dla UNIX, Mac OS X, Windows i DOS. Bazująca na "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga/PC), "Sokoban" (PC). Aby zainstalować te grę, potrzebny jest program archiwizujący np. 7-Zip.
 
index 56098d8..bbdd3eb 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = ReactOS Build Environment\r
index d2cb1c9..f51d300 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = ReactOS Build Environment AMD64 Addon\r
index 258000a..1990dea 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = ReactOS Build Environment ARM Addon\r
index b004377..0b586ea 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Samba TNG\r
@@ -22,7 +22,7 @@ Description = Cet outil vous permet d'accéder à vos répertoire/imprimantes pa
 Size = 2,13 Mo\r
 \r
 [Section.0410]\r
-Description = Questo strumento consente di accedere alle cartelle condivise di Windows / stampanti con ReactOS.\r
+Description = Questo strumento consente di accedere alle cartelle/stampanti condivise di Windows con ReactOS.\r
 \r
 [Section.0413]\r
 Description = Maakt het mogelijk om Windows gedeelde printers te gebruiken met ReactOS.\r
index 4d61035..2e18406 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = SoundBlaster Driver for VMWare\r
@@ -34,7 +34,7 @@ Size = 2,22 Mo
 [Section.0410]\r
 Name = Driver SoundBlaster per VMWare\r
 Licence = Sconosciuta\r
-Description = Unzip nella cartella "ReactOS" e riavviare ReactOS.\r
+Description = Estrarre nella cartella "ReactOS" e riavviare ReactOS due volte.\r
 \r
 [Section.0413]\r
 Name = SoundBlaster Driver voor VMWare\r
index 52300c0..208bcb8 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = SciTE\r
@@ -22,7 +22,7 @@ Description = SciTE est un éditeur de texte basé sur SCIntilla. Originelement
 Size = 730 ko\r
 \r
 [Section.0410]\r
-Description = SciTE è un editor di testo basato scintilla. Originariamente costruito per dimostrare Scintilla, è cresciuto fino a essere un editor generalmente utile con strutture per la creazione e l'esecuzione di programmi.\r
+Description = SciTE è un editor di testo basato su scintilla. Originariamente costruito per dimostrare Scintilla, è cresciuto fino a essere un editor generalmente utile con strutture per la creazione e l'esecuzione di programmi.\r
 \r
 [Section.0413]\r
 Description = SciTE is een tekstbewerker gebaseerd op SCIntilla. Origineel bedoeld om Scontilla te demonstreren, is uitgegroeid tot een handige editor met mogelijkheden voor ontwerken en uitvoeren van programma's.\r
index c976de6..c6df833 100644 (file)
@@ -1,10 +1,10 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = ScummVM\r
 Version = 1.6.0\r
 Licence = GPL\r
-Description = Sam and Max, Day of the Tentacle, etc on ReactOS.\r
+Description = Software that reproduce the working of graphical engine for videogames (Sam and Max, Day of the Tentacle, etc) on ReactOS.\r
 Size = 6.28 MB\r
 Category = 4\r
 URLSite = http://scummvm.org/\r
@@ -22,7 +22,7 @@ Description = Sam and Max, Day of the Tentacle, etc sur ReactOS.
 Size = 6,28 Mo\r
 \r
 [Section.0410]\r
-Description = Software che riproduce il funzionamento di motori grafici per videogiochi(Sam and Max, Day of the Tentacle, etc) su ReactOS.\r
+Description = Software che riproduce il funzionamento di motori grafici per videogiochi (Sam and Max, Day of the Tentacle, etc) su ReactOS.\r
 \r
 [Section.0413]\r
 Description = Sam and Max, Day of the Tentacle, enz. op ReactOS.\r
index 4837a28..236b3dc 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Simple Direct Media Layer (SDL) Mixer\r
index 0412ae5..fa77781 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Simple Direct Media Layer (SDL) Runtime\r
index 4355489..7e978db 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mozilla SeaMonkey\r
@@ -27,7 +27,7 @@ Size = 24,06 Mo
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/fr/SeaMonkey%20Setup%202.25.exe\r
 \r
 [Section.0410]\r
-Description = Mozilla Suite è vivo. Questo è l'unico e solo Browser, Mail, Chat, e Composer di cui avrete mai bisogno...\r
+Description = Mozilla Suite è vivo. Questo è l'unico pachetto che include Browser, Mail, Chat, e Composer di cui avrete mai bisogno...\r
 Size = 23.71 MB\r
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/it/SeaMonkey%20Setup%202.25.exe\r
 \r
index 8ae0a8a..ad350ef 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Snoopy
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Das Original C64 Snoopy Remake.
 
+[Section.0410]
+Description = Il remake del gioco Snoopy per Commodore 64.
+
 [Section.041f]
 Licence = Ücretsiz
 Description = Özgün C64 Snoppy'nın yeniden yapılmışı.
index e2c9769..0ff51a0 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 
 [Section]
@@ -13,6 +13,9 @@ CDPath = none
 [Section.0407]
 Description = Ein freies Schreiblernprogramm.
 
+[Section.0410]
+Description = Tutore di scrittura gratuita.
+
 [Section.0415]
 Description = Darmowy program do nauki pisania na klawiaturze.
 
index 6189475..9197a95 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = STEAM\r
index af1fd20..a4c3a8a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = SumatraPDF\r
@@ -22,7 +22,7 @@ Description = Sumatra PDF est un lecteur PDF léger, libre et open-source.
 Size = 4,0 Mo\r
 \r
 [Section.0410]\r
-Description = Sumatra PDF è un visualizzatore di file PDF. E' molto leggero ed è open source.\r
+Description = Sumatra PDF è un visualizzatore di file PDF, leggero e open source.\r
 \r
 [Section.0413]\r
 Description = Sumatra PDF is een slanke, gratis, open-bron PDF lezer.\r
index e17a8d4..e45c2c9 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Summer Bound
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Ein Spiel, ähnlich zu Frozen Fruits.
 
+[Section.0410]
+Description = Un gioco simile a Frozen Fuits
+
 [Section.041f]
 Licence = Ücretsiz
 Description = Frozen Fruits'e benzeyen bir oyun.
index 370b20b..bd0151d 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = Super DX-Ball
@@ -14,6 +14,9 @@ CDPath = none
 [Section.0407]
 Description = Super DX-Ball ist ein lebendiges und buntes Brick-Breaking-Spiel.
 
+[Section.0410]
+Description = Super DX-Ball è un gioco spacca blocchi vibrante e colorato
+
 [Section.0415]
 Description = Super DX-Ball - pełna koloru i animacji gra polegająca na zbijaniu klocków.
 
index 6f6cfac..20dd10d 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ; PL translation by wojo664
 [Section]
 Name = SuperTux
@@ -15,7 +15,7 @@ CDPath = none
 Description = SuperTux ist ein zweidimensionales, freies, Open Source Plattformspiel. 
 
 [Section.0410]
-Description = SuperTux è un gioco open-source a 2D.
+Description = SuperTux è un gioco open-source gratuito in 2D.
 
 [Section.0415]
 Description = SuperTux to darmowa dwu wymiarowa gra platformowa  OpenSource.
index 73d8134..e40f3a1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Tahoma Font\r
index a25ed47..427b78a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Mozilla Thunderbird 24
@@ -30,7 +30,7 @@ URLSite = https://www.mozilla.org/fr/thunderbird/
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/24.4.0/win32/fr/Thunderbird%20Setup%2024.4.0.exe
 
 [Section.0410]
-Description = Il più popolare e il migliore Clients mail gratuito.
+Description = Il più popolare e il migliore Client mail gratuito.
 Size = 20.91 MB
 URLSite = https://www.mozilla.org/it/thunderbird/
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/24.4.0/win32/it/Thunderbird%20Setup%2024.4.0.exe
index 201a4bf..ffc3bce 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Mozilla Thunderbird\r
@@ -30,7 +30,7 @@ URLSite = https://www.mozilla.org/fr/thunderbird/
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/fr/Thunderbird%20Setup%203.1.20.exe\r
 \r
 [Section.0410]\r
-Description = Il più popolare e il migliore Clients mail gratuito.\r
+Description = Il più popolare e il migliore Client mail gratuito.\r
 Size = 8.88 MB\r
 URLSite = https://www.mozilla.org/it/thunderbird/\r
 URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/it/Thunderbird%20Setup%203.1.20.exe\r
index 3a9954b..06e225f 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = UltraVNC\r
@@ -22,7 +22,7 @@ Description = Client/serveur VNC open source.
 Size = 3,27 Mo\r
 \r
 [Section.0410]\r
-Description = Client/serveur VNC open source.\r
+Description = Client/server VNC open source.\r
 \r
 [Section.0413]\r
 Description = Open-bron VNC afnemer/aanbieder.\r
index cfdc471..b4813f9 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual Basic 5 Runtime\r
index 1ae706e..1c48f22 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual Basic 6 Runtime\r
index 58693a9..c5c773a 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual C++ 2005 SP1 Redistributable Package\r
index 74c0f3b..1920ff1 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual C++ 2008 SP1 Redistributable Package\r
index e944533..99c6997 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Microsoft Visual C++ 2010 Redistributable Package
index 1e580af..9085eb4 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Microsoft Visual C++ 6 Redistributable Package\r
index 6faef05..6aeca75 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = VLC media player\r
index 96a0bec..a672340 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8\r
+; UTF-8\r
 \r
 [Section]\r
 Name = Windows Media Encoder 9\r
index 7d3884e..c2c46ee 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 
 [Section]
 Name = Microsoft Word Viewer
index 12604c8..ce7ff58 100644 (file)
@@ -1,4 +1,4 @@
-; UTF-8
+; UTF-8
 ;PL translation by wojo664
 
 [Section]
@@ -16,7 +16,7 @@ CDPath = none
 Description = Zaz ist ein freies Arcade Action Puzzle Spiel, ein wenig wie Frozen Bubble.
 
 [Section.0410]
-Description = Zaz è un puzzle game gratuito, simile a Frozen Bubble.
+Description = Zaz è un gioco arcade puzzle gratuito per computer, in parte simile a Frozen Bubble.
 
 [Section.0415]
 Description = Zaz to darmowa gra logiczno-zręcznościowa, trochę podobna do gry Frozen Bubble
index b24e556..03cfb35 100644 (file)
@@ -293,7 +293,7 @@ BEGIN
     ID_REGISTRY_DISCONNECTNETWORKREGISTRY "Uzaktaki bir bilgisayarın Değer Defteri'sine olan bağlantıyı keser."
     ID_REGISTRY_PRINT "Değer Defteri'nin tümünü ya da bir bölümünü yazdırır."
 /*  ID_HELP_HELPTOPICS "Değer Defteri Düzenleyicisi Yardımı'nı açar."  */
-    ID_HELP_ABOUT "İzlenceyle ilgili bilgi görüntüler."
+    ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler."
 END
 
 STRINGTABLE
@@ -320,18 +320,18 @@ BEGIN
     IDS_UNSUPPORTED_TYPE "Bu türdeki dizinler değiştirilemiyor: %ld"
     IDS_TOO_BIG_VALUE "Değer çok büyük: %ld"
     IDS_MULTI_SZ_EMPTY_STRING "REG_MULTI_SZ veri türü boş dizgi içeremez.\nBoş dizgiler dizelgeden silinmiştir."
-    IDS_QUERY_DELETE_KEY_ONE "Bu dizini silmeyi doğruluyor musunuz?"
-    IDS_QUERY_DELETE_KEY_MORE "Bu dizinleri silmeyi doğruluyor musunuz?"
+    IDS_QUERY_DELETE_KEY_ONE "Bu dizini silmek istemeyi doğruluyor musunuz?"
+    IDS_QUERY_DELETE_KEY_MORE "Bu dizinleri silmek istemeyi doğruluyor musunuz?"
     IDS_QUERY_DELETE_KEY_CONFIRM "Dizin Silme Doğrulaması"
-    IDS_QUERY_DELETE_ONE "Bu değeri silmeyi doğruluyor musunuz?"
-    IDS_QUERY_DELETE_MORE "Bu değerleri silmeyi doğruluyor musunuz?"
+    IDS_QUERY_DELETE_ONE "Bu değeri silmek istemeyi doğruluyor musunuz?"
+    IDS_QUERY_DELETE_MORE "Bu değerleri silmek istemeyi doğruluyor musunuz?"
     IDS_QUERY_DELETE_CONFIRM "Değer Silme Doğrulaması"
     IDS_ERR_DELVAL_CAPTION "Değerler Silinmesi Yanlışlığı"
     IDS_ERR_DELETEVALUE "Tüm belirtilmiş değerler silinemiyor."
     IDS_ERR_RENVAL_CAPTION "Değer Adı Değiştirilmesi Yanlışlığı"
     IDS_ERR_RENVAL_TOEMPTY "Adı değiştirilemiyor: %s. Belirtilen değer adı boş. Başka bir ad yazıp yeniden deneyiniz."
     IDS_QUERY_IMPORT_HIVE_CAPTION "Dizin Yenileme Doğrulaması"
-    IDS_QUERY_IMPORT_HIVE_MSG "Bir dizin seçili dizinle yenilenecektir.\nBu dizinin tüm alt dizinleri ve değerleri silinecektir.\nEylemi sürdürmek istiyor musunuz?"
+    IDS_QUERY_IMPORT_HIVE_MSG "Bir dizin seçili dizinle yenilenecektir.\nBu dizinin tüm alt dizinleri ve değerleri silinecektir.\nİşlemi sürdürmek istiyor musunuz?"
     IDS_NEW_KEY "%d. Yeni Dizin"
     IDS_NEW_VALUE "%d. Yeni Değer"
 END
@@ -397,7 +397,7 @@ END
 STRINGTABLE
 BEGIN
     IDS_IMPORT_PROMPT "Bilgi ekleme, yanlışlıkla değerleri değiştirebilir ya da silebilir ve bileşenlerin doğru çalışmasını engelleyebilir.\nEğer ""%s"" içindeki bilginin kaynağına güvenmiyorsanız onu Değer Defteri'ne eklemeyiniz.\n\nSürdürmek istediğinizi doğruluyor musunuz?"
-    IDS_IMPORT_OK "%s içinde bulunan dizinler ve değerler Değer Defteri'ne başarıyla eklendi."
+    IDS_IMPORT_OK """%s"" içinde bulunan dizinler ve değerler Değer Defteri'ne başarıyla eklendi."
     IDS_IMPORT_ERROR """%s"" alınamıyor: Kütüğü açmada yanlışlık. Bir disk yanlışlığı, bir kütük dizgesi yanlışlığı ya da kütüğün olmaması olabilir."
     IDS_EXPORT_ERROR """%s"" verilemiyor: Kütüğü oluşturmada ya da kütüğe yazmada yanlışlık. Bir disk yanlışlığı ya da bir kütük dizgesi yanlışlığı olabilir."
 END
@@ -541,6 +541,6 @@ END
  *STRINGTABLE
  *BEGIN
  *    ID_HELP_HELPTOPICS "Değer Defteri Düzenleyicisi Yardımı'nı açar."
- *    ID_HELP_ABOUT "İzlenceyle ilgili bilgi görüntüler."
+ *    ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler."
  *END
  */
index 81ca9ed..b12348b 100644 (file)
@@ -35,7 +35,7 @@ BEGIN
     GROUPBOX "Ses Düzeyi Düzenlenecekler", -1, 7, 25, 211, 77
     PUSHBUTTON "&Çalma", IDC_PLAYBACK, 13, 43, 47, 8, BS_AUTORADIOBUTTON
     PUSHBUTTON "K&aydetme", IDC_RECORDING, 13, 61, 47, 8, BS_AUTORADIOBUTTON
-    PUSHBUTTON "&Diğer:", IDC_OTHER, 13, 80, 42, 8, BS_AUTORADIOBUTTON | WS_DISABLED
+    PUSHBUTTON "&Başka:", IDC_OTHER, 13, 80, 42, 8, BS_AUTORADIOBUTTON | WS_DISABLED
     COMBOBOX IDC_LINE, 55, 80, 155, 50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED
     LTEXT "Aşağıdaki ses düzeyi denetimlerini göster:", IDC_LABELCONTROLS, 7, 109, 162, 8
     CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96
index c0715aa..93329eb 100644 (file)
@@ -277,11 +277,11 @@ FONT 8, "MS Shell Dlg"
 BEGIN
     DEFPUSHBUTTON "Tamam", IDOK, 84, 178, 50, 14
     PUSHBUTTON "İptal", IDCANCEL, 138, 178, 50, 14
-    LTEXT "Bu seçenekler, ""İşlemci"" sekmesindeki dikeçlerin hangisinin görüntülenip görüntülenmeyeceğini belirler.", IDC_STATIC, 7, 7, 181, 17
+    LTEXT "Görev Yöneticisi'nin İşlemler sayfasında gözükecek dikeçleri seçiniz.", IDC_STATIC, 7, 7, 181, 17
     CONTROL "Yansıma Adı", IDC_IMAGENAME, "Button", BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP, 7, 28, 56, 10
     CONTROL "PID (İşlem Tanımlayıcı)", IDC_PID, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 39, 88, 10
     CONTROL "CPU Kullanımı", IDC_CPUUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 50, 53, 10
-    CONTROL "CPU Çalışma Süresi", IDC_CPUTIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 61, 48, 10
+    CONTROL "CPU Süresi", IDC_CPUTIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 61, 48, 10
     CONTROL "Bellek Kullanımı", IDC_MEMORYUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 72, 63, 10
     CONTROL "Bellek Kullanım Aralığı", IDC_MEMORYUSAGEDELTA, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 83, 82, 10
     CONTROL "En Yüksek Bellek Kullanımı", IDC_PEAKMEMORYUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 94, 82, 10
@@ -295,14 +295,14 @@ BEGIN
     CONTROL "Farazî Bellek Boyutu", IDC_VIRTUALMEMORYSIZE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 39, 77, 10
     CONTROL "Sayfalanmış Havuz", IDC_PAGEDPOOL, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 50, 53, 10
     CONTROL "Sayfalanmamış Havuz", IDC_NONPAGEDPOOL, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 61, 67, 10
-    CONTROL "Öncelik", IDC_BASEPRIORITY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 72, 55, 10
+    CONTROL "Birinci Öncelik", IDC_BASEPRIORITY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 72, 55, 10
     CONTROL "İşleçler", IDC_HANDLECOUNT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 83, 59, 10
     CONTROL "İş Parçacıkları", IDC_THREADCOUNT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 94, 59, 10
     CONTROL "GDI Nesneleri", IDC_GDIOBJECTS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 105, 55, 10
     CONTROL "G/Ç Yazma", IDC_IOWRITES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 116, 49, 10
     CONTROL "G/Ç Yazma Çokluları", IDC_IOWRITEBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 127, 65, 10
-    CONTROL "G/Ç Diğer", IDC_IOOTHER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 138, 46, 10
-    CONTROL "G/Ç Diğer Çoklular", IDC_IOOTHERBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 149, 65, 10
+    CONTROL "G/Ç Başka", IDC_IOOTHER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 138, 46, 10
+    CONTROL "G/Ç Başka Çoklular", IDC_IOOTHERBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 149, 65, 10
 END
 
 /* String Tables */
@@ -311,64 +311,64 @@ STRINGTABLE
 BEGIN
     IDS_APP_TITLE "Görev Yöneticisi"
     IDC_TASKMGR "Görev Yöneticisi"
-    IDS_IDLE_PROCESS "Çalışmayan İşlemci Yüzdesi İşlemi"
+    IDS_IDLE_PROCESS "Dizge Boşta İşlemi"
 END
 
 STRINGTABLE
 BEGIN
-    ID_FILE_NEW "Yeni görev çalıştırır."
-    ID_OPTIONS_ALWAYSONTOP "Görev Yöneticisi'ni diğer pencerelerin üstünde tutar."
-    ID_OPTIONS_MINIMIZEONUSE "Geçiş yapılırken Görev Yöneticisi'ni simge durumuna küçültür."
+    ID_FILE_NEW "Yeni bir izlence çalıştırır."
+    ID_OPTIONS_ALWAYSONTOP "Simge durumuna küçültülmeden Görev Yöneticisi başka tüm pencerelerin önünde durur."
+    ID_OPTIONS_MINIMIZEONUSE "Geçme işlemi uygulanırken Görev Yöneticisi simge durumuna küçültülür."
     ID_OPTIONS_HIDEWHENMINIMIZED "Görev Yöneticisi simge durumuna küçültüldüğünde Görev Yöneticisi'ni gizler."
-    ID_VIEW_REFRESH "Görev Yöneticisi'ndeki bilgileri yeniler."
-    ID_VIEW_LARGE "Görevleri büyük simgelerle gösterir."
-    ID_VIEW_SMALL "Görevleri küçük simgelerle gösterir."
-    ID_VIEW_DETAILS "Görevleri küçük simgelerle, ayrıntılı olarak gösterir."
-    ID_VIEW_UPDATESPEED_HIGH "Her yarım sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler."
-    ID_VIEW_UPDATESPEED_NORMAL "Her iki sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler."
-    ID_VIEW_UPDATESPEED_LOW "Her dört sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler."
+    ID_VIEW_REFRESH "Yenileme Hızı ayârını önemsemeden Görev Yöneticisi'ni şimdi yenilemeye zorlar."
+    ID_VIEW_LARGE "Görevleri büyük simgeler kullanarak gösterir."
+    ID_VIEW_SMALL "Görevleri küçük simgeler kullanarak gösterir."
+    ID_VIEW_DETAILS "Her bir görev için bilgi görüntüler."
+    ID_VIEW_UPDATESPEED_HIGH "Her sâniyede iki kez görünümü yeniler."
+    ID_VIEW_UPDATESPEED_NORMAL "Her iki sâniyede bir görünümü yeniler."
+    ID_VIEW_UPDATESPEED_LOW "Her dört sâniyede bir görünümü yeniler."
 END
 
 STRINGTABLE
 BEGIN
-    ID_VIEW_UPDATESPEED_PAUSED "Görev Yöneticisi'ndeki bilgilerin kendiliğinden yenilenmesini durdurur."
-    ID_WINDOWS_TILEHORIZONTALLY "Masaüstündeki pencereleri yatay olarak sıralar."
-    ID_WINDOWS_TILEVERTICALLY "Masaüstündeki pencereleri dikey olarak sıralar."
+    ID_VIEW_UPDATESPEED_PAUSED "Kendiliğinden yenilemez."
+    ID_WINDOWS_TILEHORIZONTALLY "Masaüstünde pencereleri yatay olarak döşer."
+    ID_WINDOWS_TILEVERTICALLY "Masaüstünde pencereleri dikey olarak döşer."
     ID_WINDOWS_MINIMIZE "Pencereleri simge durumuna küçültür."
-    ID_WINDOWS_MAXIMIZE "Pencereleri her bir pencerenin görüntülüğü kaplayacağı şekilde büyütür."
-    ID_WINDOWS_CASCADE "Pencereleri masaüstünde çapraz olarak sıralar."
-    ID_WINDOWS_BRINGTOFRONT "Pencereyi öne getirir ancak o pencereye geçiş yapmaz."
-    ID_HELP_TOPICS "Görev Yöneticisi ile ilgili yardım konularını görüntüler."
-    ID_HELP_ABOUT "Görev Yöneticisi ile ilgili bilgi görüntüler."
-    ID_FILE_EXIT "Görev Yöneticisi'nden çıkar."
-    ID_OPTIONS_SHOW16BITTASKS "Farazî DOS Makinesi (ntvdm.exe) altında çalışan 16 bitlik uygulamaları da görüntüler."
-    ID_VIEW_SELECTCOLUMNS """İşlemler"" sekmesinde hangi dikeçlerin görüntülenip görüntülenmeyeceğini belirler."
-    ID_VIEW_SHOWKERNELTIMES "İşlemci çizgelerinde çekirdek zamanlarını gösterir."
-    ID_VIEW_CPUHISTORY_ONEGRAPHALL "Toplam CPU kullanımını tek çizgede gösterir."
-    ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Her CPU'nun kullanımını ayrı çizgelerde gösterir."
-    ID_APPLICATION_PAGE_SWITCHTO "Seçilen görevi öne getirip o göreve odaklatır."
+    ID_WINDOWS_MAXIMIZE "Pencereleri büyütür."
+    ID_WINDOWS_CASCADE "Masaüstünde pencereleri çapraz olarak basamaklar."
+    ID_WINDOWS_BRINGTOFRONT "Pencereyi öne getirir ancak ona geçmez."
+    ID_HELP_TOPICS "Görev Yöneticisi yardım konularını görüntüler."
+    ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler."
+    ID_FILE_EXIT "Görev Yöneticisi uygulamasından çıkar."
+    ID_OPTIONS_SHOW16BITTASKS "İlişkili ntvdm.exe altındaki 16 bitlik görevleri gösterir."
+    ID_VIEW_SELECTCOLUMNS "İşlemler sayfasında hangi dikeçlerin görünür olacağını seçer."
+    ID_VIEW_SHOWKERNELTIMES "Başarım çizgelerinde çekirdek sürelerini görüntüler."
+    ID_VIEW_CPUHISTORY_ONEGRAPHALL "Bir bayağı geçmiş çizgesi toplam CPU kullanımını gösterir."
+    ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Her bir CPU'nun kendi geçmiş çizgesi vardır."
+    ID_APPLICATION_PAGE_SWITCHTO "Bir görevi ön plana getirir, o göreve odaklatır."
 END
 
 STRINGTABLE
 BEGIN
-    ID_ENDTASK "Seçili görevi sonlandırmaya çalışır."
-    ID_GOTOPROCESS "Seçili görevin işlemine gider."
-    ID_RESTORE "Görev Yöneticisi'ni gizli olmaktan çıkarır."
-    ID_PROCESS_PAGE_ENDPROCESS "Seçili işlemi sonlandırır."
-    ID_PROCESS_PAGE_ENDPROCESSTREE "Seçili işlemi ve bu işlemin bağlı olduğu tüm işlemleri sonlandırır."
-    ID_PROCESS_PAGE_DEBUG "Seçili işleme bir yanlışlık ayıklayıcı bağlar."
-    ID_PROCESS_PAGE_SETAFFINITY "Seçili işlemin hangi CPU'larla yürütüleceğini belirler."
-    ID_PROCESS_PAGE_SETPRIORITY_REALTIME "Seçili işlemin öncelik sırasını EŞ ZAMANLI yapar."
-    ID_PROCESS_PAGE_SETPRIORITY_HIGH "Seçili işlemin öncelik sırasını YÜKSEK yapar."
-    ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL "Seçili işlemin öncelik sırasını ORTA-YÜKSEK yapar."
-    ID_PROCESS_PAGE_SETPRIORITY_NORMAL "Seçili işlemin öncelik sırasını ORTA yapar."
-    ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Seçili işlemin öncelik sırasını ORTA-DÜŞÜK yapar."
-    ID_PROCESS_PAGE_SETPRIORITY_LOW "Seçili işlemin öncelik sırasını DÜŞÜK yapar."
+    ID_ENDTASK "Seçilen görevleri sonlandırmayı bildirir."
+    ID_GOTOPROCESS "Seçilen görevin işlemine odaklatır."
+    ID_RESTORE "Görev Yöneticisi'ni gizli durumdan döndürür."
+    ID_PROCESS_PAGE_ENDPROCESS "İşlemi dizgeden siler."
+    ID_PROCESS_PAGE_ENDPROCESSTREE "Bu işlemi ve tüm astlarını bu dizgeden sonlandırır."
+    ID_PROCESS_PAGE_DEBUG "Bu işleme yanlışlık ayıklayıcı bağlar."
+    ID_PROCESS_PAGE_SETAFFINITY "İşleme hangi CPU'ların üzerinde çalışmasına izin verileceğini denetler."
+    ID_PROCESS_PAGE_SETPRIORITY_REALTIME "İşlemi EŞ ZAMANLI öncelik sınıfına getirir."
+    ID_PROCESS_PAGE_SETPRIORITY_HIGH "İşlemi YÜKSEK öncelik sınıfına getirir."
+    ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL "İşlemi DÜZGÜLÜ ÜSTÜ öncelik sınıfına getirir."
+    ID_PROCESS_PAGE_SETPRIORITY_NORMAL "İşlemi DÜZGÜLÜ öncelik sınıfına getirir."
+    ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "İşlemi DÜZGÜLÜ ALTI öncelik sınıfına getirir."
+    ID_PROCESS_PAGE_SETPRIORITY_LOW "İşlemi DÜŞÜK öncelik sınıfına getirir."
 END
 
 STRINGTABLE
 BEGIN
-    IDS_TAB_APPS "Görevler"
+    IDS_TAB_APPS "Uygulamalar"
     IDS_TAB_PROCESSES "İşlemler"
     IDS_TAB_PERFORMANCE "Başarım"
     IDS_TAB_TASK "Görev"
@@ -378,7 +378,7 @@ BEGIN
     IDS_TAB_USERNAME "Kullanıcı Adı"
     IDS_TAB_SESSIONID "Oturum Kimliği"
     IDS_TAB_CPU "CPU Kullanımı"
-    IDS_TAB_CPUTIME "CPU Çalışma Süresi"
+    IDS_TAB_CPUTIME "CPU Süresi"
     IDS_TAB_MEMUSAGE "Bellek Kullanımı"
     IDS_TAB_PEAKMEMUSAGE "En Yüksek Bellek Kullanımı"
     IDS_TAB_MEMDELTA "Bellek Kullanım Aralığı"
@@ -387,43 +387,43 @@ BEGIN
     IDS_TAB_VMSIZE "Farazî Bellek Boyutu"
     IDS_TAB_PAGEDPOOL "Sayfalanmış Havuz"
     IDS_TAB_NPPOOL "Sayfalanmamış Havuz"
-    IDS_TAB_BASEPRI "Öncelik"
+    IDS_TAB_BASEPRI "Birinci Öncelik"
     IDS_TAB_HANDLES "İşleçler"
     IDS_TAB_THREADS "İş Parçacıkları"
     IDS_TAB_USERPBJECTS "Kullanıcı Nesneleri"
     IDS_TAB_GDIOBJECTS "GDI Nesneleri"
     IDS_TAB_IOREADS "G/Ç Okuma"
     IDS_TAB_IOWRITES "G/Ç Yazma"
-    IDS_TAB_IOOTHER "G/Ç Diğer"
+    IDS_TAB_IOOTHER "G/Ç Başka"
     IDS_TAB_IOREADBYTES "G/Ç Okuma Çokluları"
     IDS_TAB_IOWRITESBYTES "G/Ç Yazma Çokluları"
-    IDS_TAB_IOOTHERBYTES "G/Ç Diğer Çoklular"
+    IDS_TAB_IOOTHERBYTES "G/Ç Başka Çoklular"
     IDS_MENU_SELECTCOLUMNS "&Dikeçleri Seç..."
     IDS_MENU_16BITTASK "&16 Bitlik Görevleri Göster"
     IDS_MENU_WINDOWS "&Pencereler"
     IDS_MENU_LARGEICONS "&Büyük Simgeler"
     IDS_MENU_SMALLICONS "&Küçük Simgeler"
     IDS_MENU_DETAILS "&Ayrıntılar"
-    IDS_MENU_ONEGRAPHALLCPUS "&Tüm CPU'lar İçin Aynı Çizge"
-    IDS_MENU_ONEGRAPHPERCPU "&Her CPU'ya Birer Çizge"
+    IDS_MENU_ONEGRAPHALLCPUS "&Tek Çizge, Tüm CPU'lar"
+    IDS_MENU_ONEGRAPHPERCPU "&CPU Başına Bir Çizge"
     IDS_MENU_CPUHISTORY "&CPU Geçmişi"
-    IDS_MENU_SHOWKERNELTIMES "&Çekirdek Zamanlarını Göster"
+    IDS_MENU_SHOWKERNELTIMES "&Çekirdek Sürelerini Göster"
     IDS_CREATENEWTASK "Yeni Görev Oluşturma"
-    IDS_CREATENEWTASK_DESC "Çalıştırılacak görevin konumunu yazınız:"
-    IDS_MSG_ACCESSPROCESSAFF "CPU'larla ilişkisi erişilemez veyâ değiştirilemez."
-    IDS_MSG_PROCESSONEPRO "Herhangi bir işlem, en az bir CPU ile ilişkili olmalıdır."
-    IDS_MSG_INVALIDOPTION "Geçersiz seçenek."
-    IDS_MSG_UNABLEDEBUGPROCESS "Yanlışlık ayıklama işlemi yapılamaz."
-    IDS_MSG_WARNINGDEBUG "UYARI: Bu işlemde yanlışlık ayıklama, veri yitimine neden olabilir.\nBu işleme bir yanlışlık ayıklayıcı bağlamayı doğruluyor musunuz?"
-    IDS_MSG_TASKMGRWARNING "Uyarı"
-    IDS_MSG_WARNINGTERMINATING "UYARI: Bir işlemin sonlandırılması, dizge\nkararsızlığı veyâ veri yitimi gibi istenmeyen durumlara neden olabilir. Bu\nişlemi sonlandırmayı doğruluyor musunuz?"
-    IDS_MSG_UNABLETERMINATEPRO "İşlem sonlandırma yapılamaz."
-    IDS_MSG_UNABLECHANGEPRIORITY "İşlemci önceliği değiştirilemez."
-    IDS_MSG_WARNINGCHANGEPRIORITY "UYARI: İşlemci önceliğinin değiştirilmesi, dizge\nkararsızlığı gibi istenmeyen durumlara neden olabilir. Bu işlemin\nişlemci önceliğini değiştirmeyi doğruluyor musunuz?"
+    IDS_CREATENEWTASK_DESC "Bir izlencenin, bir dizinin, bir belgenin veyâ bir Umûmî Ağ kaynağının adını yazınız, Görev Yöneticisi onu sizin için açacaktır."
+    IDS_MSG_ACCESSPROCESSAFF "İşlemci İlişkisinin Erişilememesi veyâ Ayarlanamaması"
+    IDS_MSG_PROCESSONEPRO "İşlem en azından bir işlemciyle ilişkisi olmalıdır."
+    IDS_MSG_INVALIDOPTION "Geçersiz Seçenek"
+    IDS_MSG_UNABLEDEBUGPROCESS "Yanlışlık Ayıklama İşleminin Yapılamaması"
+    IDS_MSG_WARNINGDEBUG "UYARI: Bu işlemde yanlışlık ayıklama veri yitimiyle sonuçlanabilir.\nYanlışlık ayıklayıcı bağlamak istediğinizi doğruluyor musunuz?"
+    IDS_MSG_TASKMGRWARNING "Görev Yöneticisi Uyarısı"
+    IDS_MSG_WARNINGTERMINATING "UYARI: Bir işlemin sonlandırılması, veri\nyitimi ve dizge kararsızlığını içeren istenmeyen sonuçlara neden\nolabilir. İşlem sonlandırılmadan önce durumunu veyâ verisini\nkaydetme fırsatı verilmeyecektir. İşlemi\nsonlandırmak istediğinizi doğruluyor musunuz?"
+    IDS_MSG_UNABLETERMINATEPRO "İşlem Sonlandırmanın Yapılamaması"
+    IDS_MSG_UNABLECHANGEPRIORITY "Önceliğin Değiştirilememesi"
+    IDS_MSG_WARNINGCHANGEPRIORITY "UYARI: Bu işlemin öncelik sınıfının değiştirilmesi, dizge\nkararsızlığını içeren istenmeyen sonuçlara neden olabilir. Öncelik \nsınıfını değiştirmek istediğinizi doğruluyor musunuz?"
     IDS_MSG_TRAYICONCPUUSAGE "CPU Kullanımı: %%%d"
     IDS_STATUS_MEMUSAGE "Bellek Kullanımı: %d KB / %d KB"
     IDS_STATUS_CPUUSAGE "CPU Kullanımı: %%%3d"
-    IDS_STATUS_PROCESSES "İşlem Sayısı: %d"
+    IDS_STATUS_PROCESSES "İşlem: %d"
     IDS_Not_Responding "Yanıt Vermiyor"
     IDS_Running "Çalışıyor"
 END
index b7860ff..0468cd7 100644 (file)
@@ -7,9 +7,9 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS
 CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "ReactOS Kur'a Hoşgeldiniz.", IDC_STARTTITLE, 115, 8, 195, 24
-    LTEXT "Daha bu CD'den ReactOS'u doğrudan kuramazsınız. Bu CD'den ReactOS'u kurmak için bilgisayarınızı yeniden başlatınız.", IDC_STATIC, 115, 40, 195, 100
-    LTEXT "Kur'dan çıkmak için ""İptal"" düğmesine tıklayınız.", IDC_STATIC, 115, 169, 195, 17
+    LTEXT "ReactOS Kur Büyücüsü'ne Hoşgeldiniz", IDC_STARTTITLE, 115, 8, 195, 24
+    LTEXT "Daha bu CD'den ReactOS'u doğrudan kuramazsınız. Lütfen ReactOS'u kurmak için bu CD'den bilgisayarınızı yeniden başlatınız.", IDC_STATIC, 115, 40, 195, 100
+    LTEXT "Kur'dan çıkmak için İptal'e tıklayınız.", IDC_STATIC, 115, 169, 195, 17
 END
 
 IDD_LANGSELPAGE DIALOGEX 0, 0, 317, 193
@@ -20,9 +20,9 @@ BEGIN
     CONTROL "IDB_LOGO", IDB_ROSLOGO, "Static", WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 18, 0, 290, 99
     CONTROL "Kurulum Dili:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 109, 106, 11
     CONTROL "", IDC_LANGUAGES, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 132, 107, 176, 142
-    CONTROL "Düğme Takımı Düzeni:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 142, 106, 11
+    CONTROL "Düğme Takımı Giriş Yöntemi:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 142, 106, 11
     CONTROL "", IDC_KEYLAYOUT, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 132, 141, 176, 81
-    LTEXT "Kurulum türünü seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 10
+    LTEXT "Kurulum türünü seçmek için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 297, 10
 END
 
 IDD_TYPEPAGE DIALOGEX 0, 0, 317, 193
@@ -32,8 +32,8 @@ FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "Kurulum Türü", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172
     CONTROL "ReactOS'u Yükleme", IDC_INSTALL, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 20, 15, 277, 10
-    CONTROL "ReactOS'u Onarma ya da Yükseltme", IDC_SETUP, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 20, 30, 277, 10
-    LTEXT "Aygıt seçeneklerini seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 10
+    CONTROL "Kurulu ReactOS'u Onarma ya da Yükseltme", IDC_SETUP, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 20, 30, 277, 10
+    LTEXT "Aygıtları kurmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 297, 10
 END
 
 IDD_DEVICEPAGE DIALOGEX 0, 0, 317, 193
@@ -41,14 +41,14 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS
 CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    CONTROL "Aygıt Seçenekleri", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172
-    LTEXT "Bilgisayar Türü:", IDC_STATIC, 20, 15, 80, 10
+    CONTROL "Aygıt Ayarları", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172
+    LTEXT "Bilgisayar:", IDC_STATIC, 20, 15, 80, 10
     CONTROL "", IDC_COMPUTER, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 15, 180, 80
-    LTEXT "Görüntü Ayarları:", IDC_STATIC, 20, 35, 80, 10
+    LTEXT "Görüntü:", IDC_STATIC, 20, 35, 80, 10
     CONTROL "", IDC_DISPLAY, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 35, 180, 80
-    LTEXT "Düğme Takımı Türü:", IDC_STATIC, 20, 55, 80, 10
+    LTEXT "Düğme Takımı:", IDC_STATIC, 20, 55, 80, 10
     CONTROL "", IDC_KEYBOARD, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 55, 180, 80
-    LTEXT "Kurulum yapılacak bölümü seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20
+    LTEXT "Kurulum aygıtını kurmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20
 END
 
 IDD_DRIVEPAGE DIALOGEX 0, 0, 317, 193
@@ -56,13 +56,13 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS
 CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    CONTROL "ReactOS'un Kurulacağı Bölüm", IDC_STATIC, "Button", BS_GROUPBOX, 10, 1, 298, 176
+    CONTROL "ReactOS Kurulumu İçin Bölümlendirme", IDC_STATIC, "Button", BS_GROUPBOX, 10, 1, 298, 176
     LISTBOX IDC_PARTITION, 20, 12, 278, 142, LBS_HASSTRINGS | WS_VSCROLL
     PUSHBUTTON "&Oluştur...", IDC_PARTCREATE, 20, 155, 50, 15
     PUSHBUTTON "&Sil", IDC_PARTDELETE, 76, 155, 50, 15
     PUSHBUTTON "S&ürücü", IDC_DEVICEDRIVER, 162, 155, 50, 15, WS_DISABLED
     PUSHBUTTON "G&elişmiş Seçenekler...", IDC_PARTMOREOPTS, 218, 155, 80, 15
-    LTEXT "Kurulum özetini görmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20
+    LTEXT "Kurulum özetini gözden geçirmek için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20
 END
 
 IDD_PARTITION DIALOGEX 0, 0, 145, 90
@@ -71,7 +71,7 @@ CAPTION "Bölüm Oluşturma"
 FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "", IDC_UPDOWN1, "msctls_updown32", WS_VISIBLE, 104, 22, 9, 13
-    CONTROL "Bölüm Oluşturma", IDC_STATIC, "Button", BS_GROUPBOX, 7, 5, 129, 57
+    CONTROL "Bölüm Oluşturma ve Biçimlendirme", IDC_STATIC, "Button", BS_GROUPBOX, 7, 5, 129, 57
     LTEXT "Büyüklük:", IDC_STATIC, 13, 24, 27, 9
     EDITTEXT IDC_PARTSIZE, 52, 23, 53, 13, WS_VISIBLE | WS_TABSTOP
     LTEXT "GB", IDC_UNIT, 117, 24, 14, 9
@@ -83,15 +83,15 @@ END
 
 IDD_BOOTOPTIONS DIALOGEX 0, 0, 305, 116
 STYLE WS_VISIBLE | WS_CAPTION
-CAPTION "Gelişmiş Seçenekler"
+CAPTION "Gelişmiş Bölümlendirme Seçenekleri"
 FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "Kurulum Dizini", IDC_STATIC, "Button", BS_GROUPBOX, 4, 1, 298, 30
     EDITTEXT IDC_PATH, 10, 11, 278, 13, WS_VISIBLE
-    CONTROL "Önyükleyici Kurulumu", IDC_STATIC, "Button", BS_GROUPBOX, 4, 36, 298, 52
-    CONTROL "Önyükleyici, diskin MBR'sine ve VBR'sine kurulsun.", IDC_INSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 46, 278, 11
-    CONTROL "Önyükleyici, diskin yalnızca VBR'sine kurulsun.", IDC_INSTVBRONLY, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 57, 278, 11
-    CONTROL "Önyükleyici kurulmasın.", IDC_NOINSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 10, 68, 278, 11
+    CONTROL "Ön Yükleyici Kurulumu", IDC_STATIC, "Button", BS_GROUPBOX, 4, 36, 298, 52
+    CONTROL "Ön yükleyiciyi diskin üzerine kur. (MBR ve VBR)", IDC_INSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 46, 278, 11
+    CONTROL "Ön yükleyiciyi diskin üzerine kur. (Yalnızca VBR)", IDC_INSTVBRONLY, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 57, 278, 11
+    CONTROL "Ön yükleyici kurulumu yok.", IDC_NOINSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 10, 68, 278, 11
     PUSHBUTTON "Tamam", IDOK, 180, 94, 50, 15, WS_TABSTOP | WS_VISIBLE
     PUSHBUTTON "İptal", IDCANCEL, 240, 94, 50, 15, WS_TABSTOP | WS_VISIBLE
 END
@@ -102,7 +102,7 @@ CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "Kurulum Özeti", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172
-    LTEXT "Kurulumu başlatmak için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20
+    LTEXT "Kurulumu işlemini başlatmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20
 END
 
 IDD_PROCESSPAGE DIALOGEX 0, 0, 317, 193
@@ -110,7 +110,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS
 CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    CONTROL "Kurulum Süreci", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172
+    CONTROL "Kurulum İşlemi", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172
     LTEXT "Kütükler yükleniyor...", IDC_ACTIVITY, 20, 50, 277, 10
     LTEXT "sınama.txt", IDC_ITEM, 30, 80, 257, 10
     CONTROL "", IDC_PROCESSPROGRESS, "msctls_progress32", PBS_SMOOTH | WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 120, 277, 8
@@ -118,32 +118,32 @@ END
 
 IDD_RESTARTPAGE DIALOGEX 0, 0, 317, 193
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "ReactOS Kur"
+CAPTION "ReactOS Kurulumunun Bitirilmesi"
 FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "ReactOS Kurulumunun İlk Aşaması Bitmesi", IDC_FINISHTITLE, "Button", BS_GROUPBOX, 10, 0, 297, 172
-    LTEXT "ReactOS kurulumunun ilk aşaması bitti.", IDC_STATIC, 20, 50, 277, 10
-    LTEXT """Bitir"" düğmesine bastığınızda bilgisayarınız yeniden başlatılacak.", IDC_STATIC, 20, 80, 277, 10
+    LTEXT "ReactOS kurulumunun ilk aşamasını başarılı bir şekilde bitirdiniz.", IDC_STATIC, 20, 50, 277, 10
+    LTEXT "Bitir'e tıkladığınızda bilgisayarınız yeniden başlatılacaktır.", IDC_STATIC, 20, 80, 277, 10
     CONTROL "", IDC_RESTART_PROGRESS, "msctls_progress32", PBS_SMOOTH | WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 120, 277, 8
-    LTEXT "Eğer bilgisayarınızda takılı bir CD varsa onu çıkarttığınızdan sonra ""Bitir"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 20
+    LTEXT "Eğer bir sürücüde bir CD varsa onu çıkartınız. Sonra, bilgisayarınızı yeniden başlatmak için Bitir'e tıklayınız.", IDC_STATIC, 10, 180, 297, 20
 END
 
 STRINGTABLE
 BEGIN
     IDS_LANGTITLE "Dil Seçimi"
-    IDS_LANGSUBTITLE "Kurulum ve dizge dilini seçiniz."
+    IDS_LANGSUBTITLE "Kurulum ve son dizge dilini seçiniz."
     IDS_TYPETITLE "ReactOS Kur'a Hoşgeldiniz"
     IDS_TYPESUBTITLE "Kurulum türünü seçiniz."
-    IDS_DEVICETITLE "Aygıt Seçeneklerinin Seçilmesi"
-    IDS_DEVICESUBTITLE "Görüntü ayarlarını ve düğme takımı türünü seçiniz."
-    IDS_DRIVETITLE "Kurulum Yapılacak Bölümün Seçilmesi"
-    IDS_DRIVESUBTITLE "Kurulum yapılacak bölümü, kurulum dizinini ve önyükleyici seçeneklerini seçiniz."
+    IDS_DEVICETITLE "Ana Aygıtların Kurulumu"
+    IDS_DEVICESUBTITLE "Görüntü ve düğme takımı ayarlarını yapınız."
+    IDS_DRIVETITLE "Kurulum Bölümünün ve Dizge Dizininin Anıklanması"
+    IDS_DRIVESUBTITLE "Kurulum bölümünü, dizge dizinini ve ön yükleyiciyi anıklayınız."
     IDS_PROCESSTITLE "Bölümün Biçimlendirilmesi, Kütüklerin Çoğaltılması ve Önyükleyicinin Kurulması"
-    IDS_PROCESSSUBTITLE "Bölüm biçimlendiriliyor, kütükler çoğaltılıyor ve önyükleyici kuruluyor."
-    IDS_RESTARTTITLE "Kurulumun İlk Aşamasının Bitmesi"
-    IDS_RESTARTSUBTITLE "Kurulumun ilk aşaması bitti. İkincisine geçmek için bilgisayarı yeniden başlatınız."
+    IDS_PROCESSSUBTITLE "Bölüm oluşturuluyor ve biçimlendiriliyor, kütükler çoğaltılıyor, ön yükleyici kuruluyor ve anıklanıyor."
+    IDS_RESTARTTITLE "Kurulumun İlk Aşaması Bitti"
+    IDS_RESTARTSUBTITLE "Kurulumun ilk aşaması bitirildi, ikinci aşamayla sürdürmek için yeniden başlatınız."
     IDS_SUMMARYTITLE "Kurulum Özeti"
-    IDS_SUMMARYSUBTITLE "Kurulumdan önce, dizelgelenen kurulum seçeneklerini gözden geçiriniz."
-    IDS_ABORTSETUP "ReactOS kurulumu bitmedi. Eğer Kur'dan çıkarsanız, ReactOS'u kurmak için Kur'u yeniden çalıştırabilirsiniz. Çıkmayı doğruluyor musunuz?"
+    IDS_SUMMARYSUBTITLE "Kurulumdan aygıtına uygulanmadan önce gözden geçirmek için dizelgelenen kurulum seçenekleri."
+    IDS_ABORTSETUP "ReactOS bilgisayarınıza tümüyle kurulmadı. Eğer şimdi Kur'dan çıkarsanız, ReactOS'u kurmak için Kur'u yeniden çalıştırmayı isteybilirsiniz. Gerçekten çıkılsın mı?"
     IDS_ABORTSETUP2 "Kurulum iptal edilsin mi?"
 END
index 84b31a1..3fb5b36 100644 (file)
@@ -78,12 +78,12 @@ IDB_ROSLOGO BITMAP "res/rosbitmap.bmp"
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
-#ifdef LANGUAGE_TR_TR
-    #include "lang/tr-TR.rc"
-#endif
 #ifdef LANGUAGE_SQ_AL
     #include "lang/sq-AL.rc"
 #endif
+#ifdef LANGUAGE_TR_TR
+    #include "lang/tr-TR.rc"
+#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index 9865e26..74d5ad3 100644 (file)
@@ -87,7 +87,8 @@ extern PPARTLIST PartitionList;
 
 static
 VOID
-CreateCommonFreeLoaderSections(PINICACHE IniCache)
+CreateCommonFreeLoaderSections(
+    PINICACHE IniCache)
 {
     PINICACHESECTION IniSection;
 
@@ -1178,7 +1179,6 @@ InstallMbrBootCodeToDisk(
         return Status;
     }
 
-
     /* Allocate buffer for new bootsector */
     NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
                     0,
@@ -1275,9 +1275,11 @@ InstallMbrBootCodeToDisk(
     return Status;
 }
 
+
 NTSTATUS
-InstallFat12BootCodeToFloppy(PWSTR SrcPath,
-                             PWSTR RootPath)
+InstallFat12BootCodeToFloppy(
+    PWSTR SrcPath,
+    PWSTR RootPath)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK IoStatusBlock;
@@ -1286,21 +1288,21 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
     NTSTATUS Status;
     PFAT_BOOTSECTOR OrigBootSector;
     PFAT_BOOTSECTOR NewBootSector;
-    
+
     /* Allocate buffer for original bootsector */
     OrigBootSector = 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,
                         GENERIC_READ | SYNCHRONIZE,
                         &ObjectAttributes,
@@ -1312,7 +1314,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
         return Status;
     }
-    
+
     Status = NtReadFile(FileHandle,
                         NULL,
                         NULL,
@@ -1328,8 +1330,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
         return Status;
     }
-    
-    
+
     /* Allocate buffer for new bootsector */
     NewBootSector = RtlAllocateHeap(ProcessHeap,
                                     0,
@@ -1339,16 +1340,16 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         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,
                         GENERIC_READ | SYNCHRONIZE,
                         &ObjectAttributes,
@@ -1361,7 +1362,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         RtlFreeHeap(ProcessHeap, 0, NewBootSector);
         return Status;
     }
-    
+
     Status = NtReadFile(FileHandle,
                         NULL,
                         NULL,
@@ -1378,25 +1379,25 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         RtlFreeHeap(ProcessHeap, 0, NewBootSector);
         return Status;
     }
-    
+
     /* Adjust bootsector (copy a part of the FAT16 BPB) */
     memcpy(&NewBootSector->OemName,
            &OrigBootSector->OemName,
            FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
            FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
-    
+
     /* Free the original boot sector */
     RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
-    
+
     /* Write new bootsector to RootPath */
     RtlInitUnicodeString(&Name, RootPath);
-    
+
     InitializeObjectAttributes(&ObjectAttributes,
                                &Name,
                                0,
                                NULL,
                                NULL);
-    
+
     Status = NtOpenFile(&FileHandle,
                         GENERIC_WRITE | SYNCHRONIZE,
                         &ObjectAttributes,
@@ -1409,7 +1410,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
         RtlFreeHeap(ProcessHeap, 0, NewBootSector);
         return Status;
     }
-    
+
 #if 0
     FilePosition.QuadPart = 0;
 #endif
@@ -1423,10 +1424,10 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath,
                          NULL,
                          NULL);
     NtClose(FileHandle);
-    
+
     /* Free the new boot sector */
     RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-    
+
     return Status;
 }
 
@@ -1487,7 +1488,6 @@ InstallFat16BootCodeToDisk(
         return Status;
     }
 
-
     /* Allocate buffer for new bootsector */
     NewBootSector = RtlAllocateHeap(ProcessHeap,
                                     0,
@@ -2001,6 +2001,7 @@ UpdateBootIni(
     return Status;
 }
 
+
 BOOLEAN
 CheckInstallFatBootcodeToPartition(
     PUNICODE_STRING SystemRootPath)
@@ -2339,6 +2340,7 @@ InstallFatBootcodeToPartition(
 #endif
 }
 
+
 NTSTATUS
 InstallVBRToPartition(
     PUNICODE_STRING SystemRootPath,
@@ -2373,7 +2375,7 @@ InstallFatBootcodeToFloppy(
     WCHAR SrcPath[MAX_PATH];
     WCHAR DstPath[MAX_PATH];
     NTSTATUS Status;
-    
+
     /* Format the floppy first */
     Status = VfatFormat(&FloppyDevice,
                         FMIFS_FLOPPY,
index 33b983a..6322bae 100644 (file)
 #pragma once
 
 NTSTATUS
-CreateFreeLoaderIniForDos(PWCHAR IniPath,
-                         PWCHAR ArcPath);
+CreateFreeLoaderIniForDos(
+    PWCHAR IniPath,
+    PWCHAR ArcPath);
 
 NTSTATUS
-CreateFreeLoaderIniForReactos(PWCHAR IniPath,
-                             PWCHAR ArcPath);
+CreateFreeLoaderIniForReactos(
+    PWCHAR IniPath,
+    PWCHAR ArcPath);
 
 NTSTATUS
-UpdateFreeLoaderIni(PWCHAR IniPath,
-                   PWCHAR ArcPath);
+UpdateFreeLoaderIni(
+    PWCHAR IniPath,
+    PWCHAR ArcPath);
 
 NTSTATUS
-SaveCurrentBootSector(PWSTR RootPath,
-                     PWSTR DstPath);
+SaveCurrentBootSector(
+    PWSTR RootPath,
+    PWSTR DstPath);
 
 NTSTATUS
-InstallFat16BootCodeToFile(PWSTR SrcPath,
-                          PWSTR DstPath,
-                          PWSTR RootPath);
+InstallFat16BootCodeToFile(
+    PWSTR SrcPath,
+    PWSTR DstPath,
+    PWSTR RootPath);
 
 NTSTATUS
-InstallFat32BootCodeToFile(PWSTR SrcPath,
-                          PWSTR DstPath,
-                          PWSTR RootPath);
+InstallFat32BootCodeToFile(
+    PWSTR SrcPath,
+    PWSTR DstPath,
+    PWSTR RootPath);
 
 NTSTATUS
-InstallMbrBootCodeToDisk (PWSTR SrcPath,
-                         PWSTR RootPath);
+InstallMbrBootCodeToDisk(
+    PWSTR SrcPath,
+    PWSTR RootPath);
 
 NTSTATUS
-InstallFat16BootCodeToDisk(PWSTR SrcPath,
-                          PWSTR RootPath);
+InstallFat16BootCodeToDisk(
+    PWSTR SrcPath,
+    PWSTR RootPath);
 
 NTSTATUS
-InstallFat32BootCodeToDisk(PWSTR SrcPath,
-                          PWSTR RootPath);
+InstallFat32BootCodeToDisk(
+    PWSTR SrcPath,
+    PWSTR RootPath);
 
 NTSTATUS
-UpdateBootIni(PWSTR BootIniPath,
-             PWSTR EntryName,
-             PWSTR EntryValue);
+UpdateBootIni(
+    PWSTR BootIniPath,
+    PWSTR EntryName,
+    PWSTR EntryValue);
 
 BOOLEAN
-CheckInstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath);
+CheckInstallFatBootcodeToPartition(
+    PUNICODE_STRING SystemRootPath);
 
 NTSTATUS
-InstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath,
-                             PUNICODE_STRING SourceRootPath,
-                             PUNICODE_STRING DestinationArcPath,
-                             UCHAR PartitionType);
+InstallFatBootcodeToPartition(
+    PUNICODE_STRING SystemRootPath,
+    PUNICODE_STRING SourceRootPath,
+    PUNICODE_STRING DestinationArcPath,
+    UCHAR PartitionType);
 
 NTSTATUS
-InstallVBRToPartition(PUNICODE_STRING SystemRootPath,
-                      PUNICODE_STRING SourceRootPath,
-                      PUNICODE_STRING DestinationArcPath,
-                      UCHAR PartitionType);
+InstallVBRToPartition(
+    PUNICODE_STRING SystemRootPath,
+    PUNICODE_STRING SourceRootPath,
+    PUNICODE_STRING DestinationArcPath,
+    UCHAR PartitionType);
 
 NTSTATUS
-InstallFatBootcodeToFloppy(PUNICODE_STRING SourceRootPath,
-                          PUNICODE_STRING DestinationArcPath);
+InstallFatBootcodeToFloppy(
+    PUNICODE_STRING SourceRootPath,
+    PUNICODE_STRING DestinationArcPath);
 
 /* EOF */
index 03054bc..2c5522c 100644 (file)
@@ -34,7 +34,9 @@ static PPROGRESSBAR ChkdskProgressBar = NULL;
 
 /* FUNCTIONS ****************************************************************/
 
-static BOOLEAN NTAPI
+static
+BOOLEAN
+NTAPI
 ChkdskCallback(
     IN CALLBACKCOMMAND Command,
     IN ULONG Modifier,
@@ -50,6 +52,7 @@ ChkdskCallback(
     return TRUE;
 }
 
+
 NTSTATUS
 ChkdskPartition(
     IN PUNICODE_STRING DriveRoot,
index a910e93..b573430 100644 (file)
 /* FUNCTIONS ****************************************************************/
 
 NTSTATUS
-GetSourcePaths(PUNICODE_STRING SourcePath,
-              PUNICODE_STRING SourceRootPath,
-              PUNICODE_STRING SourceRootDir)
+GetSourcePaths(
+    PUNICODE_STRING SourcePath,
+    PUNICODE_STRING SourceRootPath,
+    PUNICODE_STRING SourceRootDir)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING LinkName;
-  UNICODE_STRING SourceName;
-  WCHAR SourceBuffer[MAX_PATH] = {L'\0'};
-  HANDLE Handle;
-  NTSTATUS Status;
-  ULONG Length;
-  PWCHAR Ptr;
-
-  RtlInitUnicodeString(&LinkName,
-                      L"\\SystemRoot");
-
-  InitializeObjectAttributes(&ObjectAttributes,
-                            &LinkName,
-                            OBJ_CASE_INSENSITIVE,
-                            NULL,
-                            NULL);
-
-  Status = NtOpenSymbolicLinkObject(&Handle,
-                                   SYMBOLIC_LINK_ALL_ACCESS,
-                                   &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-    return(Status);
-
-  SourceName.Length = 0;
-  SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR);
-  SourceName.Buffer = SourceBuffer;
-
-  Status = NtQuerySymbolicLinkObject(Handle,
-                                    &SourceName,
-                                    &Length);
-  NtClose(Handle);
-
-  if (NT_SUCCESS(Status))
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING LinkName;
+    UNICODE_STRING SourceName;
+    WCHAR SourceBuffer[MAX_PATH] = {L'\0'};
+    HANDLE Handle;
+    NTSTATUS Status;
+    ULONG Length;
+    PWCHAR Ptr;
+
+    RtlInitUnicodeString(&LinkName,
+                         L"\\SystemRoot");
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenSymbolicLinkObject(&Handle,
+                                      SYMBOLIC_LINK_ALL_ACCESS,
+                                      &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    SourceName.Length = 0;
+    SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR);
+    SourceName.Buffer = SourceBuffer;
+
+    Status = NtQuerySymbolicLinkObject(Handle,
+                                       &SourceName,
+                                       &Length);
+    NtClose(Handle);
+
+    if (NT_SUCCESS(Status))
     {
-      RtlCreateUnicodeString(SourcePath,
-                             SourceName.Buffer);
-
-      /* strip trailing directory */
-      Ptr = wcsrchr(SourceName.Buffer, L'\\');
-      if (Ptr)
-      {
-          RtlCreateUnicodeString(SourceRootDir, Ptr);
-          *Ptr = 0;
-      }
-      else
-          RtlCreateUnicodeString(SourceRootDir, L"");
-
-      RtlCreateUnicodeString(SourceRootPath,
-                             SourceName.Buffer);
+        RtlCreateUnicodeString(SourcePath,
+                               SourceName.Buffer);
+
+        /* strip trailing directory */
+        Ptr = wcsrchr(SourceName.Buffer, L'\\');
+        if (Ptr)
+        {
+            RtlCreateUnicodeString(SourceRootDir, Ptr);
+            *Ptr = 0;
+        }
+        else
+            RtlCreateUnicodeString(SourceRootDir, L"");
+
+        RtlCreateUnicodeString(SourceRootPath,
+                               SourceName.Buffer);
     }
 
-  NtClose(Handle);
+    NtClose(Handle);
 
-  return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
-
 /* EOF */
index 37c918c..3d595b9 100644 (file)
@@ -27,8 +27,9 @@
 #pragma once
 
 NTSTATUS
-GetSourcePaths(PUNICODE_STRING SourcePath,
-              PUNICODE_STRING SourceRootPath,
-              PUNICODE_STRING SourceRootDir);
+GetSourcePaths(
+    PUNICODE_STRING SourcePath,
+    PUNICODE_STRING SourceRootPath,
+    PUNICODE_STRING SourceRootDir);
 
 /* EOF */
index ce0b144..4f1bc3b 100644 (file)
 
 typedef struct _QUEUEENTRY
 {
-  struct _QUEUEENTRY *Prev;
-  struct _QUEUEENTRY *Next;
-
-  PWSTR SourceCabinet;          /* May be NULL if file is not in a cabinet */
-  PWSTR SourceRootPath;
-  PWSTR SourcePath;
-  PWSTR SourceFilename;
-  PWSTR TargetDirectory;
-  PWSTR TargetFilename;
-
+    struct _QUEUEENTRY *Prev;
+    struct _QUEUEENTRY *Next;
+
+    PWSTR SourceCabinet;          /* May be NULL if file is not in a cabinet */
+    PWSTR SourceRootPath;
+    PWSTR SourcePath;
+    PWSTR SourceFilename;
+    PWSTR TargetDirectory;
+    PWSTR TargetFilename;
 } QUEUEENTRY, *PQUEUEENTRY;
 
 
 typedef struct _FILEQUEUEHEADER
 {
-  PQUEUEENTRY CopyHead;
-  PQUEUEENTRY CopyTail;
-  ULONG CopyCount;
+    PQUEUEENTRY CopyHead;
+    PQUEUEENTRY CopyTail;
+    ULONG CopyCount;
 } FILEQUEUEHEADER, *PFILEQUEUEHEADER;
 
 
 /* FUNCTIONS ****************************************************************/
 
-HSPFILEQ WINAPI
+HSPFILEQ
+WINAPI
 SetupOpenFileQueue(VOID)
 {
-  PFILEQUEUEHEADER QueueHeader;
-
-  /* Allocate queue header */
-  QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
-                                                 0,
-                                                 sizeof(FILEQUEUEHEADER));
-  if (QueueHeader == NULL)
-    return(NULL);
+    PFILEQUEUEHEADER QueueHeader;
 
-  /* Initialize queue header */
-  RtlZeroMemory(QueueHeader,
-               sizeof(FILEQUEUEHEADER));
+    /* 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);
+    return (HSPFILEQ)QueueHeader;
 }
 
 
-VOID WINAPI
-SetupCloseFileQueue(HSPFILEQ QueueHandle)
+VOID
+WINAPI
+SetupCloseFileQueue(
+    HSPFILEQ QueueHandle)
 {
-  PFILEQUEUEHEADER QueueHeader;
-  PQUEUEENTRY Entry;
+    PFILEQUEUEHEADER QueueHeader;
+    PQUEUEENTRY Entry;
 
-  if (QueueHandle == NULL)
-    return;
+    if (QueueHandle == NULL)
+        return;
 
-  QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+    QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
 
-  /* Delete copy queue */
-  Entry = QueueHeader->CopyHead;
-  while (Entry != NULL)
+    /* Delete copy queue */
+    Entry = QueueHeader->CopyHead;
+    while (Entry != NULL)
     {
-      /* Delete all strings */
-      if (Entry->SourceCabinet != NULL)
-       RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
-      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 all strings */
+        if (Entry->SourceCabinet != NULL)
+            RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+
+        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);
+    /* Delete queue header */
+    RtlFreeHeap(ProcessHeap, 0, QueueHeader);
 }
 
 
 BOOL
-SetupQueueCopy(HSPFILEQ QueueHandle,
-         PCWSTR SourceCabinet,
-              PCWSTR SourceRootPath,
-              PCWSTR SourcePath,
-              PCWSTR SourceFilename,
-              PCWSTR TargetDirectory,
-              PCWSTR TargetFilename)
+SetupQueueCopy(
+    HSPFILEQ QueueHandle,
+    PCWSTR SourceCabinet,
+    PCWSTR SourceRootPath,
+    PCWSTR SourcePath,
+    PCWSTR SourceFilename,
+    PCWSTR TargetDirectory,
+    PCWSTR TargetFilename)
 {
-  PFILEQUEUEHEADER QueueHeader;
-  PQUEUEENTRY Entry;
-  ULONG Length;
-
-  /* SourceCabinet may be NULL */
-  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 cabinet if available */
-  if (SourceCabinet != NULL)
+    PFILEQUEUEHEADER QueueHeader;
+    PQUEUEENTRY Entry;
+    ULONG Length;
+
+    /* SourceCabinet may be NULL */
+    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 cabinet if available */
+    if (SourceCabinet != NULL)
+    {
+        Length = wcslen(SourceCabinet);
+        Entry->SourceCabinet = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                       0,
+                                                       (Length + 1) * sizeof(WCHAR));
+        if (Entry->SourceCabinet == NULL)
+        {
+            RtlFreeHeap(ProcessHeap, 0, Entry);
+            return FALSE;
+        }
+
+        wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
+        Entry->SourceCabinet[Length] = (WCHAR)0;
+    }
+    else
+    {
+        Entry->SourceCabinet = NULL;
+    }
+
+    /* Copy source root path */
+    Length = wcslen(SourceRootPath);
+    Entry->SourceRootPath = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                    0,
+                                                    (Length + 1) * sizeof(WCHAR));
+    if (Entry->SourceRootPath == NULL)
     {
-      Length = wcslen(SourceCabinet);
-      Entry->SourceCabinet = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                         0,
-                                         (Length + 1) * sizeof(WCHAR));
-      if (Entry->SourceCabinet == NULL)
-      {
+        if (Entry->SourceCabinet != NULL)
+        {
+            RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+        }
+
         RtlFreeHeap(ProcessHeap, 0, Entry);
-        return(FALSE);
-      }
-      wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
-      Entry->SourceCabinet[Length] = (WCHAR)0;
+        return FALSE;
     }
-  else
+
+    wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
+    Entry->SourceRootPath[Length] = (WCHAR)0;
+
+    /* Copy source path */
+    if (SourcePath != NULL)
     {
-      Entry->SourceCabinet = NULL;
+        Length = wcslen(SourcePath);
+        Entry->SourcePath = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                    0,
+                                                    (Length + 1) * sizeof(WCHAR));
+        if (Entry->SourcePath == NULL)
+        {
+            if (Entry->SourceCabinet != NULL)
+            {
+                RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+            }
+
+            RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+            RtlFreeHeap(ProcessHeap, 0, Entry);
+            return FALSE;
+        }
+
+        wcsncpy(Entry->SourcePath, SourcePath, Length);
+        Entry->SourcePath[Length] = (WCHAR)0;
     }
 
-  /* Copy source root path */
-  Length = wcslen(SourceRootPath);
-  Entry->SourceRootPath = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                         0,
-                                         (Length + 1) * sizeof(WCHAR));
-  if (Entry->SourceRootPath == NULL)
-  {
-    if (Entry->SourceCabinet != NULL)
-      {
-        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
-      }
-    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 = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                       0,
-                                       (Length + 1) * sizeof(WCHAR));
-    if (Entry->SourcePath == NULL)
+    /* Copy source file name */
+    Length = wcslen(SourceFilename);
+    Entry->SourceFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                    0,
+                                                    (Length + 1) * sizeof(WCHAR));
+    if (Entry->SourceFilename == NULL)
     {
-      if (Entry->SourceCabinet != NULL)
+        if (Entry->SourceCabinet != NULL)
         {
-          RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+            RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
         }
-      RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
-      RtlFreeHeap(ProcessHeap, 0, Entry);
-      return(FALSE);
+
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+        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 = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                         0,
-                                         (Length + 1) * sizeof(WCHAR));
-  if (Entry->SourceFilename == NULL)
-  {
-    if (Entry->SourceCabinet != NULL)
-      {
-        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
-      }
-    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 = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                          0,
-                                          (Length + 1) * sizeof(WCHAR));
-  if (Entry->TargetDirectory == NULL)
-  {
-    if (Entry->SourceCabinet != NULL)
-      {
-        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
-      }
-    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 = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                           0,
-                                           (Length + 1) * sizeof(WCHAR));
-    if (Entry->TargetFilename == NULL)
+
+    wcsncpy(Entry->SourceFilename, SourceFilename, Length);
+    Entry->SourceFilename[Length] = (WCHAR)0;
+
+    /* Copy target directory */
+    Length = wcslen(TargetDirectory);
+    if (TargetDirectory[Length] == '\\')
+        Length--;
+    Entry->TargetDirectory = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                     0,
+                                                     (Length + 1) * sizeof(WCHAR));
+    if (Entry->TargetDirectory == NULL)
     {
-      if (Entry->SourceCabinet != NULL)
+        if (Entry->SourceCabinet != NULL)
         {
-          RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+            RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
         }
-      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);
+
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+        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);
-}
 
+    wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
+    Entry->TargetDirectory[Length] = (WCHAR)0;
 
-BOOL WINAPI
-SetupCommitFileQueueW(HWND Owner,
-                    HSPFILEQ QueueHandle,
-                    PSP_FILE_CALLBACK_W MsgHandler,
-                    PVOID Context)
-{
-  WCHAR CabinetName[MAX_PATH];
-  PFILEQUEUEHEADER QueueHeader;
-  PQUEUEENTRY Entry;
-  NTSTATUS Status;
-  PCWSTR TargetRootPath, TargetPath;
-
-  WCHAR FileSrcPath[MAX_PATH];
-  WCHAR FileDstPath[MAX_PATH];
-
-  TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath;
-  TargetPath = ((PCOPYCONTEXT)Context)->InstallPath;
-
-  if (QueueHandle == NULL)
-    return(FALSE);
-
-  QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
-
-  MsgHandler(Context,
-            SPFILENOTIFY_STARTQUEUE,
-            0,
-            0);
-
-  MsgHandler(Context,
-            SPFILENOTIFY_STARTSUBQUEUE,
-            FILEOP_COPY,
-            QueueHeader->CopyCount);
-
-  /* Commit copy queue */
-  Entry = QueueHeader->CopyHead;
-  while (Entry != NULL)
-  {
-    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'\\')
+    /* Copy optional target filename */
+    if (TargetFilename != NULL)
     {
-      wcscat(FileDstPath, Entry->TargetDirectory);
+        Length = wcslen(TargetFilename);
+        Entry->TargetFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                        0,
+                                                        (Length + 1) * sizeof(WCHAR));
+        if (Entry->TargetFilename == NULL)
+        {
+            if (Entry->SourceCabinet != NULL)
+            {
+                RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+            }
+
+            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
     {
-      if (TargetPath != NULL)
-      {
-       if (TargetPath[0] != L'\\')
-         wcscat(FileDstPath, L"\\");
-       wcscat(FileDstPath, TargetPath);
-      }
-      wcscat(FileDstPath, L"\\");
-      wcscat(FileDstPath, Entry->TargetDirectory);
+        Entry->Prev = QueueHeader->CopyTail;
+        Entry->Next = NULL;
+        QueueHeader->CopyTail->Next = Entry;
+        QueueHeader->CopyTail = Entry;
     }
 
-    /* Use only the destination path if the file is in a cabinet */
-    if (Entry->SourceCabinet == NULL)
-      {
-        wcscat(FileDstPath, L"\\");
-        if (Entry->TargetFilename != NULL)
-          wcscat(FileDstPath, Entry->TargetFilename);
-        else
-          wcscat(FileDstPath, Entry->SourceFilename);
-      }
+    QueueHeader->CopyCount++;
+
+    return TRUE;
+}
+
+
+BOOL
+WINAPI
+SetupCommitFileQueueW(
+    HWND Owner,
+    HSPFILEQ QueueHandle,
+    PSP_FILE_CALLBACK_W MsgHandler,
+    PVOID Context)
+{
+    WCHAR CabinetName[MAX_PATH];
+    PFILEQUEUEHEADER QueueHeader;
+    PQUEUEENTRY Entry;
+    NTSTATUS Status;
+    PCWSTR TargetRootPath, TargetPath;
+
+    WCHAR FileSrcPath[MAX_PATH];
+    WCHAR FileDstPath[MAX_PATH];
+
+    TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath;
+    TargetPath = ((PCOPYCONTEXT)Context)->InstallPath;
+
+    if (QueueHandle == NULL)
+        return FALSE;
 
-    /* FIXME: Do it! */
-    DPRINT("'%S' ==> '%S'\n",
-          FileSrcPath,
-          FileDstPath);
+    QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
 
     MsgHandler(Context,
-              SPFILENOTIFY_STARTCOPY,
-              (UINT_PTR)Entry->SourceFilename,
-              FILEOP_COPY);
-
-    if (Entry->SourceCabinet != NULL)
-      {
-        /* Extract the file */
-        wcscpy(CabinetName, Entry->SourceRootPath);
-        if (Entry->SourcePath != NULL)
-          wcscat(CabinetName, Entry->SourcePath);
-        wcscat(CabinetName, L"\\");
-        wcscat(CabinetName, Entry->SourceCabinet);
-        Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath);
-      }
-    else
-      {
-        /* Copy the file */
-        Status = SetupCopyFile(FileSrcPath, FileDstPath);
-      }
-    if (!NT_SUCCESS(Status))
-    {
-      MsgHandler(Context,
-                SPFILENOTIFY_COPYERROR,
-                (UINT_PTR)Entry->SourceFilename,
-                FILEOP_COPY);
+               SPFILENOTIFY_STARTQUEUE,
+               0,
+               0);
 
-    }
-    else
+    MsgHandler(Context,
+               SPFILENOTIFY_STARTSUBQUEUE,
+               FILEOP_COPY,
+               QueueHeader->CopyCount);
+
+    /* Commit copy queue */
+    Entry = QueueHeader->CopyHead;
+    while (Entry != NULL)
     {
-      MsgHandler(Context,
-                SPFILENOTIFY_ENDCOPY,
-                (UINT_PTR)Entry->SourceFilename,
-                FILEOP_COPY);
-    }
+        wcscpy(FileSrcPath, Entry->SourceRootPath);
+        if (Entry->SourcePath != NULL)
+            wcscat(FileSrcPath, Entry->SourcePath);
+        wcscat(FileSrcPath, L"\\");
+        wcscat(FileSrcPath, Entry->SourceFilename);
 
-    Entry = Entry->Next;
-  }
+        /* 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);
+        }
+
+        /* Use only the destination path if the file is in a cabinet */
+        if (Entry->SourceCabinet == NULL)
+        {
+            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_ENDSUBQUEUE,
-            FILEOP_COPY,
-            0);
+        MsgHandler(Context,
+                   SPFILENOTIFY_STARTCOPY,
+                   (UINT_PTR)Entry->SourceFilename,
+                   FILEOP_COPY);
+
+        if (Entry->SourceCabinet != NULL)
+        {
+            /* Extract the file */
+            wcscpy(CabinetName, Entry->SourceRootPath);
+            if (Entry->SourcePath != NULL)
+                wcscat(CabinetName, Entry->SourcePath);
+            wcscat(CabinetName, L"\\");
+            wcscat(CabinetName, Entry->SourceCabinet);
+            Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath);
+        }
+        else
+        {
+            /* Copy the file */
+            Status = SetupCopyFile(FileSrcPath, FileDstPath);
+        }
 
-  MsgHandler(Context,
-            SPFILENOTIFY_ENDQUEUE,
-            0,
-            0);
+        if (!NT_SUCCESS(Status))
+        {
+            MsgHandler(Context,
+                       SPFILENOTIFY_COPYERROR,
+                       (UINT_PTR)Entry->SourceFilename,
+                       FILEOP_COPY);
+        }
+        else
+        {
+            MsgHandler(Context,
+                       SPFILENOTIFY_ENDCOPY,
+                       (UINT_PTR)Entry->SourceFilename,
+                       FILEOP_COPY);
+        }
+
+        Entry = Entry->Next;
+    }
+
+    MsgHandler(Context,
+               SPFILENOTIFY_ENDSUBQUEUE,
+               FILEOP_COPY,
+               0);
+
+    MsgHandler(Context,
+               SPFILENOTIFY_ENDQUEUE,
+               0,
+               0);
 
-  return(TRUE);
+    return TRUE;
 }
 
 /* EOF */
index 7dc8587..17ebe04 100644 (file)
 
 typedef PVOID HSPFILEQ;
 
-typedef UINT (CALLBACK* PSP_FILE_CALLBACK_W)(PVOID Context,
-                                  UINT Notification,
-                                  UINT_PTR Param1,
-                                  UINT_PTR Param2);
+typedef UINT (CALLBACK* PSP_FILE_CALLBACK_W)(
+    PVOID Context,
+    UINT Notification,
+    UINT_PTR Param1,
+    UINT_PTR Param2);
 
 typedef struct _COPYCONTEXT
 {
-  LPCWSTR DestinationRootPath; /* Not owned by this structure */
-  LPCWSTR InstallPath; /* Not owned by this structure */
-  ULONG TotalOperations;
-  ULONG CompletedOperations;
-  PPROGRESSBAR ProgressBar;
-  PPROGRESSBAR MemoryBars[4];
+    LPCWSTR DestinationRootPath; /* Not owned by this structure */
+    LPCWSTR InstallPath; /* Not owned by this structure */
+    ULONG TotalOperations;
+    ULONG CompletedOperations;
+    PPROGRESSBAR ProgressBar;
+    PPROGRESSBAR MemoryBars[4];
 } COPYCONTEXT, *PCOPYCONTEXT;
 
 /* FUNCTIONS ****************************************************************/
 
-HSPFILEQ WINAPI
+HSPFILEQ
+WINAPI
 SetupOpenFileQueue(VOID);
 
-VOID WINAPI
+VOID
+WINAPI
 SetupCloseFileQueue(
-       IN HSPFILEQ QueueHandle);
+    IN HSPFILEQ QueueHandle);
 
-BOOL WINAPI
+BOOL
+WINAPI
 SetupQueueCopyWNew(
-       IN HSPFILEQ QueueHandle,
-       IN PCWSTR SourceRootPath,
-       IN PCWSTR SourcePath,
-       IN PCWSTR SourceFileName,
-       IN PCWSTR SourceDescription,
-       IN PCWSTR SourceTagFile,
-       IN PCWSTR TargetDirectory,
-       IN PCWSTR TargetFileName,
-       IN DWORD CopyStyle);
+    IN HSPFILEQ QueueHandle,
+    IN PCWSTR SourceRootPath,
+    IN PCWSTR SourcePath,
+    IN PCWSTR SourceFileName,
+    IN PCWSTR SourceDescription,
+    IN PCWSTR SourceTagFile,
+    IN PCWSTR TargetDirectory,
+    IN PCWSTR TargetFileName,
+    IN DWORD CopyStyle);
+
+BOOL
+SetupQueueCopy(
+    HSPFILEQ QueueHandle,
+    PCWSTR SourceCabinet,
+    PCWSTR SourceRootPath,
+    PCWSTR SourcePath,
+    PCWSTR SourceFilename,
+    PCWSTR TargetDirectory,
+    PCWSTR TargetFilename);
 
 BOOL
-SetupQueueCopy(HSPFILEQ QueueHandle,
-         PCWSTR SourceCabinet,
-              PCWSTR SourceRootPath,
-              PCWSTR SourcePath,
-              PCWSTR SourceFilename,
-              PCWSTR TargetDirectory,
-              PCWSTR TargetFilename);
-
-BOOL WINAPI
-SetupCommitFileQueueW(HWND Owner,
-                    HSPFILEQ QueueHandle,
-                    PSP_FILE_CALLBACK_W MsgHandler,
-                    PVOID Context);
+WINAPI
+SetupCommitFileQueueW(
+    HWND Owner,
+    HSPFILEQ QueueHandle,
+    PSP_FILE_CALLBACK_W MsgHandler,
+    PVOID Context);
 
 /* EOF */
index 2902088..eaabc3d 100644 (file)
@@ -38,358 +38,373 @@ static WCHAR CurrentCabinetName[MAX_PATH];
 static CAB_SEARCH Search;
 
 NTSTATUS
-SetupCreateDirectory(PWCHAR DirectoryName)
+SetupCreateDirectory(
+    PWCHAR DirectoryName)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  IO_STATUS_BLOCK IoStatusBlock;
-  UNICODE_STRING PathName;
-  HANDLE DirectoryHandle;
-  NTSTATUS Status;
-
-  RtlCreateUnicodeString(&PathName,
-                        DirectoryName);
-  if (PathName.Length > sizeof(WCHAR) &&
-      PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
-      PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    UNICODE_STRING PathName;
+    HANDLE DirectoryHandle;
+    NTSTATUS Status;
+
+    RtlCreateUnicodeString(&PathName,
+                           DirectoryName);
+    if (PathName.Length > sizeof(WCHAR) &&
+        PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
+        PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
     {
-       PathName.Length -= sizeof(WCHAR);
-       PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
+        PathName.Length -= sizeof(WCHAR);
+        PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
     }
 
-  if (PathName.Length > sizeof(WCHAR) &&
-      PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
+    if (PathName.Length > sizeof(WCHAR) &&
+        PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
     {
-      PathName.Length -= sizeof(WCHAR);
-      PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
-   }
-
-  InitializeObjectAttributes(&ObjectAttributes,
-                            &PathName,
-                            OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
-                            NULL,
-                            NULL);
-
-  Status = NtCreateFile(&DirectoryHandle,
-                       DIRECTORY_ALL_ACCESS,
-                       &ObjectAttributes,
-                       &IoStatusBlock,
-                       NULL,
-                       FILE_ATTRIBUTE_DIRECTORY,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE,
-                       FILE_OPEN_IF,
-                       FILE_DIRECTORY_FILE,
-                       NULL,
-                       0);
-  if (NT_SUCCESS(Status))
+        PathName.Length -= sizeof(WCHAR);
+        PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &PathName,
+                               OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+                               NULL,
+                               NULL);
+
+    Status = NtCreateFile(&DirectoryHandle,
+                          DIRECTORY_ALL_ACCESS,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          FILE_ATTRIBUTE_DIRECTORY,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE,
+                          FILE_OPEN_IF,
+                          FILE_DIRECTORY_FILE,
+                          NULL,
+                          0);
+    if (NT_SUCCESS(Status))
     {
-      NtClose(DirectoryHandle);
+        NtClose(DirectoryHandle);
     }
 
-  RtlFreeUnicodeString(&PathName);
+    RtlFreeUnicodeString(&PathName);
 
-  return(Status);
+    return Status;
 }
 
 
 NTSTATUS
-SetupCopyFile(PWCHAR SourceFileName,
-             PWCHAR DestinationFileName)
+SetupCopyFile(
+    PWCHAR SourceFileName,
+    PWCHAR DestinationFileName)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  HANDLE FileHandleSource;
-  HANDLE FileHandleDest;
-  static IO_STATUS_BLOCK IoStatusBlock;
-  FILE_STANDARD_INFORMATION FileStandard;
-  FILE_BASIC_INFORMATION FileBasic;
-  ULONG RegionSize;
-  UNICODE_STRING FileName;
-  NTSTATUS Status;
-  PVOID SourceFileMap = 0;
-  HANDLE SourceFileSection;
-  SIZE_T SourceSectionSize = 0;
-  LARGE_INTEGER ByteOffset;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE FileHandleSource;
+    HANDLE FileHandleDest;
+    static IO_STATUS_BLOCK IoStatusBlock;
+    FILE_STANDARD_INFORMATION FileStandard;
+    FILE_BASIC_INFORMATION FileBasic;
+    ULONG RegionSize;
+    UNICODE_STRING FileName;
+    NTSTATUS Status;
+    PVOID SourceFileMap = 0;
+    HANDLE SourceFileSection;
+    SIZE_T SourceSectionSize = 0;
+    LARGE_INTEGER ByteOffset;
 
 #ifdef __REACTOS__
-  RtlInitUnicodeString(&FileName,
-                      SourceFileName);
-
-  InitializeObjectAttributes(&ObjectAttributes,
-                            &FileName,
-                            OBJ_CASE_INSENSITIVE,
-                            NULL,
-                            NULL);
-
-  Status = NtOpenFile(&FileHandleSource,
-                     GENERIC_READ,
-                     &ObjectAttributes,
-                     &IoStatusBlock,
-                     FILE_SHARE_READ,
-                     FILE_SEQUENTIAL_ONLY);
-  if(!NT_SUCCESS(Status))
+    RtlInitUnicodeString(&FileName,
+                         SourceFileName);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandleSource,
+                        GENERIC_READ,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SEQUENTIAL_ONLY);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
-      goto done;
+        DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
+        goto done;
     }
 #else
-  FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
-  if (FileHandleSource == INVALID_HANDLE_VALUE)
-  {
-    Status = STATUS_UNSUCCESSFUL;
-    goto done;
-  }
+    FileHandleSource = CreateFileW(SourceFileName,
+                                   GENERIC_READ,
+                                   FILE_SHARE_READ,
+                                   NULL,
+                                   OPEN_EXISTING,
+                                   0,
+                                   NULL);
+    if (FileHandleSource == INVALID_HANDLE_VALUE)
+    {
+        Status = STATUS_UNSUCCESSFUL;
+        goto done;
+    }
 #endif
 
-  Status = NtQueryInformationFile(FileHandleSource,
-                                 &IoStatusBlock,
-                                 &FileStandard,
-                                 sizeof(FILE_STANDARD_INFORMATION),
-                                 FileStandardInformation);
-  if(!NT_SUCCESS(Status))
+    Status = NtQueryInformationFile(FileHandleSource,
+                                    &IoStatusBlock,
+                                    &FileStandard,
+                                    sizeof(FILE_STANDARD_INFORMATION),
+                                    FileStandardInformation);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtQueryInformationFile failed: %x\n", Status);
-      goto closesrc;
+        DPRINT1("NtQueryInformationFile failed: %x\n", Status);
+        goto closesrc;
     }
-  Status = NtQueryInformationFile(FileHandleSource,
-                                 &IoStatusBlock,&FileBasic,
-                                 sizeof(FILE_BASIC_INFORMATION),
-                                 FileBasicInformation);
-  if(!NT_SUCCESS(Status))
+
+    Status = NtQueryInformationFile(FileHandleSource,
+                                    &IoStatusBlock,&FileBasic,
+                                    sizeof(FILE_BASIC_INFORMATION),
+                                    FileBasicInformation);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtQueryInformationFile failed: %x\n", Status);
-      goto closesrc;
+        DPRINT1("NtQueryInformationFile failed: %x\n", Status);
+        goto closesrc;
     }
 
-  Status = NtCreateSection( &SourceFileSection,
-                           SECTION_MAP_READ,
-                           NULL,
-                           NULL,
-                           PAGE_READONLY,
-                           SEC_COMMIT,
-                           FileHandleSource);
-  if(!NT_SUCCESS(Status))
+    Status = NtCreateSection(&SourceFileSection,
+                             SECTION_MAP_READ,
+                             NULL,
+                             NULL,
+                             PAGE_READONLY,
+                             SEC_COMMIT,
+                             FileHandleSource);
+    if (!NT_SUCCESS(Status))
     {
       DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
       goto closesrc;
     }
 
-  Status = NtMapViewOfSection( SourceFileSection,
-                              NtCurrentProcess(),
-                              &SourceFileMap,
-                              0,
-                              0,
-                              NULL,
-                              &SourceSectionSize,
-                              ViewUnmap,
-                              0,
-                              PAGE_READONLY );
-  if(!NT_SUCCESS(Status))
+    Status = NtMapViewOfSection(SourceFileSection,
+                                NtCurrentProcess(),
+                                &SourceFileMap,
+                                0,
+                                0,
+                                NULL,
+                                &SourceSectionSize,
+                                ViewUnmap,
+                                0,
+                                PAGE_READONLY );
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName);
-      goto closesrcsec;
+        DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName);
+        goto closesrcsec;
     }
 
-  RtlInitUnicodeString(&FileName,
-                      DestinationFileName);
-
-  InitializeObjectAttributes(&ObjectAttributes,
-                            &FileName,
-                            OBJ_CASE_INSENSITIVE,
-                            NULL,
-                            NULL);
-
-  Status = NtCreateFile(&FileHandleDest,
-                       GENERIC_WRITE | SYNCHRONIZE,
-                       &ObjectAttributes,
-                       &IoStatusBlock,
-                       NULL,
-                       FILE_ATTRIBUTE_NORMAL,
-                       0,
-                       FILE_OVERWRITE_IF,
-                       FILE_NO_INTERMEDIATE_BUFFERING |
-                       FILE_SEQUENTIAL_ONLY |
-                       FILE_SYNCHRONOUS_IO_NONALERT,
-                       NULL,
-                       0);
-  if(!NT_SUCCESS(Status))
+    RtlInitUnicodeString(&FileName,
+                         DestinationFileName);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtCreateFile(&FileHandleDest,
+                          GENERIC_WRITE | SYNCHRONIZE,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          FILE_ATTRIBUTE_NORMAL,
+                          0,
+                          FILE_OVERWRITE_IF,
+                          FILE_NO_INTERMEDIATE_BUFFERING |
+                          FILE_SEQUENTIAL_ONLY |
+                          FILE_SYNCHRONOUS_IO_NONALERT,
+                          NULL,
+                          0);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtCreateFile failed: %x\n", Status);
-      goto unmapsrcsec;
+        DPRINT1("NtCreateFile failed: %x\n", Status);
+        goto unmapsrcsec;
     }
 
-  RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
-  IoStatusBlock.Status = 0;
-  ByteOffset.QuadPart = 0;
-  Status = NtWriteFile(FileHandleDest,
-                      NULL,
-                      NULL,
-                      NULL,
-                      &IoStatusBlock,
-                      SourceFileMap,
-                      RegionSize,
-                      &ByteOffset,
-                      NULL);
-  if(!NT_SUCCESS(Status))
+    RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
+    IoStatusBlock.Status = 0;
+    ByteOffset.QuadPart = 0;
+    Status = NtWriteFile(FileHandleDest,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         SourceFileMap,
+                         RegionSize,
+                         &ByteOffset,
+                         NULL);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
-      goto closedest;
+        DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
+        goto closedest;
     }
-  /* Copy file date/time from source file */
-  Status = NtSetInformationFile(FileHandleDest,
-                               &IoStatusBlock,
-                               &FileBasic,
-                               sizeof(FILE_BASIC_INFORMATION),
-                               FileBasicInformation);
-  if(!NT_SUCCESS(Status))
+
+    /* Copy file date/time from source file */
+    Status = NtSetInformationFile(FileHandleDest,
+                                  &IoStatusBlock,
+                                  &FileBasic,
+                                  sizeof(FILE_BASIC_INFORMATION),
+                                  FileBasicInformation);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtSetInformationFile failed: %x\n", Status);
-      goto closedest;
+        DPRINT1("NtSetInformationFile failed: %x\n", Status);
+        goto closedest;
     }
 
-  /* shorten the file back to it's real size after completing the write */
-  Status = NtSetInformationFile(FileHandleDest,
-                      &IoStatusBlock,
-                      &FileStandard.EndOfFile,
-                      sizeof(FILE_END_OF_FILE_INFORMATION),
-                      FileEndOfFileInformation);
-
-  if(!NT_SUCCESS(Status))
+    /* shorten the file back to it's real size after completing the write */
+    Status = NtSetInformationFile(FileHandleDest,
+                                  &IoStatusBlock,
+                                  &FileStandard.EndOfFile,
+                                  sizeof(FILE_END_OF_FILE_INFORMATION),
+                                  FileEndOfFileInformation);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtSetInformationFile failed: %x\n", Status);
+        DPRINT1("NtSetInformationFile failed: %x\n", Status);
     }
 
- closedest:
-  NtClose(FileHandleDest);
- unmapsrcsec:
-  NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap );
- closesrcsec:
-  NtClose(SourceFileSection);
- closesrc:
-  NtClose(FileHandleSource);
- done:
-  return(Status);
+closedest:
+    NtClose(FileHandleDest);
+
+unmapsrcsec:
+    NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
+
+closesrcsec:
+    NtClose(SourceFileSection);
+
+closesrc:
+    NtClose(FileHandleSource);
+
+done:
+    return Status;
 }
 
 #ifdef __REACTOS__
 NTSTATUS
-SetupExtractFile(PWCHAR CabinetFileName,
-        PWCHAR SourceFileName,
-             PWCHAR DestinationPathName)
+SetupExtractFile(
+    PWCHAR CabinetFileName,
+    PWCHAR SourceFileName,
+    PWCHAR DestinationPathName)
 {
-  ULONG CabStatus;
+    ULONG CabStatus;
 
-  DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
-    CabinetFileName, SourceFileName, DestinationPathName);
+    DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
+           CabinetFileName, SourceFileName, DestinationPathName);
 
-  if (HasCurrentCabinet)
+    if (HasCurrentCabinet)
     {
-      DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
+        DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
     }
 
-  if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
+    if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
     {
-      DPRINT("Using same cabinet as last time\n");
-
-      /* Use our last location because the files should be sequential */
-      CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search);
-      if (CabStatus != CAB_STATUS_SUCCESS)
-      {
-          DPRINT("Sequential miss on file: %S\n", SourceFileName);
-          
-          /* Looks like we got unlucky */
-          CabStatus = CabinetFindFirst(SourceFileName, &Search);
-      }
+        DPRINT("Using same cabinet as last time\n");
+
+        /* Use our last location because the files should be sequential */
+        CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search);
+        if (CabStatus != CAB_STATUS_SUCCESS)
+        {
+            DPRINT("Sequential miss on file: %S\n", SourceFileName);
+
+            /* Looks like we got unlucky */
+            CabStatus = CabinetFindFirst(SourceFileName, &Search);
+        }
     }
-  else
+    else
     {
-      DPRINT("Using new cabinet\n");
+        DPRINT("Using new cabinet\n");
 
-      if (HasCurrentCabinet)
+        if (HasCurrentCabinet)
         {
-          CabinetCleanup();
+            CabinetCleanup();
         }
 
-      wcscpy(CurrentCabinetName, CabinetFileName);
+        wcscpy(CurrentCabinetName, CabinetFileName);
 
-      CabinetInitialize();
-      CabinetSetEventHandlers(NULL, NULL, NULL);
-      CabinetSetCabinetName(CabinetFileName);
+        CabinetInitialize();
+        CabinetSetEventHandlers(NULL, NULL, NULL);
+        CabinetSetCabinetName(CabinetFileName);
 
-      CabStatus = CabinetOpen();
-      if (CabStatus == CAB_STATUS_SUCCESS)
+        CabStatus = CabinetOpen();
+        if (CabStatus == CAB_STATUS_SUCCESS)
         {
-          DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
-          HasCurrentCabinet = TRUE;
+            DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
+            HasCurrentCabinet = TRUE;
         }
-      else
+        else
         {
-          DPRINT("Cannot open cabinet (%d)\n", CabStatus);
-          return STATUS_UNSUCCESSFUL;
+            DPRINT("Cannot open cabinet (%d)\n", CabStatus);
+            return STATUS_UNSUCCESSFUL;
         }
-        
-      /* We have to start at the beginning here */
-      CabStatus = CabinetFindFirst(SourceFileName, &Search);
+
+        /* We have to start at the beginning here */
+        CabStatus = CabinetFindFirst(SourceFileName, &Search);
     }
-    
-  if (CabStatus != CAB_STATUS_SUCCESS)
-  {
-      DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName());
-      return STATUS_UNSUCCESSFUL;
-  }
-
-  CabinetSetDestinationPath(DestinationPathName);
-  CabStatus = CabinetExtractFile(&Search);
-  if (CabStatus != CAB_STATUS_SUCCESS)
+
+    if (CabStatus != CAB_STATUS_SUCCESS)
+    {
+        DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName());
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    CabinetSetDestinationPath(DestinationPathName);
+    CabStatus = CabinetExtractFile(&Search);
+    if (CabStatus != CAB_STATUS_SUCCESS)
     {
-      DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
-      return STATUS_UNSUCCESSFUL;
+        DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
+        return STATUS_UNSUCCESSFUL;
     }
 
-  return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 #endif
 
 BOOLEAN
-DoesFileExist(PWSTR PathName,
-             PWSTR FileName)
+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)
+    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);
+        if (FileName[0] != L'\\')
+            wcscat(FullName, L"\\");
+        wcscat(FullName, FileName);
     }
 
-  RtlInitUnicodeString(&Name,
-                      FullName);
-
-  InitializeObjectAttributes(&ObjectAttributes,
-                            &Name,
-                            OBJ_CASE_INSENSITIVE,
-                            NULL,
-                            NULL);
-
-  Status = NtOpenFile(&FileHandle,
-                     GENERIC_READ | SYNCHRONIZE,
-                     &ObjectAttributes,
-                     &IoStatusBlock,
-                     0,
-                     FILE_SYNCHRONOUS_IO_NONALERT);
-  if (!NT_SUCCESS(Status))
+    RtlInitUnicodeString(&Name,
+                         FullName);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        GENERIC_READ | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        0,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
     {
-      return(FALSE);
+      return FALSE;
     }
 
-  NtClose(FileHandle);
+    NtClose(FileHandle);
 
-  return(TRUE);
+    return TRUE;
 }
 
 /* EOF */
index a1d45cb..5522321 100644 (file)
 #pragma once
 
 NTSTATUS
-SetupCreateDirectory(PWCHAR DirectoryName);
+SetupCreateDirectory(
+    PWCHAR DirectoryName);
 
 NTSTATUS
-SetupCopyFile(PWCHAR SourceFileName,
-             PWCHAR DestinationFileName);
+SetupCopyFile(
+    PWCHAR SourceFileName,
+    PWCHAR DestinationFileName);
 
 NTSTATUS
-SetupExtractFile(PWCHAR CabinetFileName,
-        PWCHAR SourceFileName,
-             PWCHAR DestinationFileName);
+SetupExtractFile(
+    PWCHAR CabinetFileName,
+    PWCHAR SourceFileName,
+    PWCHAR DestinationFileName);
 
 BOOLEAN
-DoesFileExist(PWSTR PathName,
-             PWSTR FileName);
+DoesFileExist(
+    PWSTR PathName,
+    PWSTR FileName);
 
 /* EOF */
index 00f4374..dd2ee16 100644 (file)
@@ -34,7 +34,9 @@ static PPROGRESSBAR FormatProgressBar = NULL;
 
 /* FUNCTIONS ****************************************************************/
 
-static BOOLEAN NTAPI
+static
+BOOLEAN
+NTAPI
 FormatCallback(
     IN CALLBACKCOMMAND Command,
     IN ULONG Modifier,
@@ -82,6 +84,7 @@ FormatCallback(
     return TRUE;
 }
 
+
 NTSTATUS
 FormatPartition(
     IN PUNICODE_STRING DriveRoot,
index 93db77c..85045a8 100644 (file)
@@ -65,6 +65,7 @@ FS_AddProvider(
     InsertTailList(&List->ListHead, &Item->ListEntry);
 }
 
+
 PFILE_SYSTEM_LIST
 CreateFileSystemList(
     IN SHORT Left,
@@ -111,6 +112,7 @@ CreateFileSystemList(
     return List;
 }
 
+
 VOID
 DestroyFileSystemList(
     IN PFILE_SYSTEM_LIST List)
@@ -131,6 +133,7 @@ DestroyFileSystemList(
     RtlFreeHeap(ProcessHeap, 0, List);
 }
 
+
 VOID
 DrawFileSystemList(
     IN PFILE_SYSTEM_LIST List)
@@ -183,6 +186,7 @@ DrawFileSystemList(
     }
 }
 
+
 VOID
 ScrollDownFileSystemList(
     IN PFILE_SYSTEM_LIST List)
@@ -194,6 +198,7 @@ ScrollDownFileSystemList(
     }
 }
 
+
 VOID
 ScrollUpFileSystemList(
     IN PFILE_SYSTEM_LIST List)
index 1c84024..6b28e29 100644 (file)
 
 typedef struct _FILE_SYSTEM_ITEM
 {
-       LIST_ENTRY ListEntry;
-       LPCWSTR FileSystem; /* Not owned by the item */
-       FORMATEX FormatFunc;
-       CHKDSKEX ChkdskFunc;
-       BOOLEAN QuickFormat;
+    LIST_ENTRY ListEntry;
+    LPCWSTR FileSystem; /* Not owned by the item */
+    FORMATEX FormatFunc;
+    CHKDSKEX ChkdskFunc;
+    BOOLEAN QuickFormat;
 } FILE_SYSTEM_ITEM, *PFILE_SYSTEM_ITEM;
 
 typedef struct _FILE_SYSTEM_LIST
 {
-       SHORT Left;
-       SHORT Top;
-       PFILE_SYSTEM_ITEM Selected;
-       LIST_ENTRY ListHead; /* List of FILE_SYSTEM_ITEM */
+    SHORT Left;
+    SHORT Top;
+    PFILE_SYSTEM_ITEM Selected;
+    LIST_ENTRY ListHead; /* List of FILE_SYSTEM_ITEM */
 } FILE_SYSTEM_LIST, *PFILE_SYSTEM_LIST;
 
 VOID
 FS_AddProvider(
-       IN OUT PFILE_SYSTEM_LIST List,
-       IN LPCWSTR FileSystem,
-       IN FORMATEX FormatFunc,
-       IN CHKDSKEX ChkdskFunc);
+    IN OUT PFILE_SYSTEM_LIST List,
+    IN LPCWSTR FileSystem,
+    IN FORMATEX FormatFunc,
+    IN CHKDSKEX ChkdskFunc);
 
 PFILE_SYSTEM_LIST
 CreateFileSystemList(
-       IN SHORT Left,
-       IN SHORT Top,
-       IN BOOLEAN ForceFormat,
-       IN LPCWSTR ForceFileSystem);
+    IN SHORT Left,
+    IN SHORT Top,
+    IN BOOLEAN ForceFormat,
+    IN LPCWSTR ForceFileSystem);
 
 VOID
 DestroyFileSystemList(
index 9073ca3..6e5a736 100644 (file)
@@ -84,8 +84,9 @@ CreateGenericList(VOID)
 
 
 VOID
-DestroyGenericList(PGENERIC_LIST List,
-                   BOOLEAN FreeUserData)
+DestroyGenericList(
+    PGENERIC_LIST List,
+    BOOLEAN FreeUserData)
 {
     PGENERIC_LIST_ENTRY ListEntry;
     PLIST_ENTRY Entry;
@@ -110,10 +111,11 @@ DestroyGenericList(PGENERIC_LIST List,
 
 
 BOOLEAN
-AppendGenericListEntry(PGENERIC_LIST List,
-                     PCHAR Text,
-                     PVOID UserData,
-                     BOOLEAN Current)
+AppendGenericListEntry(
+    PGENERIC_LIST List,
+    PCHAR Text,
+    PVOID UserData,
+    BOOLEAN Current)
 {
     PGENERIC_LIST_ENTRY Entry;
 
@@ -139,8 +141,10 @@ AppendGenericListEntry(PGENERIC_LIST List,
 }
 
 
-static VOID
-DrawListFrame(PGENERIC_LIST GenericList)
+static
+VOID
+DrawListFrame(
+    PGENERIC_LIST GenericList)
 {
     COORD coPos;
     DWORD Written;
@@ -221,8 +225,10 @@ DrawListFrame(PGENERIC_LIST GenericList)
 }
 
 
-static VOID
-DrawListEntries(PGENERIC_LIST GenericList)
+static
+VOID
+DrawListEntries(
+    PGENERIC_LIST GenericList)
 {
     PGENERIC_LIST_ENTRY ListEntry;
     PLIST_ENTRY Entry;
@@ -286,8 +292,11 @@ DrawListEntries(PGENERIC_LIST GenericList)
     }
 }
 
-static VOID
-DrawScrollBarGenericList(PGENERIC_LIST GenericList)
+
+static
+VOID
+DrawScrollBarGenericList(
+    PGENERIC_LIST GenericList)
 {
     COORD coPos;
     DWORD Written;
@@ -331,12 +340,14 @@ DrawScrollBarGenericList(PGENERIC_LIST GenericList)
     }
 }
 
+
 VOID
-DrawGenericList(PGENERIC_LIST List,
-                SHORT Left,
-                SHORT Top,
-                SHORT Right,
-                SHORT Bottom)
+DrawGenericList(
+    PGENERIC_LIST List,
+    SHORT Left,
+    SHORT Top,
+    SHORT Right,
+    SHORT Bottom)
 {
     List->FirstShown = List->ListHead.Flink;
     List->Left = Left;
@@ -353,8 +364,10 @@ DrawGenericList(PGENERIC_LIST List,
     DrawScrollBarGenericList(List);
 }
 
+
 VOID
-ScrollPageDownGenericList (PGENERIC_LIST List)
+ScrollPageDownGenericList(
+    PGENERIC_LIST List)
 {
     SHORT i;
 
@@ -374,8 +387,10 @@ ScrollPageDownGenericList (PGENERIC_LIST List)
     List->Redraw = TRUE;
 }
 
+
 VOID
-ScrollPageUpGenericList (PGENERIC_LIST List)
+ScrollPageUpGenericList(
+    PGENERIC_LIST List)
 {
     SHORT i;
 
@@ -395,8 +410,10 @@ ScrollPageUpGenericList (PGENERIC_LIST List)
     List->Redraw = TRUE;
 }
 
+
 VOID
-ScrollDownGenericList (PGENERIC_LIST List)
+ScrollDownGenericList(
+    PGENERIC_LIST List)
 {
     PLIST_ENTRY Entry;
 
@@ -423,7 +440,9 @@ ScrollDownGenericList (PGENERIC_LIST List)
 
 
 VOID
-ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex)
+ScrollToPositionGenericList(
+    PGENERIC_LIST List,
+    ULONG uIndex)
 {
     PLIST_ENTRY Entry;
     ULONG uCount = 0;
@@ -456,7 +475,8 @@ ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex)
 
 
 VOID
-ScrollUpGenericList (PGENERIC_LIST List)
+ScrollUpGenericList(
+    PGENERIC_LIST List)
 {
     PLIST_ENTRY Entry;
 
@@ -483,7 +503,8 @@ ScrollUpGenericList (PGENERIC_LIST List)
 
 
 VOID
-RedrawGenericList(PGENERIC_LIST List)
+RedrawGenericList(
+    PGENERIC_LIST List)
 {
     if (List->CurrentEntry == NULL)
         return;
@@ -497,7 +518,9 @@ RedrawGenericList(PGENERIC_LIST List)
 
 
 VOID
-SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry)
+SetCurrentListEntry(
+    PGENERIC_LIST List,
+    PGENERIC_LIST_ENTRY Entry)
 {
     if (Entry->List != List)
         return;
@@ -506,14 +529,16 @@ SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry)
 
 
 PGENERIC_LIST_ENTRY
-GetCurrentListEntry(PGENERIC_LIST List)
+GetCurrentListEntry(
+    PGENERIC_LIST List)
 {
     return List->CurrentEntry;
 }
 
 
 PGENERIC_LIST_ENTRY
-GetFirstListEntry(PGENERIC_LIST List)
+GetFirstListEntry(
+    PGENERIC_LIST List)
 {
     PLIST_ENTRY Entry = List->ListHead.Flink;
 
@@ -524,7 +549,8 @@ GetFirstListEntry(PGENERIC_LIST List)
 
 
 PGENERIC_LIST_ENTRY
-GetNextListEntry(PGENERIC_LIST_ENTRY Entry)
+GetNextListEntry(
+    PGENERIC_LIST_ENTRY Entry)
 {
     PLIST_ENTRY Next = Entry->Entry.Flink;
 
@@ -535,21 +561,25 @@ GetNextListEntry(PGENERIC_LIST_ENTRY Entry)
 
 
 PVOID
-GetListEntryUserData(PGENERIC_LIST_ENTRY List)
+GetListEntryUserData(
+    PGENERIC_LIST_ENTRY List)
 {
     return List->UserData;
 }
 
 
 LPCSTR
-GetListEntryText(PGENERIC_LIST_ENTRY List)
+GetListEntryText(
+    PGENERIC_LIST_ENTRY List)
 {
     return List->Text;
 }
 
 
 VOID
-GenericListKeyPress (PGENERIC_LIST GenericList, CHAR AsciChar)
+GenericListKeyPress(
+    PGENERIC_LIST GenericList,
+    CHAR AsciChar)
 {
     PGENERIC_LIST_ENTRY ListEntry;
     PGENERIC_LIST_ENTRY OldListEntry;
@@ -609,14 +639,16 @@ End:
 
 
 VOID
-SaveGenericListState(PGENERIC_LIST List)
+SaveGenericListState(
+    PGENERIC_LIST List)
 {
     List->BackupEntry = List->CurrentEntry;
 }
 
 
 VOID
-RestoreGenericListState(PGENERIC_LIST List)
+RestoreGenericListState(
+    PGENERIC_LIST List)
 {
     List->CurrentEntry = List->BackupEntry;
 }
index 8b09a5e..bfe9020 100644 (file)
@@ -35,68 +35,90 @@ PGENERIC_LIST
 CreateGenericList(VOID);
 
 VOID
-DestroyGenericList(PGENERIC_LIST List,
-                   BOOLEAN FreeUserData);
+DestroyGenericList(
+    PGENERIC_LIST List,
+    BOOLEAN FreeUserData);
 
 BOOLEAN
-AppendGenericListEntry(PGENERIC_LIST List,
-                       PCHAR Text,
-                       PVOID UserData,
-                       BOOLEAN Current);
+AppendGenericListEntry(
+    PGENERIC_LIST List,
+    PCHAR Text,
+    PVOID UserData,
+    BOOLEAN Current);
 
 VOID
-DrawGenericList(PGENERIC_LIST List,
-                SHORT Left,
-                SHORT Top,
-                SHORT Right,
-                SHORT Bottom);
+DrawGenericList(
+    PGENERIC_LIST List,
+    SHORT Left,
+    SHORT Top,
+    SHORT Right,
+    SHORT Bottom);
 
 VOID
-DrawScrollBarGenericLis(PGENERIC_LIST List);
+DrawScrollBarGenericLis(
+    PGENERIC_LIST List);
 
 VOID
-ScrollDownGenericList(PGENERIC_LIST List);
+ScrollDownGenericList(
+    PGENERIC_LIST List);
 
 VOID
-ScrollUpGenericList(PGENERIC_LIST List);
+ScrollUpGenericList(
+    PGENERIC_LIST List);
 
 VOID
-ScrollPageDownGenericList(PGENERIC_LIST List);
+ScrollPageDownGenericList(
+    PGENERIC_LIST List);
 
 VOID
-ScrollPageUpGenericList(PGENERIC_LIST List);
+ScrollPageUpGenericList(
+    PGENERIC_LIST List);
 
 VOID
-ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex);
+ScrollToPositionGenericList(
+    PGENERIC_LIST List,
+    ULONG uIndex);
 
 VOID
-RedrawGenericList(PGENERIC_LIST List);
+RedrawGenericList(
+    PGENERIC_LIST List);
 
 VOID
-SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry);
+SetCurrentListEntry(
+    PGENERIC_LIST List,
+    PGENERIC_LIST_ENTRY Entry);
 
 PGENERIC_LIST_ENTRY
-GetCurrentListEntry(PGENERIC_LIST List);
+GetCurrentListEntry(
+    PGENERIC_LIST List);
 
 PGENERIC_LIST_ENTRY
-GetFirstListEntry(PGENERIC_LIST List);
+GetFirstListEntry(
+    PGENERIC_LIST List);
 
 PGENERIC_LIST_ENTRY
-GetNextListEntry(PGENERIC_LIST_ENTRY Entry);
+GetNextListEntry(
+    PGENERIC_LIST_ENTRY Entry);
 
 PVOID
-GetListEntryUserData(PGENERIC_LIST_ENTRY List);
+GetListEntryUserData(
+    PGENERIC_LIST_ENTRY List);
 
 LPCSTR
-GetListEntryText(PGENERIC_LIST_ENTRY List);
+GetListEntryText(
+    PGENERIC_LIST_ENTRY List);
 
 VOID
-SaveGenericListState(PGENERIC_LIST List);
+SaveGenericListState(
+    PGENERIC_LIST List);
 
 VOID
-RestoreGenericListState(PGENERIC_LIST List);
+RestoreGenericListState(
+    PGENERIC_LIST List);
 
 VOID
-GenericListKeyPress (PGENERIC_LIST List, CHAR AsciChar);
+GenericListKeyPress(
+    PGENERIC_LIST List,
+    CHAR AsciChar);
 
 /* EOF */
index 14a3a51..6d8a84b 100644 (file)
 #endif
 
 BOOLEAN
-HOST_InitConsole(
-       VOID);
+HOST_InitConsole(VOID);
 
 BOOLEAN
-HOST_InitMemory(
-       VOID);
+HOST_InitMemory(VOID);
 
 BOOLEAN
 HOST_CreateFileSystemList(
-       IN PFILE_SYSTEM_LIST List);
+    IN PFILE_SYSTEM_LIST List);
 
 BOOLEAN
 HOST_FormatPartition(
-       IN PFILE_SYSTEM_ITEM FileSystem,
-       IN PCUNICODE_STRING DriveRoot,
-       IN PFMIFSCALLBACK Callback);
+    IN PFILE_SYSTEM_ITEM FileSystem,
+    IN PCUNICODE_STRING DriveRoot,
+    IN PFMIFSCALLBACK Callback);
index e2ea1b4..1eb6d66 100644 (file)
 
 #ifdef __REACTOS__
 
-BOOL WINAPI
+BOOL
+WINAPI
 InfpFindFirstLineW(
-       IN HINF InfHandle,
-       IN PCWSTR Section,
-       IN PCWSTR Key,
-       IN OUT PINFCONTEXT Context)
+    IN HINF InfHandle,
+    IN PCWSTR Section,
+    IN PCWSTR Key,
+    IN OUT PINFCONTEXT Context)
 {
-       PINFCONTEXT pContext;
-       BOOL ret;
+    PINFCONTEXT pContext;
+    BOOL ret;
 
-       ret = InfFindFirstLine(InfHandle, Section, Key, &pContext);
-       if (!ret)
-               return FALSE;
+    ret = InfFindFirstLine(InfHandle, Section, Key, &pContext);
+    if (!ret)
+        return FALSE;
 
-       memcpy(Context, pContext, sizeof(INFCONTEXT));
-       InfFreeContext(pContext);
-       return TRUE;
+    memcpy(Context, pContext, sizeof(INFCONTEXT));
+    InfFreeContext(pContext);
+    return TRUE;
 }
 
-HINF WINAPI
+
+HINF
+WINAPI
 InfpOpenInfFileW(
-       IN PCWSTR FileName,
-       IN PCWSTR InfClass,
-       IN DWORD InfStyle,
-       IN LCID LocaleId,
-       OUT PUINT ErrorLine)
+    IN PCWSTR FileName,
+    IN PCWSTR InfClass,
+    IN DWORD InfStyle,
+    IN LCID LocaleId,
+    OUT PUINT ErrorLine)
 {
-       HINF hInf = NULL;
-       UNICODE_STRING FileNameU;
-       ULONG ErrorLineUL;
-       NTSTATUS Status;
-
-       RtlInitUnicodeString(&FileNameU, FileName);
-       Status = InfOpenFile(
-               &hInf,
-               &FileNameU,
-               LANGIDFROMLCID(LocaleId),
-               &ErrorLineUL);
-       *ErrorLine = (UINT)ErrorLineUL;
-       if (!NT_SUCCESS(Status))
-               return INVALID_HANDLE_VALUE;
-
-       return hInf;
+    HINF hInf = NULL;
+    UNICODE_STRING FileNameU;
+    ULONG ErrorLineUL;
+    NTSTATUS Status;
+
+    RtlInitUnicodeString(&FileNameU, FileName);
+    Status = InfOpenFile(&hInf,
+                         &FileNameU,
+                         LANGIDFROMLCID(LocaleId),
+                         &ErrorLineUL);
+    *ErrorLine = (UINT)ErrorLineUL;
+    if (!NT_SUCCESS(Status))
+        return INVALID_HANDLE_VALUE;
+
+    return hInf;
 }
-
 #endif /* __REACTOS__ */
 
+
 BOOLEAN
 INF_GetData(
-       IN PINFCONTEXT Context,
-       OUT PWCHAR *Key,
-       OUT PWCHAR *Data)
+    IN PINFCONTEXT Context,
+    OUT PWCHAR *Key,
+    OUT PWCHAR *Data)
 {
 #ifdef __REACTOS__
-       return InfGetData(Context, Key, Data);
+    return InfGetData(Context, Key, Data);
 #else
-       static PWCHAR pLastCallData[4] = { NULL, NULL, NULL, NULL };
-       static DWORD currentIndex = 0;
-       DWORD dwSize, i;
-       BOOL ret;
-
-       currentIndex ^= 2;
-
-       if (Key) *Key = NULL;
-       if (Data) *Data = NULL;
-
-       if (SetupGetFieldCount(Context) != 1)
-               return FALSE;
-
-       for (i = 0; i <= 1; i++)
-       {
-               ret = SetupGetStringFieldW(
-                       Context,
-                       i,
-                       NULL,
-                       0,
-                       &dwSize);
-               if (!ret)
-                       return FALSE;
-               HeapFree(GetProcessHeap(), 0, pLastCallData[i + currentIndex]);
-               pLastCallData[i + currentIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
-               ret = SetupGetStringFieldW(
-                       Context,
-                       i,
-                       pLastCallData[i + currentIndex],
-                       dwSize,
-                       NULL);
-               if (!ret)
-                       return FALSE;
-       }
-
-       if (Key)
-               *Key = pLastCallData[0 + currentIndex];
-       if (Data)
-               *Data = pLastCallData[1 + currentIndex];
-       return TRUE;
+    static PWCHAR pLastCallData[4] = { NULL, NULL, NULL, NULL };
+    static DWORD currentIndex = 0;
+    DWORD dwSize, i;
+    BOOL ret;
+
+    currentIndex ^= 2;
+
+    if (Key)
+        *Key = NULL;
+
+    if (Data)
+        *Data = NULL;
+
+    if (SetupGetFieldCount(Context) != 1)
+        return FALSE;
+
+    for (i = 0; i <= 1; i++)
+    {
+        ret = SetupGetStringFieldW(Context,
+                                   i,
+                                   NULL,
+                                   0,
+                                   &dwSize);
+        if (!ret)
+            return FALSE;
+
+        HeapFree(GetProcessHeap(), 0, pLastCallData[i + currentIndex]);
+        pLastCallData[i + currentIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
+        ret = SetupGetStringFieldW(Context,
+                                   i,
+                                   pLastCallData[i + currentIndex],
+                                   dwSize,
+                                   NULL);
+        if (!ret)
+            return FALSE;
+    }
+
+    if (Key)
+        *Key = pLastCallData[0 + currentIndex];
+
+    if (Data)
+        *Data = pLastCallData[1 + currentIndex];
+
+    return TRUE;
 #endif /* !__REACTOS__ */
 }
 
+
 BOOLEAN
 INF_GetDataField(
-       IN PINFCONTEXT Context,
-       IN ULONG FieldIndex,
-       OUT PWCHAR *Data)
+    IN PINFCONTEXT Context,
+    IN ULONG FieldIndex,
+    OUT PWCHAR *Data)
 {
 #ifdef __REACTOS__
-       return InfGetDataField(Context, FieldIndex, Data);
+    return InfGetDataField(Context, FieldIndex, Data);
 #else
-       static PWCHAR pLastCallsData[] = { NULL, NULL, NULL };
-       static DWORD NextIndex = 0;
-       DWORD dwSize;
-       BOOL ret;
-
-       *Data = NULL;
-
-       ret = SetupGetStringFieldW(
-               Context,
-               FieldIndex,
-               NULL,
-               0,
-               &dwSize);
-       if (!ret)
-               return FALSE;
-       HeapFree(GetProcessHeap(), 0, pLastCallsData[NextIndex]);
-       pLastCallsData[NextIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
-       ret = SetupGetStringFieldW(
-               Context,
-               FieldIndex,
-               pLastCallsData[NextIndex],
-               dwSize,
-               NULL);
-       if (!ret)
-               return FALSE;
-
-       *Data = pLastCallsData[NextIndex];
-       NextIndex = (NextIndex + 1) % (sizeof(pLastCallsData) / sizeof(pLastCallsData[0]));
-       return TRUE;
+    static PWCHAR pLastCallsData[] = { NULL, NULL, NULL };
+    static DWORD NextIndex = 0;
+    DWORD dwSize;
+    BOOL ret;
+
+    *Data = NULL;
+
+    ret = SetupGetStringFieldW(Context,
+                               FieldIndex,
+                               NULL,
+                               0,
+                               &dwSize);
+    if (!ret)
+        return FALSE;
+
+    HeapFree(GetProcessHeap(), 0, pLastCallsData[NextIndex]);
+    pLastCallsData[NextIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
+    ret = SetupGetStringFieldW(Context,
+                               FieldIndex,
+                               pLastCallsData[NextIndex],
+                               dwSize,
+                               NULL);
+    if (!ret)
+        return FALSE;
+
+    *Data = pLastCallsData[NextIndex];
+    NextIndex = (NextIndex + 1) % (sizeof(pLastCallsData) / sizeof(pLastCallsData[0]));
+    return TRUE;
 #endif /* !__REACTOS__ */
 }
 
+
 HINF WINAPI
 INF_OpenBufferedFileA(
-       IN PSTR FileBuffer,
-       IN ULONG FileSize,
-       IN PCSTR InfClass,
-       IN DWORD InfStyle,
-       IN LCID LocaleId,
-       OUT PUINT ErrorLine)
+    IN PSTR FileBuffer,
+    IN ULONG FileSize,
+    IN PCSTR InfClass,
+    IN DWORD InfStyle,
+    IN LCID LocaleId,
+    OUT PUINT ErrorLine)
 {
 #ifdef __REACTOS__
-       HINF hInf = NULL;
-       ULONG ErrorLineUL;
-       NTSTATUS Status;
-
-       Status = InfOpenBufferedFile(
-               &hInf,
-               FileBuffer,
-               FileSize,
-               LANGIDFROMLCID(LocaleId),
-               &ErrorLineUL);
-       *ErrorLine = (UINT)ErrorLineUL;
-       if (!NT_SUCCESS(Status))
-               return INVALID_HANDLE_VALUE;
-
-       return hInf;
+    HINF hInf = NULL;
+    ULONG ErrorLineUL;
+    NTSTATUS Status;
+
+    Status = InfOpenBufferedFile(&hInf,
+                                 FileBuffer,
+                                 FileSize,
+                                 LANGIDFROMLCID(LocaleId),
+                                 &ErrorLineUL);
+    *ErrorLine = (UINT)ErrorLineUL;
+    if (!NT_SUCCESS(Status))
+        return INVALID_HANDLE_VALUE;
+
+    return hInf;
 #else
-       return INVALID_HANDLE_VALUE;
+    return INVALID_HANDLE_VALUE;
 #endif /* !__REACTOS__ */
 }
 
index ba0e45a..83133f9 100644 (file)
  * Delete it once we don't use inflib anymore */
 typedef struct _INFCONTEXT
 {
-       PVOID Inf;
-       PVOID Section;
-       PVOID Line;
+    PVOID Inf;
+    PVOID Section;
+    PVOID Line;
 } INFCONTEXT;
 
-BOOL WINAPI
+BOOL
+WINAPI
 InfpFindFirstLineW(
-       IN HINF InfHandle,
-       IN PCWSTR Section,
-       IN PCWSTR Key,
-       IN OUT PINFCONTEXT Context);
+    IN HINF InfHandle,
+    IN PCWSTR Section,
+    IN PCWSTR Key,
+    IN OUT PINFCONTEXT Context);
 
-HINF WINAPI
+HINF
+WINAPI
 InfpOpenInfFileW(
-       IN PCWSTR FileName,
-       IN PCWSTR InfClass,
-       IN DWORD InfStyle,
-       IN LCID LocaleId,
-       OUT PUINT ErrorLine);
+    IN PCWSTR FileName,
+    IN PCWSTR InfClass,
+    IN DWORD InfStyle,
+    IN LCID LocaleId,
+    OUT PUINT ErrorLine);
 
 #endif /* __REACTOS__ */
 
 BOOLEAN
 INF_GetData(
-       IN PINFCONTEXT Context,
-       OUT PWCHAR *Key,
-       OUT PWCHAR *Data);
+    IN PINFCONTEXT Context,
+    OUT PWCHAR *Key,
+    OUT PWCHAR *Data);
 
 BOOLEAN
 INF_GetDataField(
-       IN PINFCONTEXT Context,
-       IN ULONG FieldIndex,
-       OUT PWCHAR *Data);
+    IN PINFCONTEXT Context,
+    IN ULONG FieldIndex,
+    OUT PWCHAR *Data);
 
 HINF WINAPI
 INF_OpenBufferedFileA(
-       IN PSTR FileBuffer,
-       IN ULONG FileSize,
-       IN PCSTR InfClass,
-       IN DWORD InfStyle,
-       IN LCID LocaleId,
-       OUT PUINT ErrorLine);
+    IN PSTR FileBuffer,
+    IN ULONG FileSize,
+    IN PCSTR InfClass,
+    IN DWORD InfStyle,
+    IN LCID LocaleId,
+    OUT PUINT ErrorLine);
 
 /* EOF */
index fa40dc1..0b8dff5 100644 (file)
 
 /* PRIVATE FUNCTIONS ********************************************************/
 
-static PINICACHEKEY
-IniCacheFreeKey(PINICACHEKEY Key)
+static
+PINICACHEKEY
+IniCacheFreeKey(
+    PINICACHEKEY Key)
 {
-  PINICACHEKEY Next;
+    PINICACHEKEY Next;
 
-  if (Key == NULL)
+    if (Key == NULL)
     {
-      return(NULL);
+        return NULL;
     }
 
-  Next = Key->Next;
-  if (Key->Name != NULL)
+    Next = Key->Next;
+    if (Key->Name != NULL)
     {
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Key->Name);
-      Key->Name = NULL;
+        RtlFreeHeap(ProcessHeap, 0, Key->Name);
+        Key->Name = NULL;
     }
 
-  if (Key->Data != NULL)
+    if (Key->Data != NULL)
     {
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Key->Data);
-      Key->Data = NULL;
+        RtlFreeHeap(ProcessHeap, 0, Key->Data);
+        Key->Data = NULL;
     }
 
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Key);
+    RtlFreeHeap(ProcessHeap, 0, Key);
 
-  return(Next);
+    return Next;
 }
 
 
-static PINICACHESECTION
-IniCacheFreeSection(PINICACHESECTION Section)
+static
+PINICACHESECTION
+IniCacheFreeSection(
+    PINICACHESECTION Section)
 {
-  PINICACHESECTION Next;
+    PINICACHESECTION Next;
 
-  if (Section == NULL)
+    if (Section == NULL)
     {
-      return(NULL);
+        return NULL;
     }
 
-  Next = Section->Next;
-  while (Section->FirstKey != NULL)
+    Next = Section->Next;
+    while (Section->FirstKey != NULL)
     {
-      Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
+        Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
     }
-  Section->LastKey = NULL;
+    Section->LastKey = NULL;
 
-  if (Section->Name != NULL)
+    if (Section->Name != NULL)
     {
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Section->Name);
-      Section->Name = NULL;
+        RtlFreeHeap(ProcessHeap, 0, Section->Name);
+        Section->Name = NULL;
     }
 
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Section);
+    RtlFreeHeap(ProcessHeap, 0, Section);
 
-  return(Next);
+    return Next;
 }
 
 
-static PINICACHEKEY
-IniCacheFindKey(PINICACHESECTION Section,
-               PWCHAR Name,
-               ULONG NameLength)
+static
+PINICACHEKEY
+IniCacheFindKey(
+     PINICACHESECTION Section,
+     PWCHAR Name,
+     ULONG NameLength)
 {
-  PINICACHEKEY Key;
+    PINICACHEKEY Key;
 
-  Key = Section->FirstKey;
-  while (Key != NULL)
+    Key = Section->FirstKey;
+    while (Key != NULL)
     {
-      if (NameLength == wcslen(Key->Name))
-       {
-         if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
-           break;
-       }
+        if (NameLength == wcslen(Key->Name))
+        {
+            if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
+                break;
+        }
 
-      Key = Key->Next;
+        Key = Key->Next;
     }
 
-  return(Key);
+    return Key;
 }
 
 
-static PINICACHEKEY
-IniCacheAddKey(PINICACHESECTION Section,
-              PCHAR Name,
-              ULONG NameLength,
-              PCHAR Data,
-              ULONG DataLength)
+static
+PINICACHEKEY
+IniCacheAddKey(
+    PINICACHESECTION Section,
+    PCHAR Name,
+    ULONG NameLength,
+    PCHAR Data,
+    ULONG DataLength)
 {
-  PINICACHEKEY Key;
-  ULONG i;
+    PINICACHEKEY Key;
+    ULONG i;
 
-  Key = NULL;
+    Key = NULL;
 
-  if (Section == NULL ||
-      Name == NULL ||
-      NameLength == 0 ||
-      Data == NULL ||
-      DataLength == 0)
+    if (Section == NULL ||
+        Name == NULL ||
+        NameLength == 0 ||
+        Data == NULL ||
+        DataLength == 0)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
-                                     0,
-                                     sizeof(INICACHEKEY));
-  if (Key == NULL)
+    Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+                                        0,
+                                        sizeof(INICACHEKEY));
+    if (Key == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
 
-  RtlZeroMemory(Key,
-               sizeof(INICACHEKEY));
+    RtlZeroMemory(Key,
+                  sizeof(INICACHEKEY));
 
-
-  Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                             0,
-                             (NameLength + 1) * sizeof(WCHAR));
-  if (Key->Name == NULL)
+    Key->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                        0,
+                                        (NameLength + 1) * sizeof(WCHAR));
+    if (Key->Name == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Key);
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Key);
+        return NULL;
     }
 
-  /* Copy value name */
-  for (i = 0; i < NameLength; i++)
+    /* Copy value name */
+    for (i = 0; i < NameLength; i++)
     {
-      Key->Name[i] = (WCHAR)Name[i];
+        Key->Name[i] = (WCHAR)Name[i];
     }
-  Key->Name[NameLength] = 0;
-
+    Key->Name[NameLength] = 0;
 
-  Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                             0,
-                             (DataLength + 1) * sizeof(WCHAR));
-  if (Key->Data == NULL)
+    Key->Data = (WCHAR*)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);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Key->Name);
+        RtlFreeHeap(ProcessHeap, 0, Key);
+        return NULL;
     }
 
-  /* Copy value data */
-  for (i = 0; i < DataLength; i++)
+    /* Copy value data */
+    for (i = 0; i < DataLength; i++)
     {
-      Key->Data[i] = (WCHAR)Data[i];
+        Key->Data[i] = (WCHAR)Data[i];
     }
-  Key->Data[DataLength] = 0;
+    Key->Data[DataLength] = 0;
 
 
-  if (Section->FirstKey == NULL)
+    if (Section->FirstKey == NULL)
     {
-      Section->FirstKey = Key;
-      Section->LastKey = Key;
+        Section->FirstKey = Key;
+        Section->LastKey = Key;
     }
-  else
+    else
     {
-      Section->LastKey->Next = Key;
-      Key->Prev = Section->LastKey;
-      Section->LastKey = Key;
+        Section->LastKey->Next = Key;
+        Key->Prev = Section->LastKey;
+        Section->LastKey = Key;
     }
 
-  return(Key);
+  return Key;
 }
 
+
 #if 0
-static PINICACHESECTION
-IniCacheFindSection(PINICACHE Cache,
-                   PWCHAR Name,
-                   ULONG NameLength)
+static
+PINICACHESECTION
+IniCacheFindSection(
+    PINICACHE Cache,
+    PWCHAR Name,
+    ULONG NameLength)
 {
-  PINICACHESECTION Section = NULL;
+    PINICACHESECTION Section = NULL;
 
-  if (Cache == NULL || Name == NULL || NameLength == 0)
+    if (Cache == NULL || Name == NULL || NameLength == 0)
     {
-      return(NULL);
+        return NULL;
     }
 
-  Section = Cache->FirstSection;
+    Section = Cache->FirstSection;
 
-  /* iterate through list of sections */
-  while (Section != NULL)
+    /* 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;
-       }
+        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;
+        /* get the next section*/
+        Section = Section->Next;
     }
 
-  return(Section);
+    return Section;
 }
 #endif
 
-static PINICACHESECTION
-IniCacheAddSection(PINICACHE Cache,
-                  PCHAR Name,
-                  ULONG NameLength)
+
+static
+PINICACHESECTION
+IniCacheAddSection(
+    PINICACHE Cache,
+    PCHAR Name,
+    ULONG NameLength)
 {
-  PINICACHESECTION Section = NULL;
-  ULONG i;
+    PINICACHESECTION Section = NULL;
+    ULONG i;
 
-  if (Cache == NULL || Name == NULL || NameLength == 0)
+    if (Cache == NULL || Name == NULL || NameLength == 0)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
-                                             0,
-                                             sizeof(INICACHESECTION));
-  if (Section == NULL)
+    Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+                                                0,
+                                                sizeof(INICACHESECTION));
+    if (Section == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
-  RtlZeroMemory(Section,
-               sizeof(INICACHESECTION));
 
-  /* Allocate and initialize section name */
-  Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                 0,
-                                 (NameLength + 1) * sizeof(WCHAR));
-  if (Section->Name == NULL)
+    RtlZeroMemory(Section, sizeof(INICACHESECTION));
+
+    /* Allocate and initialize section name */
+    Section->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                            0,
+                                            (NameLength + 1) * sizeof(WCHAR));
+    if (Section->Name == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Section);
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Section);
+        return NULL;
     }
 
-  /* Copy section name */
-  for (i = 0; i < NameLength; i++)
+    /* Copy section name */
+    for (i = 0; i < NameLength; i++)
     {
-      Section->Name[i] = (WCHAR)Name[i];
+        Section->Name[i] = (WCHAR)Name[i];
     }
-  Section->Name[NameLength] = 0;
+    Section->Name[NameLength] = 0;
 
-  /* Append section */
-  if (Cache->FirstSection == NULL)
+    /* Append section */
+    if (Cache->FirstSection == NULL)
     {
-      Cache->FirstSection = Section;
-      Cache->LastSection = Section;
+        Cache->FirstSection = Section;
+        Cache->LastSection = Section;
     }
-  else
+    else
     {
-      Cache->LastSection->Next = Section;
-      Section->Prev = Cache->LastSection;
-      Cache->LastSection = Section;
+        Cache->LastSection->Next = Section;
+        Section->Prev = Cache->LastSection;
+        Cache->LastSection = Section;
     }
 
-  return(Section);
+    return Section;
 }
 
 
-static PCHAR
-IniCacheSkipWhitespace(PCHAR Ptr)
+static
+PCHAR
+IniCacheSkipWhitespace(
+    PCHAR Ptr)
 {
-  while (*Ptr != 0 && isspace(*Ptr))
-    Ptr++;
+    while (*Ptr != 0 && isspace(*Ptr))
+        Ptr++;
 
-  return((*Ptr == 0) ? NULL : Ptr);
+    return (*Ptr == 0) ? NULL : Ptr;
 }
 
 
-static PCHAR
-IniCacheSkipToNextSection(PCHAR Ptr)
+static
+PCHAR
+IniCacheSkipToNextSection(
+    PCHAR Ptr)
 {
-  while (*Ptr != 0 && *Ptr != '[')
+    while (*Ptr != 0 && *Ptr != '[')
     {
-      while (*Ptr != 0 && *Ptr != L'\n')
-       {
-         Ptr++;
-       }
-      Ptr++;
+        while (*Ptr != 0 && *Ptr != L'\n')
+        {
+            Ptr++;
+        }
+
+        Ptr++;
     }
 
-  return((*Ptr == 0) ? NULL : Ptr);
+    return (*Ptr == 0) ? NULL : Ptr;
 }
 
 
-static PCHAR
-IniCacheGetSectionName(PCHAR Ptr,
-                      PCHAR *NamePtr,
-                      PULONG NameSize)
+static
+PCHAR
+IniCacheGetSectionName(
+    PCHAR Ptr,
+    PCHAR *NamePtr,
+    PULONG NameSize)
 {
-  ULONG Size = 0;
-  CHAR Name[256];
+    ULONG Size = 0;
+    CHAR Name[256];
 
-  *NamePtr = NULL;
-  *NameSize = 0;
+    *NamePtr = NULL;
+    *NameSize = 0;
 
-  /* skip whitespace */
-  while (*Ptr != 0 && isspace(*Ptr))
+    /* skip whitespace */
+    while (*Ptr != 0 && isspace(*Ptr))
     {
-      Ptr++;
+        Ptr++;
     }
 
-  *NamePtr = Ptr;
+    *NamePtr = Ptr;
 
-  while (*Ptr != 0 && *Ptr != ']')
+    while (*Ptr != 0 && *Ptr != ']')
     {
-      Size++;
-      Ptr++;
+        Size++;
+        Ptr++;
     }
+    Ptr++;
 
-  Ptr++;
-
-  while (*Ptr != 0 && *Ptr != L'\n')
+    while (*Ptr != 0 && *Ptr != L'\n')
     {
-      Ptr++;
+        Ptr++;
     }
-  Ptr++;
+    Ptr++;
 
-  *NameSize = Size;
+    *NameSize = Size;
 
-  strncpy(Name, *NamePtr, Size);
-  Name[Size] = 0;
+    strncpy(Name, *NamePtr, Size);
+    Name[Size] = 0;
 
-  DPRINT("SectionName: '%s'\n", Name);
+    DPRINT("SectionName: '%s'\n", Name);
 
-  return(Ptr);
+    return Ptr;
 }
 
 
-static PCHAR
-IniCacheGetKeyName(PCHAR Ptr,
-                  PCHAR *NamePtr,
-                  PULONG NameSize)
+static
+PCHAR
+IniCacheGetKeyName(
+    PCHAR Ptr,
+    PCHAR *NamePtr,
+    PULONG NameSize)
 {
-  ULONG Size = 0;
+    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);
+    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,
-                   BOOLEAN String)
+static
+PCHAR
+IniCacheGetKeyValue(
+    PCHAR Ptr,
+    PCHAR *DataPtr,
+    PULONG DataSize,
+    BOOLEAN String)
 {
-  ULONG Size = 0;
+    ULONG Size = 0;
 
-  *DataPtr = NULL;
-  *DataSize = 0;
+    *DataPtr = NULL;
+    *DataSize = 0;
 
-  /* Skip whitespace */
-  while (*Ptr != 0 && isspace(*Ptr))
+    /* Skip whitespace */
+    while (*Ptr != 0 && isspace(*Ptr))
     {
-      Ptr++;
+        Ptr++;
     }
 
-  /* Check and skip '=' */
-  if (*Ptr != '=')
+    /* Check and skip '=' */
+    if (*Ptr != '=')
     {
-      return(NULL);
+        return NULL;
     }
-  Ptr++;
+    Ptr++;
 
-  /* Skip whitespace */
-  while (*Ptr != 0 && isspace(*Ptr))
+    /* Skip whitespace */
+    while (*Ptr != 0 && isspace(*Ptr))
     {
-      Ptr++;
+        Ptr++;
     }
 
-  if (*Ptr == '"' && String)
+    if (*Ptr == '"' && String)
     {
-      Ptr++;
+        Ptr++;
+
+        /* Get data */
+        *DataPtr = Ptr;
+        while (*Ptr != '"')
+        {
+            Ptr++;
+            Size++;
+        }
+        Ptr++;
 
-      /* Get data */
-      *DataPtr = Ptr;
-      while (*Ptr != '"')
-       {
-         Ptr++;
-         Size++;
-       }
-      Ptr++;
-      while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
-       {
-         Ptr++;
-       }
+        while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
+        {
+            Ptr++;
+        }
     }
-  else
+    else
     {
-      /* Get data */
-      *DataPtr = Ptr;
-      while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
-       {
-         Ptr++;
-         Size++;
-       }
+        /* Get data */
+        *DataPtr = Ptr;
+        while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
+        {
+            Ptr++;
+            Size++;
+        }
     }
 
-  /* Skip to next line */
-  if (*Ptr == '\r')
-    Ptr++;
-  if (*Ptr == '\n')
-    Ptr++;
+    /* Skip to next line */
+    if (*Ptr == '\r')
+        Ptr++;
+    if (*Ptr == '\n')
+        Ptr++;
 
-  *DataSize = Size;
+    *DataSize = Size;
 
-  return(Ptr);
+    return Ptr;
 }
 
 
-
-
 /* PUBLIC FUNCTIONS *********************************************************/
 
 NTSTATUS
-IniCacheLoad(PINICACHE *Cache,
-            PUNICODE_STRING FileName,
-            BOOLEAN String)
+IniCacheLoad(
+    PINICACHE *Cache,
+    PUNICODE_STRING FileName,
+    BOOLEAN 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;
-
-  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_SYNCHRONOUS_IO_NONALERT | 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 (!NT_SUCCESS(Status))
-    {
-      DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
-      NtClose(FileHandle);
-      return(Status);
-    }
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    FILE_STANDARD_INFORMATION FileInfo;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE FileHandle;
+    NTSTATUS Status;
+    PCHAR FileBuffer;
+    ULONG FileLength;
+    PCHAR Ptr;
+    LARGE_INTEGER FileOffset;
+
+    PINICACHESECTION Section;
+    PINICACHEKEY Key;
+
+    PCHAR SectionName;
+    ULONG SectionNameSize;
+
+    PCHAR KeyName;
+    ULONG KeyNameSize;
 
-  FileLength = FileInfo.EndOfFile.u.LowPart;
+    PCHAR KeyValue;
+    ULONG KeyValueSize;
 
-  DPRINT("File size: %lu\n", FileLength);
+    *Cache = NULL;
 
-  /* Allocate file buffer */
-  FileBuffer = (CHAR*) RtlAllocateHeap(ProcessHeap,
-                              0,
-                              FileLength + 1);
-  if (FileBuffer == NULL)
+    /* Open ini file */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               FileName,
+                               0,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        GENERIC_READ | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+    if (!NT_SUCCESS(Status))
     {
-      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);
-
-  /* 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);
+        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 (!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 = (CHAR*)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);
+
+    /* 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)
+IniCacheDestroy(
+    PINICACHE Cache)
 {
-  if (Cache == NULL)
+    if (Cache == NULL)
     {
-      return;
+        return;
     }
 
-  while (Cache->FirstSection != NULL)
+    while (Cache->FirstSection != NULL)
     {
-      Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
+        Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
     }
-  Cache->LastSection = NULL;
+    Cache->LastSection = NULL;
 
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Cache);
+    RtlFreeHeap(ProcessHeap, 0, Cache);
 }
 
 
 PINICACHESECTION
-IniCacheGetSection(PINICACHE Cache,
-                  PWCHAR Name)
+IniCacheGetSection(
+    PINICACHE Cache,
+    PWCHAR Name)
 {
-  PINICACHESECTION Section = NULL;
+    PINICACHESECTION Section = NULL;
 
-  if (Cache == NULL || Name == NULL)
+    if (Cache == NULL || Name == NULL)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  /* Iterate through list of sections */
-  Section = Cache->FirstSection;
-  while (Section != NULL)
+    /* Iterate through list of sections */
+    Section = Cache->FirstSection;
+    while (Section != NULL)
     {
-      DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
+        DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
 
-      /* Are the section names the same? */
-      if (_wcsicmp(Section->Name, Name) == 0)
-       return(Section);
+        /* Are the section names the same? */
+        if (_wcsicmp(Section->Name, Name) == 0)
+            return Section;
 
-      /* Get the next section */
-      Section = Section->Next;
+        /* Get the next section */
+        Section = Section->Next;
     }
 
-  DPRINT("Section not found\n");
+    DPRINT("Section not found\n");
 
-  return(NULL);
+    return NULL;
 }
 
 
 NTSTATUS
-IniCacheGetKey(PINICACHESECTION Section,
-              PWCHAR KeyName,
-              PWCHAR *KeyData)
+IniCacheGetKey(
+    PINICACHESECTION Section,
+    PWCHAR KeyName,
+    PWCHAR *KeyData)
 {
-  PINICACHEKEY Key;
+    PINICACHEKEY Key;
 
-  if (Section == NULL || KeyName == NULL || KeyData == NULL)
+    if (Section == NULL || KeyName == NULL || KeyData == NULL)
     {
-      DPRINT("Invalid parameter\n");
-      return(STATUS_INVALID_PARAMETER);
+        DPRINT("Invalid parameter\n");
+        return STATUS_INVALID_PARAMETER;
     }
 
-  *KeyData = NULL;
+    *KeyData = NULL;
 
-  Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
-  if (Key == NULL)
+    Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
+    if (Key == NULL)
     {
-      return(STATUS_INVALID_PARAMETER);
+        return STATUS_INVALID_PARAMETER;
     }
 
-  *KeyData = Key->Data;
+    *KeyData = Key->Data;
 
-  return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
 
 PINICACHEITERATOR
-IniCacheFindFirstValue(PINICACHESECTION Section,
-                      PWCHAR *KeyName,
-                      PWCHAR *KeyData)
+IniCacheFindFirstValue(
+    PINICACHESECTION Section,
+    PWCHAR *KeyName,
+    PWCHAR *KeyData)
 {
-  PINICACHEITERATOR Iterator;
-  PINICACHEKEY Key;
+    PINICACHEITERATOR Iterator;
+    PINICACHEKEY Key;
 
-  if (Section == NULL || KeyName == NULL || KeyData == NULL)
+    if (Section == NULL || KeyName == NULL || KeyData == NULL)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  Key = Section->FirstKey;
-  if (Key == NULL)
+    Key = Section->FirstKey;
+    if (Key == NULL)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  *KeyName = Key->Name;
-  *KeyData = Key->Data;
+    *KeyName = Key->Name;
+    *KeyData = Key->Data;
 
-  Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
-                                               0,
-                                               sizeof(INICACHEITERATOR));
-  if (Iterator == NULL)
+    Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
+                                                  0,
+                                                  sizeof(INICACHEITERATOR));
+    if (Iterator == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
 
-  Iterator->Section = Section;
-  Iterator->Key = Key;
+    Iterator->Section = Section;
+    Iterator->Key = Key;
 
-  return(Iterator);
+    return Iterator;
 }
 
 
 BOOLEAN
-IniCacheFindNextValue(PINICACHEITERATOR Iterator,
-                     PWCHAR *KeyName,
-                     PWCHAR *KeyData)
+IniCacheFindNextValue(
+    PINICACHEITERATOR Iterator,
+    PWCHAR *KeyName,
+    PWCHAR *KeyData)
 {
-  PINICACHEKEY Key;
+    PINICACHEKEY Key;
 
-  if (Iterator == NULL || KeyName == NULL || KeyData == NULL)
+    if (Iterator == NULL || KeyName == NULL || KeyData == NULL)
     {
-      DPRINT("Invalid parameter\n");
-      return(FALSE);
+        DPRINT("Invalid parameter\n");
+        return FALSE;
     }
 
-  Key = Iterator->Key->Next;
-  if (Key == NULL)
+    Key = Iterator->Key->Next;
+    if (Key == NULL)
     {
-      DPRINT("No more entries\n");
-      return(FALSE);
+        DPRINT("No more entries\n");
+        return FALSE;
     }
 
-  *KeyName = Key->Name;
-  *KeyData = Key->Data;
+    *KeyName = Key->Name;
+    *KeyData = Key->Data;
 
-  Iterator->Key = Key;
+    Iterator->Key = Key;
 
-  return(TRUE);
+    return TRUE;
 }
 
 
 VOID
-IniCacheFindClose(PINICACHEITERATOR Iterator)
+IniCacheFindClose(
+    PINICACHEITERATOR Iterator)
 {
-  if (Iterator == NULL)
-    return;
+    if (Iterator == NULL)
+        return;
 
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Iterator);
+    RtlFreeHeap(ProcessHeap, 0, Iterator);
 }
 
 
 PINICACHEKEY
-IniCacheInsertKey(PINICACHESECTION Section,
-                 PINICACHEKEY AnchorKey,
-                 INSERTATION_TYPE InsertationType,
-                 PWCHAR Name,
-                 PWCHAR Data)
+IniCacheInsertKey(
+    PINICACHESECTION Section,
+    PINICACHEKEY AnchorKey,
+    INSERTATION_TYPE InsertationType,
+    PWCHAR Name,
+    PWCHAR Data)
 {
-  PINICACHEKEY Key;
+    PINICACHEKEY Key;
 
-  Key = NULL;
+    Key = NULL;
 
-  if (Section == NULL ||
-      Name == NULL ||
-      *Name == 0 ||
-      Data == NULL ||
-      *Data == 0)
+    if (Section == NULL ||
+        Name == NULL ||
+        *Name == 0 ||
+        Data == NULL ||
+        *Data == 0)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  /* Allocate key buffer */
-  Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
-                                     0,
-                                     sizeof(INICACHEKEY));
-  if (Key == NULL)
+    /* Allocate key buffer */
+    Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+                                        0,
+                                        sizeof(INICACHEKEY));
+    if (Key == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
-  RtlZeroMemory(Key,
-               sizeof(INICACHEKEY));
 
-  /* Allocate name buffer */
-  Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                             0,
-                             (wcslen(Name) + 1) * sizeof(WCHAR));
-  if (Key->Name == NULL)
+   RtlZeroMemory(Key, sizeof(INICACHEKEY));
+
+    /* Allocate name buffer */
+    Key->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                        0,
+                                        (wcslen(Name) + 1) * sizeof(WCHAR));
+    if (Key->Name == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Key);
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Key);
+        return NULL;
     }
 
-  /* Copy value name */
-  wcscpy(Key->Name, Name);
+    /* Copy value name */
+    wcscpy(Key->Name, Name);
 
-  /* Allocate data buffer */
-  Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                             0,
-                             (wcslen(Data) + 1) * sizeof(WCHAR));
-  if (Key->Data == NULL)
+    /* Allocate data buffer */
+    Key->Data = (WCHAR*)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);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Key->Name);
+        RtlFreeHeap(ProcessHeap, 0, Key);
+        return NULL;
     }
 
-  /* Copy value data */
-  wcscpy(Key->Data, Data);
+    /* Copy value data */
+    wcscpy(Key->Data, Data);
 
-  /* Insert key into section */
-  if (Section->FirstKey == NULL)
+    /* Insert key into section */
+    if (Section->FirstKey == NULL)
     {
-      Section->FirstKey = Key;
-      Section->LastKey = Key;
+        Section->FirstKey = Key;
+        Section->LastKey = Key;
     }
-  else if ((InsertationType == INSERT_FIRST) ||
-          ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey))))
+    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;
+        /* 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))
+    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;
+        /* 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))))
+    else if ((InsertationType == INSERT_LAST) ||
+             ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey))))
     {
-      Section->LastKey->Next = Key;
-      Key->Prev = Section->LastKey;
-      Section->LastKey = Key;
+        Section->LastKey->Next = Key;
+        Key->Prev = Section->LastKey;
+        Section->LastKey = Key;
     }
-  else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL))
+    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;
+        /* Insert after the anchor key */
+        Key->Next = AnchorKey->Next;
+        Key->Prev = AnchorKey;
+        AnchorKey->Next->Prev = Key;
+        AnchorKey->Next = Key;
     }
 
-  return(Key);
+    return Key;
 }
 
 
 PINICACHE
 IniCacheCreate(VOID)
 {
-  PINICACHE Cache;
+    PINICACHE Cache;
 
-  /* Allocate inicache header */
-  Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
-                                    0,
-                                    sizeof(INICACHE));
-  if (Cache == NULL)
+    /* Allocate inicache header */
+    Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+                                       0,
+                                       sizeof(INICACHE));
+    if (Cache == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
 
-  /* Initialize inicache header */
-  RtlZeroMemory(Cache,
-               sizeof(INICACHE));
+    /* Initialize inicache header */
+    RtlZeroMemory(Cache, sizeof(INICACHE));
 
-  return(Cache);
+    return Cache;
 }
 
 
 NTSTATUS
-IniCacheSave(PINICACHE Cache,
-            PWCHAR FileName)
+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 */
-
-  DPRINT("BufferSize: %lu\n", BufferSize);
-
-  /* Allocate file buffer */
-  Buffer = (CHAR*) 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,
-                       GENERIC_WRITE | SYNCHRONIZE,
-                       &ObjectAttributes,
-                       &IoStatusBlock,
-                       NULL,
-                       FILE_ATTRIBUTE_NORMAL,
-                       0,
-                       FILE_SUPERSEDE,
-                       FILE_SYNCHRONOUS_IO_NONALERT | 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))
+    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 */
+
+    DPRINT("BufferSize: %lu\n", BufferSize);
+
+    /* Allocate file buffer */
+    Buffer = (CHAR*)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,
+                          GENERIC_WRITE | SYNCHRONIZE,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          FILE_ATTRIBUTE_NORMAL,
+                          0,
+                          FILE_SUPERSEDE,
+                          FILE_SYNCHRONOUS_IO_NONALERT | 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);
+      RtlFreeHeap(ProcessHeap, 0, Buffer);
+      return Status;
     }
 
-  NtClose(FileHandle);
+    NtClose(FileHandle);
 
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Buffer);
+    RtlFreeHeap(ProcessHeap, 0, Buffer);
 
-  return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
 
 PINICACHESECTION
-IniCacheAppendSection(PINICACHE Cache,
-                     PWCHAR Name)
+IniCacheAppendSection(
+    PINICACHE Cache,
+    PWCHAR Name)
 {
-  PINICACHESECTION Section = NULL;
+    PINICACHESECTION Section = NULL;
 
-  if (Cache == NULL || Name == NULL || *Name == 0)
+    if (Cache == NULL || Name == NULL || *Name == 0)
     {
-      DPRINT("Invalid parameter\n");
-      return(NULL);
+        DPRINT("Invalid parameter\n");
+        return NULL;
     }
 
-  Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
-                                             0,
-                                             sizeof(INICACHESECTION));
-  if (Section == NULL)
+    Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+                                                0,
+                                                sizeof(INICACHESECTION));
+    if (Section == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        return NULL;
     }
-  RtlZeroMemory(Section,
-               sizeof(INICACHESECTION));
 
-  /* Allocate and initialize section name */
-  Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                 0,
-                                 (wcslen(Name) + 1) * sizeof(WCHAR));
-  if (Section->Name == NULL)
+    RtlZeroMemory(Section, sizeof(INICACHESECTION));
+
+    /* Allocate and initialize section name */
+    Section->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                            0,
+                                            (wcslen(Name) + 1) * sizeof(WCHAR));
+    if (Section->Name == NULL)
     {
-      DPRINT("RtlAllocateHeap() failed\n");
-      RtlFreeHeap(ProcessHeap,
-                 0,
-                 Section);
-      return(NULL);
+        DPRINT("RtlAllocateHeap() failed\n");
+        RtlFreeHeap(ProcessHeap, 0, Section);
+        return NULL;
     }
 
-  /* Copy section name */
-  wcscpy(Section->Name, Name);
+    /* Copy section name */
+    wcscpy(Section->Name, Name);
 
-  /* Append section */
-  if (Cache->FirstSection == NULL)
+    /* Append section */
+    if (Cache->FirstSection == NULL)
     {
-      Cache->FirstSection = Section;
-      Cache->LastSection = Section;
+        Cache->FirstSection = Section;
+        Cache->LastSection = Section;
     }
-  else
+    else
     {
-      Cache->LastSection->Next = Section;
-      Section->Prev = Cache->LastSection;
-      Cache->LastSection = Section;
+        Cache->LastSection->Next = Section;
+        Section->Prev = Cache->LastSection;
+        Cache->LastSection = Section;
     }
 
-  return(Section);
+    return Section;
 }
 
 /* EOF */
index bd7dd33..4da4c11 100644 (file)
 
 typedef struct _INICACHEKEY
 {
-  PWCHAR Name;
-  PWCHAR Data;
+    PWCHAR Name;
+    PWCHAR Data;
 
-  struct _INICACHEKEY *Next;
-  struct _INICACHEKEY *Prev;
+    struct _INICACHEKEY *Next;
+    struct _INICACHEKEY *Prev;
 } INICACHEKEY, *PINICACHEKEY;
 
 
 typedef struct _INICACHESECTION
 {
-  PWCHAR Name;
+    PWCHAR Name;
 
-  PINICACHEKEY FirstKey;
-  PINICACHEKEY LastKey;
+    PINICACHEKEY FirstKey;
+    PINICACHEKEY LastKey;
 
-  struct _INICACHESECTION *Next;
-  struct _INICACHESECTION *Prev;
+    struct _INICACHESECTION *Next;
+    struct _INICACHESECTION *Prev;
 } INICACHESECTION, *PINICACHESECTION;
 
 
 typedef struct _INICACHE
 {
-  PINICACHESECTION FirstSection;
-  PINICACHESECTION LastSection;
+    PINICACHESECTION FirstSection;
+    PINICACHESECTION LastSection;
 } INICACHE, *PINICACHE;
 
 
 typedef struct _PINICACHEITERATOR
 {
-  PINICACHESECTION Section;
-  PINICACHEKEY Key;
+    PINICACHESECTION Section;
+    PINICACHEKEY Key;
 } INICACHEITERATOR, *PINICACHEITERATOR;
 
 
 typedef enum
 {
-  INSERT_FIRST,
-  INSERT_BEFORE,
-  INSERT_AFTER,
-  INSERT_LAST
+    INSERT_FIRST,
+    INSERT_BEFORE,
+    INSERT_AFTER,
+    INSERT_LAST
 } INSERTATION_TYPE;
 
 /* FUNCTIONS ****************************************************************/
 
 NTSTATUS
-IniCacheLoad(PINICACHE *Cache,
-            PUNICODE_STRING FileName,
-            BOOLEAN String);
+IniCacheLoad(
+    PINICACHE *Cache,
+    PUNICODE_STRING FileName,
+    BOOLEAN String);
 
 VOID
-IniCacheDestroy(PINICACHE Cache);
+IniCacheDestroy(
+    PINICACHE Cache);
 
 PINICACHESECTION
-IniCacheGetSection(PINICACHE Cache,
-                  PWCHAR Name);
+IniCacheGetSection(
+    PINICACHE Cache,
+    PWCHAR Name);
 
 NTSTATUS
-IniCacheGetKey(PINICACHESECTION Section,
-              PWCHAR KeyName,
-              PWCHAR *KeyData);
-
-
+IniCacheGetKey(
+    PINICACHESECTION Section,
+    PWCHAR KeyName,
+    PWCHAR *KeyData);
 
 PINICACHEITERATOR
-IniCacheFindFirstValue(PINICACHESECTION Section,
-                      PWCHAR *KeyName,
-                      PWCHAR *KeyData);
+IniCacheFindFirstValue(
+    PINICACHESECTION Section,
+    PWCHAR *KeyName,
+    PWCHAR *KeyData);
 
 BOOLEAN
-IniCacheFindNextValue(PINICACHEITERATOR Iterator,
-                     PWCHAR *KeyName,
-                     PWCHAR *KeyData);
+IniCacheFindNextValue(
+    PINICACHEITERATOR Iterator,
+    PWCHAR *KeyName,
+    PWCHAR *KeyData);
 
 VOID
-IniCacheFindClose(PINICACHEITERATOR Iterator);
+IniCacheFindClose(
+    PINICACHEITERATOR Iterator);
 
 
 PINICACHEKEY
-IniCacheInsertKey(PINICACHESECTION Section,
-                 PINICACHEKEY AnchorKey,
-                 INSERTATION_TYPE InsertationType,
-                 PWCHAR Name,
-                 PWCHAR Data);
+IniCacheInsertKey(
+    PINICACHESECTION Section,
+    PINICACHEKEY AnchorKey,
+    INSERTATION_TYPE InsertationType,
+    PWCHAR Name,
+    PWCHAR Data);
 
 PINICACHE
 IniCacheCreate(VOID);
 
 NTSTATUS
-IniCacheSave(PINICACHE Cache,
-            PWCHAR FileName);
+IniCacheSave(
+    PINICACHE Cache,
+    PWCHAR FileName);
 
 PINICACHESECTION
-IniCacheAppendSection(PINICACHE Cache,
-                     PWCHAR Name);
+IniCacheAppendSection(
+    PINICACHE Cache,
+    PWCHAR Name);
 
 /* EOF */
index 71a6250..1ebcf4a 100644 (file)
@@ -63,8 +63,10 @@ FindLanguageIndex(VOID)
     return 0;
 }
 
+
 BOOLEAN
-IsLanguageAvailable(PWCHAR LanguageId)
+IsLanguageAvailable(
+    PWCHAR LanguageId)
 {
     ULONG lngIndex = 0;
 
@@ -82,7 +84,8 @@ IsLanguageAvailable(PWCHAR LanguageId)
 
 static
 const MUI_ENTRY *
-FindMUIEntriesOfPage(IN ULONG PageNumber)
+FindMUIEntriesOfPage(
+    IN ULONG PageNumber)
 {
     ULONG muiIndex = 0;
     ULONG lngIndex;
@@ -102,6 +105,7 @@ FindMUIEntriesOfPage(IN ULONG PageNumber)
     return NULL;
 }
 
+
 static
 const MUI_ERROR *
 FindMUIErrorEntries(VOID)
@@ -110,6 +114,7 @@ FindMUIErrorEntries(VOID)
     return LanguageList[lngIndex].MuiErrors;
 }
 
+
 static
 const MUI_STRING *
 FindMUIStringEntries(VOID)
@@ -118,6 +123,7 @@ FindMUIStringEntries(VOID)
     return LanguageList[lngIndex].MuiStrings;
 }
 
+
 LPCWSTR
 MUIDefaultKeyboardLayout(VOID)
 {
@@ -125,6 +131,7 @@ MUIDefaultKeyboardLayout(VOID)
     return LanguageList[lngIndex].MuiLayouts[0].LayoutID;
 }
 
+
 PWCHAR
 MUIGetGeoID(VOID)
 {
@@ -132,6 +139,7 @@ MUIGetGeoID(VOID)
     return LanguageList[lngIndex].GeoID;
 }
 
+
 const MUI_LAYOUTS *
 MUIGetLayoutsList(VOID)
 {
@@ -139,8 +147,10 @@ MUIGetLayoutsList(VOID)
     return LanguageList[lngIndex].MuiLayouts;
 }
 
+
 VOID
-MUIClearPage(IN ULONG page)
+MUIClearPage(
+    IN ULONG page)
 {
     const MUI_ENTRY * entry;
     int index;
@@ -167,8 +177,10 @@ MUIClearPage(IN ULONG page)
     while (entry[index].Buffer != NULL);
 }
 
+
 VOID
-MUIDisplayPage(IN ULONG page)
+MUIDisplayPage(
+    IN ULONG page)
 {
     const MUI_ENTRY * entry;
     int index;
@@ -196,8 +208,12 @@ MUIDisplayPage(IN ULONG page)
     while (entry[index].Buffer != NULL);
 }
 
+
 VOID
-MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent)
+MUIDisplayError(
+    IN ULONG ErrorNum,
+    OUT PINPUT_RECORD Ir,
+    IN ULONG WaitEvent)
 {
     const MUI_ERROR * entry;
 
@@ -227,8 +243,10 @@ MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent)
                WaitEvent);
 }
 
+
 LPSTR
-MUIGetString(ULONG Number)
+MUIGetString(
+    ULONG Number)
 {
     ULONG i;
     const MUI_STRING * entry;
@@ -249,15 +267,20 @@ MUIGetString(ULONG Number)
     sprintf(szErr, "Error: failed find string id %lu for language index %lu\n", Number, FindLanguageIndex());
 
     PopupError(szErr,
-                NULL,
-                NULL,
-                POPUP_WAIT_NONE);
+               NULL,
+               NULL,
+               POPUP_WAIT_NONE);
 
     return "<nostring>";
 }
 
-static BOOLEAN
-AddHotkeySettings(IN LPCWSTR Hotkey, IN LPCWSTR LangHotkey, IN LPCWSTR LayoutHotkey)
+
+static
+BOOLEAN
+AddHotkeySettings(
+    IN LPCWSTR Hotkey,
+    IN LPCWSTR LangHotkey,
+    IN LPCWSTR LayoutHotkey)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -340,8 +363,10 @@ AddHotkeySettings(IN LPCWSTR Hotkey, IN LPCWSTR LangHotkey, IN LPCWSTR LayoutHot
     return TRUE;
 }
 
+
 BOOLEAN
-AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts)
+AddKbLayoutsToRegistry(
+    IN const MUI_LAYOUTS *MuiLayouts)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -509,10 +534,12 @@ AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts)
     return TRUE;
 }
 
+
 BOOLEAN
 AddKeyboardLayouts(VOID)
 {
     ULONG lngIndex = 0;
+
     do
     {
         if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
@@ -527,8 +554,13 @@ AddKeyboardLayouts(VOID)
     return FALSE;
 }
 
-static BOOLEAN
-AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPage)
+
+static
+BOOLEAN
+AddCodepageToRegistry(
+    IN LPCWSTR ACPage,
+    IN LPCWSTR OEMCPage,
+    IN LPCWSTR MACCPage)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -603,8 +635,11 @@ AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPag
     return TRUE;
 }
 
-static BOOLEAN
-AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts)
+
+static
+BOOLEAN
+AddFontsSettingsToRegistry(
+    IN const MUI_SUBFONT * MuiSubFonts)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -654,6 +689,7 @@ AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts)
     return TRUE;
 }
 
+
 BOOLEAN
 AddCodePage(VOID)
 {
@@ -682,6 +718,7 @@ AddCodePage(VOID)
     return FALSE;
 }
 
+
 VOID
 SetConsoleCodePage(VOID)
 {
index f8074ef..bf35835 100644 (file)
@@ -54,16 +54,22 @@ typedef struct
 } MUI_LANGUAGE;
 
 BOOLEAN
-IsLanguageAvailable(PWCHAR LanguageId);
+IsLanguageAvailable(
+    PWCHAR LanguageId);
 
 VOID
-MUIDisplayPage (ULONG PageNumber);
+MUIDisplayPage(
+    ULONG PageNumber);
 
 VOID
-MUIClearPage (ULONG PageNumber);
+MUIClearPage(
+    ULONG PageNumber);
 
 VOID
-MUIDisplayError (ULONG ErrorNum, PINPUT_RECORD Ir, ULONG WaitEvent);
+MUIDisplayError(
+    ULONG ErrorNum,
+    PINPUT_RECORD Ir,
+    ULONG WaitEvent);
 
 LPCWSTR
 MUIDefaultKeyboardLayout(VOID);
@@ -75,7 +81,8 @@ const MUI_LAYOUTS *
 MUIGetLayoutsList(VOID);
 
 BOOLEAN
-AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts);
+AddKbLayoutsToRegistry(
+    IN const MUI_LAYOUTS *MuiLayouts);
 
 BOOLEAN
 AddCodePage(VOID);
@@ -87,7 +94,8 @@ VOID
 SetConsoleCodePage(VOID);
 
 LPSTR
-MUIGetString(ULONG Number);
+MUIGetString(
+    ULONG Number);
 
 #define STRING_PLEASEWAIT                1
 #define STRING_INSTALLCREATEPARTITION    2
index a27f9ba..c2c4ea0 100644 (file)
@@ -409,424 +409,424 @@ const MUI_LANGUAGE LanguageList[] =
 {
   /* Lang ID,   ANSI CP, OEM CP, MAC CP,   Language Name,                   GeoID   page strgs,error strings,    other strings, fonts,       kb layouts */
 #ifdef LANGUAGE_AF_ZA
-     {L"00000436", L"1252", L"850", L"10000", L"Afrikaans", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, afZALayouts },
+    {L"00000436", L"1252", L"850", L"10000", L"Afrikaans", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, afZALayouts },
 #endif
 #ifdef LANGUAGE_SQ_AL
     {L"0000041C", L"1250", L"852", L"10029", L"Albanian (Albania)", L"355", sqALPages, sqALErrorEntries, sqALStrings, LatinFonts, sqALLayouts },
 #endif
 #ifdef LANGUAGE_AR_SA
-     {L"00000401", L"1256", L"720", L"10004", L"Arabic (Saudi Arabia)", L"966", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSALayouts },
+    {L"00000401", L"1256", L"720", L"10004", L"Arabic (Saudi Arabia)", L"966", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSALayouts },
 #endif
 #ifdef LANGUAGE_AR_IQ
-     {L"00000801", L"1256", L"720", L"10004", L"Arabic (Iraq)", L"964", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arIQLayouts },
+    {L"00000801", L"1256", L"720", L"10004", L"Arabic (Iraq)", L"964", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arIQLayouts },
 #endif
 #ifdef LANGUAGE_AR_EG
-     {L"00000C01", L"1256", L"720", L"10004", L"Arabic (Egypt)", L"20", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arEGLayouts },
+    {L"00000C01", L"1256", L"720", L"10004", L"Arabic (Egypt)", L"20", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arEGLayouts },
 #endif
 #ifdef LANGUAGE_AR_LY
-     {L"00001001", L"1256", L"720", L"10004", L"Arabic (Libya)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLYLayouts },
+    {L"00001001", L"1256", L"720", L"10004", L"Arabic (Libya)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLYLayouts },
 #endif
 #ifdef LANGUAGE_AR_DZ
-     {L"00001401", L"1256", L"720", L"10004", L"Arabic (Algeria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arDZLayouts },
+    {L"00001401", L"1256", L"720", L"10004", L"Arabic (Algeria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arDZLayouts },
 #endif
 #ifdef LANGUAGE_AR_MA
-     {L"00001801", L"1256", L"720", L"10004", L"Arabic (Morocco)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arMALayouts },
+    {L"00001801", L"1256", L"720", L"10004", L"Arabic (Morocco)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arMALayouts },
 #endif
 #ifdef LANGUAGE_AR_TN
-     {L"00001C01", L"1256", L"720", L"10004", L"Arabic (Tunisia)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arTNLayouts },
+    {L"00001C01", L"1256", L"720", L"10004", L"Arabic (Tunisia)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arTNLayouts },
 #endif
 #ifdef LANGUAGE_AR_OM
-     {L"00002001", L"1256", L"720", L"10004", L"Arabic (Oman)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arOMLayouts },
+    {L"00002001", L"1256", L"720", L"10004", L"Arabic (Oman)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arOMLayouts },
 #endif
 #ifdef LANGUAGE_AR_YE
-     {L"00002401", L"1256", L"720", L"10004", L"Arabic (Yemen)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arYELayouts },
+    {L"00002401", L"1256", L"720", L"10004", L"Arabic (Yemen)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arYELayouts },
 #endif
 #ifdef LANGUAGE_AR_SY
-     {L"00002801", L"1256", L"720", L"10004", L"Arabic (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSYLayouts },
+    {L"00002801", L"1256", L"720", L"10004", L"Arabic (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSYLayouts },
 #endif
 #ifdef LANGUAGE_AR_JO
-     {L"00002C01", L"1256", L"720", L"10004", L"Arabic (Jordan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arJOLayouts },
+    {L"00002C01", L"1256", L"720", L"10004", L"Arabic (Jordan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arJOLayouts },
 #endif
 #ifdef LANGUAGE_AR_LB
-     {L"00003001", L"1256", L"720", L"10004", L"Arabic (Lebanon)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLBLayouts },
+    {L"00003001", L"1256", L"720", L"10004", L"Arabic (Lebanon)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLBLayouts },
 #endif
 #ifdef LANGUAGE_AR_KW
-     {L"00003401", L"1256", L"720", L"10004", L"Arabic (Kuwait)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arKWLayouts },
+    {L"00003401", L"1256", L"720", L"10004", L"Arabic (Kuwait)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arKWLayouts },
 #endif
 #ifdef LANGUAGE_AR_AE
-     {L"00003801", L"1256", L"720", L"10004", L"Arabic (U.A.E.)", L"971", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arAELayouts },
+    {L"00003801", L"1256", L"720", L"10004", L"Arabic (U.A.E.)", L"971", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arAELayouts },
 #endif
 #ifdef LANGUAGE_AR_BH
-     {L"00003C01", L"1256", L"720", L"10004", L"Arabic (Bahrain)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arBHLayouts },
+    {L"00003C01", L"1256", L"720", L"10004", L"Arabic (Bahrain)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arBHLayouts },
 #endif
 #ifdef LANGUAGE_AR_QA
-     {L"00004001", L"1256", L"720", L"10004", L"Arabic (Qatar)", L"974", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arQALayouts },
+    {L"00004001", L"1256", L"720", L"10004", L"Arabic (Qatar)", L"974", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arQALayouts },
 #endif
 #ifdef LANGUAGE_HY_AM
-     {L"0000042B", L"0", L"1", L"2", L"Armenian", L"374", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hyAMLayouts },
+    {L"0000042B", L"0", L"1", L"2", L"Armenian", L"374", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hyAMLayouts },
 #endif
 #ifdef LANGUAGE_AZ_AZ
-     {L"0000082C", L"1251", L"866", L"10007", L"Azeri (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, azAZLayouts },
+    {L"0000082C", L"1251", L"866", L"10007", L"Azeri (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, azAZLayouts },
 #endif
 #ifdef LANGUAGE_AZ_AZ
-     {L"0000042C", L"1254", L"857", L"10081", L"Azeri (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, azAZLayouts },
+    {L"0000042C", L"1254", L"857", L"10081", L"Azeri (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, azAZLayouts },
 #endif
 #ifdef LANGUAGE_EU_ES
-     {L"0000042D", L"1252", L"850", L"10000", L"Basque", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, euESLayouts },
+    {L"0000042D", L"1252", L"850", L"10000", L"Basque", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, euESLayouts },
 #endif
 #ifdef LANGUAGE_BE_BY
-     {L"00000423", L"1251", L"866", L"10007", L"Belarusian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, beBYLayouts },
+    {L"00000423", L"1251", L"866", L"10007", L"Belarusian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, beBYLayouts },
 #endif
 #ifdef LANGUAGE_BG_BG
-     {L"00000402", L"1251", L"866", L"10007", L"Bulgarian", L"359", bgBGPages, bgBGErrorEntries, bgBGStrings, CyrillicFonts, bgBGLayouts },
+    {L"00000402", L"1251", L"866", L"10007", L"Bulgarian", L"359", bgBGPages, bgBGErrorEntries, bgBGStrings, CyrillicFonts, bgBGLayouts },
 #endif
 #ifdef LANGUAGE_MY_MM
-     {L"00000455", L"0", L"1", L"2", L"Burmese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, myMMLayouts },
+    {L"00000455", L"0", L"1", L"2", L"Burmese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, myMMLayouts },
 #endif
 #ifdef LANGUAGE_CA_ES
-     {L"00000403", L"1252", L"850", L"10000", L"Catalan", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, caESLayouts },
+    {L"00000403", L"1252", L"850", L"10000", L"Catalan", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, caESLayouts },
 #endif
 #ifdef LANGUAGE_ZH_TW
-     {L"00000404", L"950", L"950", L"10008", L"Chinese (Taiwan)", L"886", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhTWLayouts },
+    {L"00000404", L"950", L"950", L"10008", L"Chinese (Taiwan)", L"886", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhTWLayouts },
 #endif
 #ifdef LANGUAGE_ZH_CN
-     {L"00000804", L"936", L"936", L"10008", L"Chinese (PRC)", L"86", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhCNLayouts },
+    {L"00000804", L"936", L"936", L"10008", L"Chinese (PRC)", L"86", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhCNLayouts },
 #endif
 #ifdef LANGUAGE_ZH_HK
-     {L"00000C04", L"950", L"950", L"10008", L"Chinese (Hong Kong S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhHKLayouts },
+    {L"00000C04", L"950", L"950", L"10008", L"Chinese (Hong Kong S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhHKLayouts },
 #endif
 #ifdef LANGUAGE_ZH_SG
-     {L"00001004", L"936", L"936", L"10008", L"Chinese (Singapore)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhSGLayouts },
+    {L"00001004", L"936", L"936", L"10008", L"Chinese (Singapore)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhSGLayouts },
 #endif
 #ifdef LANGUAGE_ZH_MO
-     {L"00001404", L"950", L"950", L"10002", L"Chinese (Macau S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhMOLayouts },
+    {L"00001404", L"950", L"950", L"10002", L"Chinese (Macau S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhMOLayouts },
 #endif
 #ifdef LANGUAGE_HR_HR
-     {L"0000041A", L"1250", L"852", L"10029", L"Croatian", L"385", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, hrHRLayouts },
+    {L"0000041A", L"1250", L"852", L"10029", L"Croatian", L"385", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, hrHRLayouts },
 #endif
 #ifdef LANGUAGE_CS_CZ
-     {L"00000405", L"1250", L"852", L"10029", L"Czech", L"420", csCZPages, csCZErrorEntries, csCZStrings, LatinFonts, csCZLayouts },
+    {L"00000405", L"1250", L"852", L"10029", L"Czech", L"420", csCZPages, csCZErrorEntries, csCZStrings, LatinFonts, csCZLayouts },
 #endif
 #ifdef LANGUAGE_DA_DK
-     {L"00000406", L"1252", L"850", L"10000", L"Danish", L"45", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, daDKLayouts },
+    {L"00000406", L"1252", L"850", L"10000", L"Danish", L"45", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, daDKLayouts },
 #endif
 #ifdef LANGUAGE_DV_MV
-     {L"00000465", L"0", L"1", L"2", L"Dhivehi (Maldives)", L"960", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, dvMVLayouts },
+    {L"00000465", L"0", L"1", L"2", L"Dhivehi (Maldives)", L"960", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, dvMVLayouts },
 #endif
 #ifdef LANGUAGE_NL_NL
-     {L"00000413", L"1252", L"850", L"10000", L"Dutch (Netherlands)", L"31", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlNLLayouts },
+    {L"00000413", L"1252", L"850", L"10000", L"Dutch (Netherlands)", L"31", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlNLLayouts },
 #endif
 #ifdef LANGUAGE_NL_BE
-     {L"00000813", L"1252", L"850", L"10000", L"Dutch (Belgium)", L"32", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlBELayouts },
+    {L"00000813", L"1252", L"850", L"10000", L"Dutch (Belgium)", L"32", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlBELayouts },
 #endif
 #ifdef LANGUAGE_EN_US
-     {L"00000409", L"1252", L"437", L"10000", L"English (United States)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enUSLayouts },
+    {L"00000409", L"1252", L"437", L"10000", L"English (United States)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enUSLayouts },
 #endif
 #ifdef LANGUAGE_EN_GB
-     {L"00000809", L"1252", L"850", L"10000", L"English (United Kingdom)", L"44", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enGBLayouts },
+    {L"00000809", L"1252", L"850", L"10000", L"English (United Kingdom)", L"44", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enGBLayouts },
 #endif
 #ifdef LANGUAGE_EN_AU
-     {L"00000C09", L"1252", L"850", L"10000", L"English (Australia)", L"61", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enAULayouts },
+    {L"00000C09", L"1252", L"850", L"10000", L"English (Australia)", L"61", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enAULayouts },
 #endif
 #ifdef LANGUAGE_EN_CA
-     {L"00001009", L"1252", L"850", L"10000", L"English (Canada)", L"107", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCALayouts },
+    {L"00001009", L"1252", L"850", L"10000", L"English (Canada)", L"107", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCALayouts },
 #endif
 #ifdef LANGUAGE_EN_NZ
-     {L"00001409", L"1252", L"850", L"10000", L"English (New Zealand)", L"64", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enNZLayouts },
+    {L"00001409", L"1252", L"850", L"10000", L"English (New Zealand)", L"64", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enNZLayouts },
 #endif
 #ifdef LANGUAGE_EN_IE
-     {L"00001809", L"1252", L"850", L"10000", L"English (Ireland)", L"353", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enIELayouts },
+    {L"00001809", L"1252", L"850", L"10000", L"English (Ireland)", L"353", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enIELayouts },
 #endif
 #ifdef LANGUAGE_EN_ZA
-     {L"00001C09", L"1252", L"437", L"10000", L"English (South Africa)", L"27", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZALayouts },
+    {L"00001C09", L"1252", L"437", L"10000", L"English (South Africa)", L"27", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZALayouts },
 #endif
 #ifdef LANGUAGE_EN_JM
-     {L"00002009", L"1252", L"850", L"10000", L"English (Jamaica)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enJMLayouts },
+    {L"00002009", L"1252", L"850", L"10000", L"English (Jamaica)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enJMLayouts },
 #endif
 #ifdef LANGUAGE_EN_CB
-     {L"00002409", L"1252", L"850", L"10000", L"English (Caribbean)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCBLayouts },
+    {L"00002409", L"1252", L"850", L"10000", L"English (Caribbean)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCBLayouts },
 #endif
 #ifdef LANGUAGE_EN_BZ
-     {L"00002809", L"1252", L"850", L"10000", L"English (Belize)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enBZLayouts },
+    {L"00002809", L"1252", L"850", L"10000", L"English (Belize)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enBZLayouts },
 #endif
 #ifdef LANGUAGE_EN_TT
-     {L"00002C09", L"1252", L"850", L"10000", L"English (Trinidad)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enTTLayouts },
+    {L"00002C09", L"1252", L"850", L"10000", L"English (Trinidad)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enTTLayouts },
 #endif
 #ifdef LANGUAGE_EN_ZW
-     {L"00003009", L"1252", L"437", L"10000", L"English (Zimbabwe)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZWLayouts },
+    {L"00003009", L"1252", L"437", L"10000", L"English (Zimbabwe)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZWLayouts },
 #endif
 #ifdef LANGUAGE_EN_PH
-     {L"00003409", L"1252", L"437", L"10000", L"English (Philippines)", L"63", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enPHLayouts },
+    {L"00003409", L"1252", L"437", L"10000", L"English (Philippines)", L"63", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enPHLayouts },
 #endif
 #ifdef LANGUAGE_EO_AA
-     {L"0000048F", L"1252", L"437", L"10000", L"Esperanto", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, eoAALayouts },
+    {L"0000048F", L"1252", L"437", L"10000", L"Esperanto", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, eoAALayouts },
 #endif
 #ifdef LANGUAGE_ET_EE
-     {L"00000425", L"1252", L"775", L"10029", L"Estonian", L"372", etEEPages, etEEErrorEntries, etEEStrings, LatinFonts, etEELayouts },
+    {L"00000425", L"1252", L"775", L"10029", L"Estonian", L"372", etEEPages, etEEErrorEntries, etEEStrings, LatinFonts, etEELayouts },
 #endif
 #ifdef LANGUAGE_FO_FO
-     {L"00000438", L"1252", L"850", L"10079", L"Faeroese", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, foFOLayouts },
+    {L"00000438", L"1252", L"850", L"10079", L"Faeroese", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, foFOLayouts },
 #endif
 #ifdef LANGUAGE_FA_IR
-     {L"00000429", L"1256", L"720", L"10004", L"Farsi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, faIRLayouts },
+    {L"00000429", L"1256", L"720", L"10004", L"Farsi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, faIRLayouts },
 #endif
 #ifdef LANGUAGE_FI_FI
-     {L"0000040B", L"1252", L"850", L"10000", L"Finnish", L"358", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, fiFILayouts },
+    {L"0000040B", L"1252", L"850", L"10000", L"Finnish", L"358", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, fiFILayouts },
 #endif
 #ifdef LANGUAGE_FR_CA
-     {L"00000C0C", L"1252", L"850", L"10000", L"French (Canada)", L"107", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCALayouts },
+    {L"00000C0C", L"1252", L"850", L"10000", L"French (Canada)", L"107", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCALayouts },
 #endif
 #ifdef LANGUAGE_FR_FR
-     {L"0000040C", L"1252", L"850", L"10000", L"French (France)", L"33", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frFRLayouts },
+    {L"0000040C", L"1252", L"850", L"10000", L"French (France)", L"33", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frFRLayouts },
 #endif
 #ifdef LANGUAGE_FR_BE
-     {L"0000080C", L"1252", L"850", L"10000", L"French (Belgium)", L"32", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frBELayouts },
+    {L"0000080C", L"1252", L"850", L"10000", L"French (Belgium)", L"32", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frBELayouts },
 #endif
 #ifdef LANGUAGE_FR_CH
-     {L"0000100C", L"1252", L"850", L"10000", L"French (Switzerland)", L"41", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCHLayouts },
+    {L"0000100C", L"1252", L"850", L"10000", L"French (Switzerland)", L"41", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCHLayouts },
 #endif
 #ifdef LANGUAGE_FR_LU
-     {L"0000140C", L"1252", L"850", L"10000", L"French (Luxembourg)", L"352", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frLULayouts },
+    {L"0000140C", L"1252", L"850", L"10000", L"French (Luxembourg)", L"352", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frLULayouts },
 #endif
 #ifdef LANGUAGE_FR_MC
-     {L"0000180C", L"1252", L"850", L"10000", L"French (Monaco)", L"1", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frMCLayouts },
+    {L"0000180C", L"1252", L"850", L"10000", L"French (Monaco)", L"1", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frMCLayouts },
 #endif
 #ifdef LANGUAGE_GL_ES
-     {L"00000456", L"1252", L"850", L"10000", L"Galician (Spain)", L"34", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, glESLayouts },
+    {L"00000456", L"1252", L"850", L"10000", L"Galician (Spain)", L"34", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, glESLayouts },
 #endif
 #ifdef LANGUAGE_KA_GE
-     {L"00000437", L"0", L"1", L"2", L"Georgian", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kaGELayouts },
+    {L"00000437", L"0", L"1", L"2", L"Georgian", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kaGELayouts },
 #endif
 #ifdef LANGUAGE_DE_DE
-     {L"00000407", L"1252", L"850", L"10000", L"German (Germany)", L"49", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deDELayouts },
+    {L"00000407", L"1252", L"850", L"10000", L"German (Germany)", L"49", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deDELayouts },
 #endif
 #ifdef LANGUAGE_DE_CH
-     {L"00000807", L"1252", L"850", L"10000", L"German (Switzerland)", L"41", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deCHLayouts },
+    {L"00000807", L"1252", L"850", L"10000", L"German (Switzerland)", L"41", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deCHLayouts },
 #endif
 #ifdef LANGUAGE_DE_AT
-     {L"00000C07", L"1252", L"850", L"10000", L"German (Austria)", L"43", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deATLayouts },
+    {L"00000C07", L"1252", L"850", L"10000", L"German (Austria)", L"43", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deATLayouts },
 #endif
 #ifdef LANGUAGE_DE_LU
-     {L"00001007", L"1252", L"850", L"10000", L"German (Luxembourg)", L"352", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLULayouts },
+    {L"00001007", L"1252", L"850", L"10000", L"German (Luxembourg)", L"352", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLULayouts },
 #endif
 #ifdef LANGUAGE_DE_LI
-     {L"00001407", L"1252", L"850", L"10000", L"German (Liechtenstein)", L"423", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLILayouts },
+    {L"00001407", L"1252", L"850", L"10000", L"German (Liechtenstein)", L"423", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLILayouts },
 #endif
 #ifdef LANGUAGE_EL_GR
-     {L"00000408", L"1253", L"737", L"10006", L"Greek", L"30", elGRPages, elGRErrorEntries, elGRStrings, GreekFonts, elGRLayouts },
+    {L"00000408", L"1253", L"737", L"10006", L"Greek", L"30", elGRPages, elGRErrorEntries, elGRStrings, GreekFonts, elGRLayouts },
 #endif
 #ifdef LANGUAGE_GU_IN
-     {L"00000447", L"0", L"1", L"2", L"Gujarati (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, guINLayouts },
+    {L"00000447", L"0", L"1", L"2", L"Gujarati (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, guINLayouts },
 #endif
 #ifdef LANGUAGE_HE_IL
-     {L"0000040D", L"1255", L"862", L"10005", L"Hebrew", L"1", heILPages, heILErrorEntries, heILStrings, HebrewFonts, heILLayouts },
+    {L"0000040D", L"1255", L"862", L"10005", L"Hebrew", L"1", heILPages, heILErrorEntries, heILStrings, HebrewFonts, heILLayouts },
 #endif
 #ifdef LANGUAGE_HI_IN
-     {L"00000439", L"1252", L"437", L"10000", L"Hindi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hiINLayouts },
+    {L"00000439", L"1252", L"437", L"10000", L"Hindi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hiINLayouts },
 #endif
 #ifdef LANGUAGE_HU_HU
-     {L"0000040E", L"1250", L"852", L"10029", L"Hungarian", L"36", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, huHULayouts },
+    {L"0000040E", L"1250", L"852", L"10029", L"Hungarian", L"36", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, huHULayouts },
 #endif
 #ifdef LANGUAGE_IS_IS
-     {L"0000040F", L"1252", L"850", L"10079", L"Icelandic", L"354", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, isISLayouts },
+    {L"0000040F", L"1252", L"850", L"10079", L"Icelandic", L"354", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, isISLayouts },
 #endif
 #ifdef LANGUAGE_ID_ID
-     {L"00000421", L"1252", L"850", L"10079", L"Indonesian", L"62", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, idIDLayouts },
+    {L"00000421", L"1252", L"850", L"10079", L"Indonesian", L"62", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, idIDLayouts },
 #endif
 #ifdef LANGUAGE_IT_IT
-     {L"00000410", L"1252", L"850", L"10000", L"Italian (Italy)", L"39", itITPages, itITErrorEntries, itITStrings, LatinFonts, itITLayouts },
+    {L"00000410", L"1252", L"850", L"10000", L"Italian (Italy)", L"39", itITPages, itITErrorEntries, itITStrings, LatinFonts, itITLayouts },
 #endif
 #ifdef LANGUAGE_IT_CH
-     {L"00000810", L"1252", L"850", L"10000", L"Italian (Switzerland)", L"41", itITPages, itITErrorEntries, itITStrings, LatinFonts, itCHLayouts },
+    {L"00000810", L"1252", L"850", L"10000", L"Italian (Switzerland)", L"41", itITPages, itITErrorEntries, itITStrings, LatinFonts, itCHLayouts },
 #endif
 #ifdef LANGUAGE_JA_JP
-     {L"00000411", L"932", L"932", L"10001", L"Japanese", L"81", jaJPPages, jaJPErrorEntries, jaJPStrings, CJKFonts, jaJPLayouts },
+    {L"00000411", L"932", L"932", L"10001", L"Japanese", L"81", jaJPPages, jaJPErrorEntries, jaJPStrings, CJKFonts, jaJPLayouts },
 #endif
 #ifdef LANGUAGE_KN_IN
-     {L"0000044B", L"1252", L"437", L"10079", L"Kannada (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, knINLayouts },
+    {L"0000044B", L"1252", L"437", L"10079", L"Kannada (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, knINLayouts },
 #endif
 #ifdef LANGUAGE_KK_KZ
-     {L"0000043F", L"1251", L"866", L"10007", L"Kazakh", L"705", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kkKZLayouts },
+    {L"0000043F", L"1251", L"866", L"10007", L"Kazakh", L"705", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kkKZLayouts },
 #endif
 #ifdef LANGUAGE_KOK_IN
-     {L"00000457", L"0", L"437", L"2", L"Konkani", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kokINLayouts},
+    {L"00000457", L"0", L"437", L"2", L"Konkani", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kokINLayouts},
 #endif
 #ifdef LANGUAGE_KO_KR
-     {L"00000412", L"949", L"949", L"10003", L"Korean", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, koKRLayouts },
+    {L"00000412", L"949", L"949", L"10003", L"Korean", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, koKRLayouts },
 #endif
 #ifdef LANGUAGE_KY_KG
-     {L"00000440", L"1251", L"866", L"10007", L"Kyrgyz (Kyrgyzstan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kyKGLayouts },
+    {L"00000440", L"1251", L"866", L"10007", L"Kyrgyz (Kyrgyzstan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kyKGLayouts },
 #endif
 #ifdef LANGUAGE_LV_LV
-     {L"00000426", L"1257", L"775", L"10029", L"Latvian", L"371", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, lvLVLayouts },
+    {L"00000426", L"1257", L"775", L"10029", L"Latvian", L"371", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, lvLVLayouts },
 #endif
 #ifdef LANGUAGE_LT_LT
-     {L"00000427", L"1257", L"775", L"10029", L"Lithuanian", L"370", ltLTPages, ltLTErrorEntries, ltLTStrings, LatinFonts, ltLTLayouts },
+    {L"00000427", L"1257", L"775", L"10029", L"Lithuanian", L"370", ltLTPages, ltLTErrorEntries, ltLTStrings, LatinFonts, ltLTLayouts },
 #endif
 #ifdef LANGUAGE_MK_MK
-     {L"0000042F", L"1251", L"866", L"10007", L"FYRO Macedonian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mkMKLayouts },
+    {L"0000042F", L"1251", L"866", L"10007", L"FYRO Macedonian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mkMKLayouts },
 #endif
 #ifdef LANGUAGE_MS_BN
-     {L"0000083E", L"1252", L"850", L"10000", L"Malay (Brunei Darussalam)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msBNLayouts },
+    {L"0000083E", L"1252", L"850", L"10000", L"Malay (Brunei Darussalam)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msBNLayouts },
 #endif
 #ifdef LANGUAGE_MS_MY
-     {L"0000043E", L"1252", L"850", L"10000", L"Malay (Malaysia)", L"60", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msMYLayouts },
+    {L"0000043E", L"1252", L"850", L"10000", L"Malay (Malaysia)", L"60", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msMYLayouts },
 #endif
 #ifdef LANGUAGE_MR_IN
-     {L"0000044E", L"0", L"1", L"2", L"Marathi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, mrINLayouts },
+    {L"0000044E", L"0", L"1", L"2", L"Marathi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, mrINLayouts },
 #endif
 #ifdef LANGUAGE_MN_MN
-     {L"00000450", L"1251", L"866", L"10007", L"Mongolian (Mongolia)", L"976", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mnMNLayouts },
+    {L"00000450", L"1251", L"866", L"10007", L"Mongolian (Mongolia)", L"976", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mnMNLayouts },
 #endif
 #ifdef LANGUAGE_NB_NO
-     {L"00000414", L"1252", L"850", L"10000", L"Norwegian (Bokmal)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nbNOLayouts },
+    {L"00000414", L"1252", L"850", L"10000", L"Norwegian (Bokmal)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nbNOLayouts },
 #endif
 #ifdef LANGUAGE_NN_NO
-     {L"00000814", L"1252", L"850", L"10000", L"Norwegian (Nynorsk)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nnNOLayouts },
+    {L"00000814", L"1252", L"850", L"10000", L"Norwegian (Nynorsk)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nnNOLayouts },
 #endif
 #ifdef LANGUAGE_PL_PL
-     {L"00000415", L"1250", L"852", L"10029", L"Polish", L"48", plPLPages, plPLErrorEntries, plPLStrings, LatinFonts, plPLLayouts },
+    {L"00000415", L"1250", L"852", L"10029", L"Polish", L"48", plPLPages, plPLErrorEntries, plPLStrings, LatinFonts, plPLLayouts },
 #endif
 #ifdef LANGUAGE_PT_PT
-     {L"00000816", L"1252", L"850", L"10000", L"Portuguese (Portugal)", L"351", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, ptPTLayouts },
+    {L"00000816", L"1252", L"850", L"10000", L"Portuguese (Portugal)", L"351", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, ptPTLayouts },
 #endif
 #ifdef LANGUAGE_PT_BR
-     {L"00000416", L"1252", L"850", L"10000", L"Portuguese (Brazil)", L"55", ptBRPages, ptBRErrorEntries, ptBRStrings, LatinFonts, ptBRLayouts },
+    {L"00000416", L"1252", L"850", L"10000", L"Portuguese (Brazil)", L"55", ptBRPages, ptBRErrorEntries, ptBRStrings, LatinFonts, ptBRLayouts },
 #endif
 #ifdef LANGUAGE_PA_IN
-     {L"00000446", L"0", L"1", L"2", L"Punjabi (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, paINLayouts },
+    {L"00000446", L"0", L"1", L"2", L"Punjabi (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, paINLayouts },
 #endif
 #ifdef LANGUAGE_RO_RO
-     {L"00000418", L"1250", L"852", L"10029", L"Romanian", L"40", roROPages, roROErrorEntries, roROStrings, LatinFonts, roROLayouts },
+    {L"00000418", L"1250", L"852", L"10029", L"Romanian", L"40", roROPages, roROErrorEntries, roROStrings, LatinFonts, roROLayouts },
 #endif
 #ifdef LANGUAGE_RM_CH
-     {L"00000417", L"1252", L"850", L"10000", L"Romansh", L"41", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, rmCHLayouts },
+    {L"00000417", L"1252", L"850", L"10000", L"Romansh", L"41", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, rmCHLayouts },
 #endif
 #ifdef LANGUAGE_RU_RU
-     {L"00000419", L"1251", L"866", L"10007", L"Russian", L"7", ruRUPages, ruRUErrorEntries, ruRUStrings, CyrillicFonts, ruRULayouts },
+    {L"00000419", L"1251", L"866", L"10007", L"Russian", L"7", ruRUPages, ruRUErrorEntries, ruRUStrings, CyrillicFonts, ruRULayouts },
 #endif
 #ifdef LANGUAGE_SA_IN
-     {L"0000044F", L"0", L"1", L"2", L"Sanskrit", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, saINLayouts },
+    {L"0000044F", L"0", L"1", L"2", L"Sanskrit", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, saINLayouts },
 #endif
 #ifdef LANGUAGE_SR_SP
-     {L"00000C1A", L"1251", L"855", L"10007", L"Serbian (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, srSPLayouts },
+    {L"00000C1A", L"1251", L"855", L"10007", L"Serbian (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, srSPLayouts },
 #endif
 #ifdef LANGUAGE_SR_SP
-     {L"0000081A", L"1250", L"852", L"10029", L"Serbian (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, srSPLayouts },
+    {L"0000081A", L"1250", L"852", L"10029", L"Serbian (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, srSPLayouts },
 #endif
 #ifdef LANGUAGE_SK_SK
-     {L"0000041B", L"1250", L"852", L"10029", L"Slovak", L"421", skSKPages, skSKErrorEntries, skSKStrings, LatinFonts, skSKLayouts },
+    {L"0000041B", L"1250", L"852", L"10029", L"Slovak", L"421", skSKPages, skSKErrorEntries, skSKStrings, LatinFonts, skSKLayouts },
 #endif
 #ifdef LANGUAGE_SL_SI
-     {L"00000424", L"1250", L"852", L"10029", L"Slovenian", L"386", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, slSILayouts },
+    {L"00000424", L"1250", L"852", L"10029", L"Slovenian", L"386", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, slSILayouts },
 #endif
 #ifdef LANGUAGE_ES_ES
-     {L"0000040A", L"1252", L"850", L"10000", L"Spanish (Traditional Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts },
+    {L"0000040A", L"1252", L"850", L"10000", L"Spanish (Traditional Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts },
 #endif
 #ifdef LANGUAGE_ES_MX
-     {L"0000080A", L"1252", L"850", L"10000", L"Spanish (Mexico)", L"52", esESPages, esESErrorEntries, esESStrings, LatinFonts, esMXLayouts },
+    {L"0000080A", L"1252", L"850", L"10000", L"Spanish (Mexico)", L"52", esESPages, esESErrorEntries, esESStrings, LatinFonts, esMXLayouts },
 #endif
 #ifdef LANGUAGE_ES_ES
-     {L"00000C0A", L"1252", L"850", L"10000", L"Spanish (International Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts },
+    {L"00000C0A", L"1252", L"850", L"10000", L"Spanish (International Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts },
 #endif
 #ifdef LANGUAGE_ES_GT
-     {L"0000100A", L"1252", L"850", L"10000", L"Spanish (Guatemala)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esGTLayouts },
+    {L"0000100A", L"1252", L"850", L"10000", L"Spanish (Guatemala)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esGTLayouts },
 #endif
 #ifdef LANGUAGE_ES_CR
-     {L"0000140A", L"1252", L"850", L"10000", L"Spanish (Costa Rica)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCRLayouts },
+    {L"0000140A", L"1252", L"850", L"10000", L"Spanish (Costa Rica)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCRLayouts },
 #endif
 #ifdef LANGUAGE_ES_PA
-     {L"0000180A", L"1252", L"850", L"10000", L"Spanish (Panama)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPALayouts },
+    {L"0000180A", L"1252", L"850", L"10000", L"Spanish (Panama)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPALayouts },
 #endif
 #ifdef LANGUAGE_ES_DO
-     {L"00001C0A", L"1252", L"850", L"10000", L"Spanish (Dominican Republic)", L"110", esESPages, esESErrorEntries, esESStrings, LatinFonts, esDOLayouts },
+    {L"00001C0A", L"1252", L"850", L"10000", L"Spanish (Dominican Republic)", L"110", esESPages, esESErrorEntries, esESStrings, LatinFonts, esDOLayouts },
 #endif
 #ifdef LANGUAGE_ES_VE
-     {L"0000200A", L"1252", L"850", L"10000", L"Spanish (Venezuela)", L"58", esESPages, esESErrorEntries, esESStrings, LatinFonts, esVELayouts },
+    {L"0000200A", L"1252", L"850", L"10000", L"Spanish (Venezuela)", L"58", esESPages, esESErrorEntries, esESStrings, LatinFonts, esVELayouts },
 #endif
 #ifdef LANGUAGE_ES_CO
-     {L"0000240A", L"1252", L"850", L"10000", L"Spanish (Colombia)", L"57", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCOLayouts },
+    {L"0000240A", L"1252", L"850", L"10000", L"Spanish (Colombia)", L"57", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCOLayouts },
 #endif
 #ifdef LANGUAGE_ES_PE
-     {L"0000280A", L"1252", L"850", L"10000", L"Spanish (Peru)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPELayouts },
+    {L"0000280A", L"1252", L"850", L"10000", L"Spanish (Peru)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPELayouts },
 #endif
 #ifdef LANGUAGE_ES_AR
-     {L"00002C0A", L"1252", L"850", L"10000", L"Spanish (Argentina)", L"54", esESPages, esESErrorEntries, esESStrings, LatinFonts, esARLayouts },
+    {L"00002C0A", L"1252", L"850", L"10000", L"Spanish (Argentina)", L"54", esESPages, esESErrorEntries, esESStrings, LatinFonts, esARLayouts },
 #endif
 #ifdef LANGUAGE_ES_EC
-     {L"0000300A", L"1252", L"850", L"10000", L"Spanish (Ecuador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esECLayouts },
+    {L"0000300A", L"1252", L"850", L"10000", L"Spanish (Ecuador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esECLayouts },
 #endif
 #ifdef LANGUAGE_ES_CL
-     {L"0000340A", L"1252", L"850", L"10000", L"Spanish (Chile)", L"56", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCLLayouts },
+    {L"0000340A", L"1252", L"850", L"10000", L"Spanish (Chile)", L"56", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCLLayouts },
 #endif
 #ifdef LANGUAGE_ES_UY
-     {L"0000380A", L"1252", L"850", L"10000", L"Spanish (Uruguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esUYLayouts },
+    {L"0000380A", L"1252", L"850", L"10000", L"Spanish (Uruguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esUYLayouts },
 #endif
 #ifdef LANGUAGE_ES_PY
-     {L"00003C0A", L"1252", L"850", L"10000", L"Spanish (Paraguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPYLayouts },
+    {L"00003C0A", L"1252", L"850", L"10000", L"Spanish (Paraguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPYLayouts },
 #endif
 #ifdef LANGUAGE_ES_BO
-     {L"0000400A", L"1252", L"850", L"10000", L"Spanish (Bolivia)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esBOLayouts },
+    {L"0000400A", L"1252", L"850", L"10000", L"Spanish (Bolivia)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esBOLayouts },
 #endif
 #ifdef LANGUAGE_ES_SV
-     {L"0000440A", L"1252", L"850", L"10000", L"Spanish (El Salvador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esSVLayouts },
+    {L"0000440A", L"1252", L"850", L"10000", L"Spanish (El Salvador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esSVLayouts },
 #endif
 #ifdef LANGUAGE_ES_HN
-     {L"0000480A", L"1252", L"850", L"10000", L"Spanish (Honduras)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esHNLayouts },
+    {L"0000480A", L"1252", L"850", L"10000", L"Spanish (Honduras)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esHNLayouts },
 #endif
 #ifdef LANGUAGE_ES_NI
-     {L"00004C0A", L"1252", L"850", L"10000", L"Spanish (Nicaragua)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esNILayouts },
+    {L"00004C0A", L"1252", L"850", L"10000", L"Spanish (Nicaragua)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esNILayouts },
 #endif
 #ifdef LANGUAGE_ES_PR
-     {L"0000500A", L"1252", L"850", L"10000", L"Spanish (Puerto Rico)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPRLayouts },
+    {L"0000500A", L"1252", L"850", L"10000", L"Spanish (Puerto Rico)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPRLayouts },
 #endif
 #ifdef LANGUAGE_SW_KE
-     {L"00000441", L"1252", L"437", L"10000", L"Swahili", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, swKELayouts },
+    {L"00000441", L"1252", L"437", L"10000", L"Swahili", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, swKELayouts },
 #endif
 #ifdef LANGUAGE_SV_SE
-     {L"0000041D", L"1252", L"850", L"10000", L"Swedish", L"46", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svSELayouts },
+    {L"0000041D", L"1252", L"850", L"10000", L"Swedish", L"46", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svSELayouts },
 #endif
 #ifdef LANGUAGE_SV_FI
-     {L"0000081D", L"1252", L"850", L"10000", L"Swedish (Finland)", L"358", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svFILayouts },
+    {L"0000081D", L"1252", L"850", L"10000", L"Swedish (Finland)", L"358", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svFILayouts },
 #endif
 #ifdef LANGUAGE_SYR_SY
-     {L"0000045A", L"0", L"1", L"2", L"Syriac (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, syrSYLayouts},
+    {L"0000045A", L"0", L"1", L"2", L"Syriac (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, syrSYLayouts},
 #endif
 #ifdef LANGUAGE_TA_IN
-     {L"00000449", L"0", L"1", L"2", L"Tamil", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, taINLayouts },
+    {L"00000449", L"0", L"1", L"2", L"Tamil", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, taINLayouts },
 #endif
 #ifdef LANGUAGE_TT_TA
-     {L"00000444", L"1251", L"866", L"10007", L"Tatar", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, ttTALayouts },
+    {L"00000444", L"1251", L"866", L"10007", L"Tatar", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, ttTALayouts },
 #endif
 #ifdef LANGUAGE_TE_IN
-     {L"0000044A", L"0", L"1", L"2", L"Telugu (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, teINLayouts },
+    {L"0000044A", L"0", L"1", L"2", L"Telugu (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, teINLayouts },
 #endif
 #ifdef LANGUAGE_TH_TH
-     {L"0000041E", L"874", L"874", L"10021", L"Thai", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, thTHLayouts },
+    {L"0000041E", L"874", L"874", L"10021", L"Thai", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, thTHLayouts },
 #endif
 #ifdef LANGUAGE_TR_TR
-     {L"0000041F", L"1254", L"857", L"10081", L"Turkish", L"90", trTRPages, trTRErrorEntries, trTRStrings, LatinFonts, trTRLayouts },
+    {L"0000041F", L"1254", L"857", L"10081", L"Turkish", L"90", trTRPages, trTRErrorEntries, trTRStrings, LatinFonts, trTRLayouts },
 #endif
 #ifdef LANGUAGE_UK_UA
-     {L"00000422", L"1251", L"866", L"10017", L"Ukrainian", L"380", ukUAPages, ukUAErrorEntries, ukUAStrings, CyrillicFonts, ukUALayouts },
+    {L"00000422", L"1251", L"866", L"10017", L"Ukrainian", L"380", ukUAPages, ukUAErrorEntries, ukUAStrings, CyrillicFonts, ukUALayouts },
 #endif
 #ifdef LANGUAGE_UR_PK
-     {L"00000420", L"1256", L"720", L"10004", L"Urdu", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, urPKLayouts },
+    {L"00000420", L"1256", L"720", L"10004", L"Urdu", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, urPKLayouts },
 #endif
 #ifdef LANGUAGE_UZ_UZ
-     {L"00000443", L"1254", L"857", L"10029", L"Uzbek (Latin)", L"998", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, uzUZLayouts },
+    {L"00000443", L"1254", L"857", L"10029", L"Uzbek (Latin)", L"998", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, uzUZLayouts },
 #endif
 #ifdef LANGUAGE_UZ_UZ
-     {L"00000843", L"1251", L"866", L"10007", L"Uzbek (Cyrillic)", L"998", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, uzUZLayouts },
+    {L"00000843", L"1251", L"866", L"10007", L"Uzbek (Cyrillic)", L"998", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, uzUZLayouts },
 #endif
 #ifdef LANGUAGE_VI_VN
-     {L"0000042A", L"1258", L"1258",L"10000", L"Vietnamese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, viVNLayouts },
+    {L"0000042A", L"1258", L"1258",L"10000", L"Vietnamese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, viVNLayouts },
 #endif
 #ifdef LANGUAGE_WA_BE
-     {L"00000490", L"1252", L"850", L"10000", L"Walon", L"32", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, waBELayouts },
+    {L"00000490", L"1252", L"850", L"10000", L"Walon", L"32", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, waBELayouts },
 #endif
 #ifdef LANGUAGE_ZU_ZU
-     {L"00000435", L"1252", L"850", L"10000", L"Zulu", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, zuZULayouts },
+    {L"00000435", L"1252", L"850", L"10000", L"Zulu", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, zuZULayouts },
 #endif
-  {NULL, NULL, NULL, NULL, NULL, NULL}
+    {NULL, NULL, NULL, NULL, NULL, NULL}
 };
index 5543381..d41c9f0 100644 (file)
 /* FUNCTIONS ****************************************************************/
 
 
-static VOID
-DrawBorder(PPROGRESSBAR Bar)
+static
+VOID
+DrawBorder(
+    PPROGRESSBAR Bar)
 {
-  COORD coPos;
-  DWORD Written;
-  SHORT i;
-
-  /* draw upper left corner */
-  coPos.X = Bar->Left;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xDA, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw upper edge */
-  coPos.X = Bar->Left + 1;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xC4, // '-',
-                            Bar->Right - Bar->Left - 1,
-                            coPos,
-                            &Written);
-
-  /* draw upper right corner */
-  coPos.X = Bar->Right;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xBF, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw left and right edge */
-  for (i = Bar->Top + 2; i < Bar->Bottom; i++)
+    COORD coPos;
+    DWORD Written;
+    SHORT i;
+
+    /* draw upper left corner */
+    coPos.X = Bar->Left;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xDA, // '+',
+                                1,
+                                coPos,
+                                &Written);
+
+    /* draw upper edge */
+    coPos.X = Bar->Left + 1;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC4, // '-',
+                                Bar->Right - Bar->Left - 1,
+                                coPos,
+                                &Written);
+
+    /* draw upper right corner */
+    coPos.X = Bar->Right;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                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;
-      FillConsoleOutputCharacterA(StdOutput,
-                                0xB3, // '|',
-                                1,
-                                coPos,
-                                &Written);
-
-      coPos.X = Bar->Right;
-      FillConsoleOutputCharacterA(StdOutput,
-                                0xB3, //'|',
-                                1,
-                                coPos,
-                                &Written);
+        coPos.X = Bar->Left;
+        coPos.Y = i;
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xB3, // '|',
+                                    1,
+                                    coPos,
+                                    &Written);
+
+        coPos.X = Bar->Right;
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xB3, //'|',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
 
-  /* draw lower left corner */
-  coPos.X = Bar->Left;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xC0, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw lower edge */
-  coPos.X = Bar->Left + 1;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xC4, // '-',
-                            Bar->Right - Bar->Left - 1,
-                            coPos,
-                            &Written);
-
-  /* draw lower right corner */
-  coPos.X = Bar->Right;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xD9, // '+',
-                            1,
-                            coPos,
-                            &Written);
+    /* draw lower left corner */
+    coPos.X = Bar->Left;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC0, // '+',
+                                1,
+                                coPos,
+                                &Written);
+
+    /* draw lower edge */
+    coPos.X = Bar->Left + 1;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC4, // '-',
+                                Bar->Right - Bar->Left - 1,
+                                coPos,
+                                &Written);
+
+    /* draw lower right corner */
+    coPos.X = Bar->Right;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xD9, // '+',
+                                1,
+                                coPos,
+                                &Written);
 }
 
-static VOID
-DrawThickBorder(PPROGRESSBAR Bar)
+
+static
+VOID
+DrawThickBorder(
+    PPROGRESSBAR Bar)
 {
-  COORD coPos;
-  DWORD Written;
-  SHORT i;
-
-  /* draw upper left corner */
-  coPos.X = Bar->Left;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xC9, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw upper edge */
-  coPos.X = Bar->Left + 1;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xCD, // '-',
-                            Bar->Right - Bar->Left - 1,
-                            coPos,
-                            &Written);
-
-  /* draw upper right corner */
-  coPos.X = Bar->Right;
-  coPos.Y = Bar->Top + 1;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xBB, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw left and right edge */
-  for (i = Bar->Top + 2; i < Bar->Bottom; i++)
+    COORD coPos;
+    DWORD Written;
+    SHORT i;
+
+    /* draw upper left corner */
+    coPos.X = Bar->Left;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC9, // '+',
+                                1,
+                                coPos,
+                                &Written);
+
+    /* draw upper edge */
+    coPos.X = Bar->Left + 1;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xCD, // '-',
+                                Bar->Right - Bar->Left - 1,
+                                coPos,
+                                &Written);
+
+    /* draw upper right corner */
+    coPos.X = Bar->Right;
+    coPos.Y = Bar->Top + 1;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xBB, // '+',
+                                1,
+                                coPos,
+                                &Written);
+
+    /* draw left and right edge */
+    for (i = Bar->Top + 2; i < Bar->Bottom; i++)
     {
-      coPos.X = Bar->Left;
-      coPos.Y = i;
-      FillConsoleOutputCharacterA(StdOutput,
-                                0xBA, // '|',
-                                1,
-                                coPos,
-                                &Written);
-
-      coPos.X = Bar->Right;
-      FillConsoleOutputCharacterA(StdOutput,
-                                0xBA, //'|',
-                                1,
-                                coPos,
-                                &Written);
+        coPos.X = Bar->Left;
+        coPos.Y = i;
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xBA, // '|',
+                                    1,
+                                    coPos,
+                                    &Written);
+
+        coPos.X = Bar->Right;
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xBA, //'|',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
 
-  /* draw lower left corner */
-  coPos.X = Bar->Left;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xC8, // '+',
-                            1,
-                            coPos,
-                            &Written);
-
-  /* draw lower edge */
-  coPos.X = Bar->Left + 1;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xCD, // '-',
-                            Bar->Right - Bar->Left - 1,
-                            coPos,
-                            &Written);
-
-  /* draw lower right corner */
-  coPos.X = Bar->Right;
-  coPos.Y = Bar->Bottom;
-  FillConsoleOutputCharacterA(StdOutput,
-                            0xBC, // '+',
-                            1,
-                            coPos,
-                            &Written);
+    /* draw lower left corner */
+    coPos.X = Bar->Left;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC8, // '+',
+                                1,
+                                coPos,
+                                &Written);
+
+    /* draw lower edge */
+    coPos.X = Bar->Left + 1;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xCD, // '-',
+                                Bar->Right - Bar->Left - 1,
+                                coPos,
+                                &Written);
+
+    /* draw lower right corner */
+    coPos.X = Bar->Right;
+    coPos.Y = Bar->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xBC, // '+',
+                                1,
+                                coPos,
+                                &Written);
 }
 
-static VOID
-DrawProgressBar(PPROGRESSBAR Bar)
+
+static
+VOID
+DrawProgressBar(
+    PPROGRESSBAR Bar)
 {
-  CHAR TextBuffer[8];
-  COORD coPos;
-  DWORD Written;
-  PROGRESSBAR BarBorder = *Bar;
-
-  /* Print percentage */
-  sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
-
-  coPos.X = Bar->Left + (Bar->Width - 2) / 2;
-  coPos.Y = Bar->Top;
-  WriteConsoleOutputCharacterA(StdOutput,
-                              TextBuffer,
-                              4,
-                              coPos,
-                              &Written);
-
-  /* Draw the progress bar border */
-  DrawBorder(Bar);
-
-  /* Write Text Associated with Bar */
-  CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text);
-
-  /* Draw the progress bar "border" border */
-  if (Bar->Double)
-  {
-      BarBorder.Top -= 5;
-      BarBorder.Bottom += 2;
-      BarBorder.Right += 5;
-      BarBorder.Left -= 5;
-      DrawThickBorder(&BarBorder);
-  }
-
-  /* Draw the bar */
-  coPos.X = Bar->Left + 1;
-  for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+    CHAR TextBuffer[8];
+    COORD coPos;
+    DWORD Written;
+    PROGRESSBAR BarBorder = *Bar;
+
+    /* Print percentage */
+    sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+
+    coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+    coPos.Y = Bar->Top;
+    WriteConsoleOutputCharacterA(StdOutput,
+                                 TextBuffer,
+                                 4,
+                                 coPos,
+                                 &Written);
+
+    /* Draw the progress bar border */
+    DrawBorder(Bar);
+
+    /* Write Text Associated with Bar */
+    CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text);
+
+    /* Draw the progress bar "border" border */
+    if (Bar->Double)
     {
-      FillConsoleOutputAttribute(StdOutput,
-                                FOREGROUND_YELLOW | BACKGROUND_BLUE,
-                                Bar->Width - 2,
-                                coPos,
-                                &Written);
-
-      FillConsoleOutputCharacterA(StdOutput,
-                                ' ',
-                                Bar->Width - 2,
-                                coPos,
-                                &Written);
+        BarBorder.Top -= 5;
+        BarBorder.Bottom += 2;
+        BarBorder.Right += 5;
+        BarBorder.Left -= 5;
+        DrawThickBorder(&BarBorder);
     }
 
+    /* Draw the bar */
+    coPos.X = Bar->Left + 1;
+    for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+    {
+        FillConsoleOutputAttribute(StdOutput,
+                                   FOREGROUND_YELLOW | BACKGROUND_BLUE,
+                                   Bar->Width - 2,
+                                   coPos,
+                                   &Written);
+
+        FillConsoleOutputCharacterA(StdOutput,
+                                    ' ',
+                                    Bar->Width - 2,
+                                    coPos,
+                                    &Written);
+    }
 }
 
 
-
 PPROGRESSBAR
-CreateProgressBar(SHORT Left,
-                 SHORT Top,
-                 SHORT Right,
-                 SHORT Bottom,
-          SHORT TextTop,
-          SHORT TextRight,
-          IN BOOLEAN DoubleEdge,
-          char* Text)
+CreateProgressBar(
+    SHORT Left,
+    SHORT Top,
+    SHORT Right,
+    SHORT Bottom,
+    SHORT TextTop,
+    SHORT TextRight,
+    IN BOOLEAN DoubleEdge,
+    CHAR *Text)
 {
-  PPROGRESSBAR Bar;
+    PPROGRESSBAR Bar;
 
-  Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap,
-                                     0,
-                                     sizeof(PROGRESSBAR));
-  if (Bar == NULL)
-    return(NULL);
+    Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap,
+                                        0,
+                                        sizeof(PROGRESSBAR));
+    if (Bar == NULL)
+        return NULL;
 
-  Bar->Left = Left;
-  Bar->Top = Top;
-  Bar->Right = Right;
-  Bar->Bottom = Bottom;
-  Bar->TextTop = TextTop;
-  Bar->TextRight = TextRight;
-  Bar->Double = DoubleEdge;
-  Bar->Text = Text;
+    Bar->Left = Left;
+    Bar->Top = Top;
+    Bar->Right = Right;
+    Bar->Bottom = Bottom;
+    Bar->TextTop = TextTop;
+    Bar->TextRight = TextRight;
+    Bar->Double = DoubleEdge;
+    Bar->Text = Text;
 
-  Bar->Width = Bar->Right - Bar->Left + 1;
+    Bar->Width = Bar->Right - Bar->Left + 1;
 
-  Bar->Percent = 0;
-  Bar->Pos = 0;
+    Bar->Percent = 0;
+    Bar->Pos = 0;
 
-  Bar->StepCount = 0;
-  Bar->CurrentStep = 0;
+    Bar->StepCount = 0;
+    Bar->CurrentStep = 0;
 
-  DrawProgressBar(Bar);
+    DrawProgressBar(Bar);
 
-  return(Bar);
+    return Bar;
 }
 
 
 VOID
-DestroyProgressBar(PPROGRESSBAR Bar)
+DestroyProgressBar(
+    PPROGRESSBAR Bar)
 {
-  RtlFreeHeap(ProcessHeap,
-             0,
-             Bar);
+    RtlFreeHeap(ProcessHeap, 0, Bar);
 }
 
+
 VOID
-ProgressSetStepCount(PPROGRESSBAR Bar,
-                    ULONG StepCount)
+ProgressSetStepCount(
+    PPROGRESSBAR Bar,
+    ULONG StepCount)
 {
-  Bar->CurrentStep = 0;
-  Bar->StepCount = StepCount;
+    Bar->CurrentStep = 0;
+    Bar->StepCount = StepCount;
 
-  DrawProgressBar(Bar);
+    DrawProgressBar(Bar);
 }
 
 
 VOID
-ProgressNextStep(PPROGRESSBAR Bar)
+ProgressNextStep(
+    PPROGRESSBAR Bar)
 {
-  ProgressSetStep(Bar, Bar->CurrentStep + 1);
+    ProgressSetStep(Bar, Bar->CurrentStep + 1);
 }
 
 
 VOID
-ProgressSetStep (PPROGRESSBAR Bar,
-                ULONG Step)
+ProgressSetStep(
+    PPROGRESSBAR Bar,
+    ULONG Step)
 {
-  CHAR TextBuffer[8];
-  COORD coPos;
-  DWORD Written;
-  ULONG NewPercent;
-  ULONG NewPos;
+    CHAR TextBuffer[8];
+    COORD coPos;
+    DWORD Written;
+    ULONG NewPercent;
+    ULONG NewPos;
 
-  if (Step > Bar->StepCount)
-    return;
+    if (Step > Bar->StepCount)
+        return;
 
-  Bar->CurrentStep = Step;
+    Bar->CurrentStep = Step;
 
-  /* Calculate new percentage */
-  NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+    /* Calculate new percentage */
+    NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
 
-  /* Redraw precentage if changed */
-  if (Bar->Percent != NewPercent)
+    /* Redraw precentage if changed */
+    if (Bar->Percent != NewPercent)
     {
-      Bar->Percent = NewPercent;
+        Bar->Percent = NewPercent;
 
-      sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+        sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
 
-      coPos.X = Bar->Left + (Bar->Width - 2) / 2;
-      coPos.Y = Bar->Top;
-      WriteConsoleOutputCharacterA(StdOutput,
-                                  TextBuffer,
-                                  4,
-                                  coPos,
-                                  &Written);
+        coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+        coPos.Y = Bar->Top;
+        WriteConsoleOutputCharacterA(StdOutput,
+                                     TextBuffer,
+                                     4,
+                                     coPos,
+                                     &Written);
     }
 
-  /* Calculate bar position */
-  NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+    /* 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)
+    /* 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;
-         FillConsoleOutputCharacterA(StdOutput,
-                                    0xDB,
-                                    Bar->Pos / 2,
-                                    coPos,
-                                    &Written);
-         coPos.X += Bar->Pos/2;
-
-         if (NewPos & 1)
-           {
-             FillConsoleOutputCharacterA(StdOutput,
-                                        0xDD,
-                                        1,
-                                        coPos,
-                                        &Written);
-             coPos.X++;
-           }
-
-         if (coPos.X <= Bar->Right - 1)
-           {
-             FillConsoleOutputCharacterA(StdOutput,
-                                        ' ',
-                                        Bar->Right - coPos.X,
-                                        coPos,
-                                        &Written);
-           }
-       }
+        Bar->Pos = NewPos;
+
+        for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+        {
+            coPos.X = Bar->Left + 1;
+            FillConsoleOutputCharacterA(StdOutput,
+                                        0xDB,
+                                        Bar->Pos / 2,
+                                        coPos,
+                                        &Written);
+            coPos.X += Bar->Pos/2;
+
+            if (NewPos & 1)
+            {
+                FillConsoleOutputCharacterA(StdOutput,
+                                            0xDD,
+                                            1,
+                                            coPos,
+                                            &Written);
+                coPos.X++;
+            }
+
+            if (coPos.X <= Bar->Right - 1)
+            {
+                FillConsoleOutputCharacterA(StdOutput,
+                                            ' ',
+                                            Bar->Right - coPos.X,
+                                            coPos,
+                                            &Written);
+            }
+        }
     }
 }
 
index 948501c..4e48604 100644 (file)
 
 typedef struct _PROGRESS
 {
-  SHORT Left;
-  SHORT Top;
-  SHORT Right;
-  SHORT Bottom;
-  SHORT TextTop;
-  SHORT TextRight;
+    SHORT Left;
+    SHORT Top;
+    SHORT Right;
+    SHORT Bottom;
+    SHORT TextTop;
+    SHORT TextRight;
 
-  SHORT Width;
+    SHORT Width;
 
-  ULONG Percent;
-  SHORT Pos;
+    ULONG Percent;
+    SHORT Pos;
 
-  ULONG StepCount;
-  ULONG CurrentStep;
+    ULONG StepCount;
+    ULONG CurrentStep;
 
-  BOOLEAN Double;
-  CHAR *Text;
+    BOOLEAN Double;
+    CHAR *Text;
 } PROGRESSBAR, *PPROGRESSBAR;
 
 /* FUNCTIONS ****************************************************************/
 
 PPROGRESSBAR
-CreateProgressBar(SHORT Left,
-                 SHORT Top,
-                 SHORT Right,
-                 SHORT Bottom,
-          SHORT TextTop,
-          SHORT TextRight,
-          BOOLEAN DoubleEdge,
-          char* Text);
+CreateProgressBar(
+    SHORT Left,
+    SHORT Top,
+    SHORT Right,
+    SHORT Bottom,
+    SHORT TextTop,
+    SHORT TextRight,
+    BOOLEAN DoubleEdge,
+    CHAR *Text);
 
 VOID
-DestroyProgressBar(PPROGRESSBAR Bar);
+DestroyProgressBar(
+    PPROGRESSBAR Bar);
 
 VOID
-ProgressSetStepCount(PPROGRESSBAR Bar,
-                    ULONG StepCount);
+ProgressSetStepCount(
+    PPROGRESSBAR Bar,
+    ULONG StepCount);
 
 VOID
-ProgressNextStep(PPROGRESSBAR Bar);
+ProgressNextStep(
+    PPROGRESSBAR Bar);
 
 VOID
-ProgressSetStep (PPROGRESSBAR Bar,
-                ULONG Step);
+ProgressSetStep(
+    PPROGRESSBAR Bar,
+    ULONG Step);
 
 /* EOF */
index 493a17a..032c5d9 100644 (file)
 
 typedef struct _REG_DISK_MOUNT_INFO
 {
-  ULONG Signature;
-  LARGE_INTEGER StartingOffset;
+    ULONG Signature;
+    LARGE_INTEGER StartingOffset;
 } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
 
 #include <poppack.h>
 
 /* FUNCTIONS ****************************************************************/
 
-static BOOLEAN
-GetRootKey (PWCHAR Name)
+static
+BOOLEAN
+GetRootKey(
+    PWCHAR Name)
 {
-  if (!_wcsicmp (Name, L"HKCR"))
+    if (!_wcsicmp (Name, L"HKCR"))
     {
-      wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\");
-      return TRUE;
+        wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\");
+        return TRUE;
     }
 
-  if (!_wcsicmp (Name, L"HKCU"))
+    if (!_wcsicmp (Name, L"HKCU"))
     {
-      wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\");
-      return TRUE;
+        wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\");
+        return TRUE;
     }
 
-  if (!_wcsicmp (Name, L"HKLM"))
+    if (!_wcsicmp (Name, L"HKLM"))
     {
-      wcscpy (Name, L"\\Registry\\Machine\\");
-      return TRUE;
+        wcscpy (Name, L"\\Registry\\Machine\\");
+        return TRUE;
     }
 
-  if (!_wcsicmp (Name, L"HKU"))
+    if (!_wcsicmp (Name, L"HKU"))
     {
-      wcscpy (Name, L"\\Registry\\User\\");
-      return TRUE;
+        wcscpy (Name, L"\\Registry\\User\\");
+        return TRUE;
     }
 
 #if 0
-  if (!_wcsicmp (Name, L"HKR"))
-    return FALSE;
+    if (!_wcsicmp (Name, L"HKR"))
+        return FALSE;
 #endif
 
-  return FALSE;
+    return FALSE;
 }
 
 
@@ -500,7 +502,7 @@ CreateNestedKey (PHANDLE KeyHandle,
  * Called once for each AddReg and DelReg entry in a given section.
  */
 static BOOLEAN
-registry_callback (HINF hInf, PCWSTR Section, BOOLEAN Delete)
+registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete)
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   WCHAR Buffer[MAX_INF_STRING_LENGTH];
@@ -624,148 +626,154 @@ registry_callback (HINF hInf, PCWSTR Section, BOOLEAN Delete)
 
 
 BOOLEAN
-ImportRegistryFile(PWSTR Filename,
-                   PWSTR Section,
-                   LCID LocaleId,
-                   BOOLEAN Delete)
+ImportRegistryFile(
+    PWSTR Filename,
+    PWSTR Section,
+    LCID LocaleId,
+    BOOLEAN Delete)
 {
-  WCHAR FileNameBuffer[MAX_PATH];
-  HINF hInf;
-  UINT ErrorLine;
-
-  /* Load inf file from install media. */
-  wcscpy(FileNameBuffer, SourcePath.Buffer);
-  wcscat(FileNameBuffer, L"\\");
-  wcscat(FileNameBuffer, Filename);
-
-  hInf = SetupOpenInfFileW(
-                       FileNameBuffer,
-                       NULL,
-                       INF_STYLE_WIN4,
-                       LocaleId,
-                       &ErrorLine);
-  if (hInf == INVALID_HANDLE_VALUE)
+    WCHAR FileNameBuffer[MAX_PATH];
+    HINF hInf;
+    UINT ErrorLine;
+
+    /* Load inf file from install media. */
+    wcscpy(FileNameBuffer, SourcePath.Buffer);
+    wcscat(FileNameBuffer, L"\\");
+    wcscat(FileNameBuffer, Filename);
+
+    hInf = SetupOpenInfFileW(FileNameBuffer,
+                             NULL,
+                             INF_STYLE_WIN4,
+                             LocaleId,
+                             &ErrorLine);
+    if (hInf == INVALID_HANDLE_VALUE)
     {
-      DPRINT1("SetupOpenInfFile() failed\n");
-      return FALSE;
+        DPRINT1("SetupOpenInfFile() failed\n");
+        return FALSE;
     }
 
-  if (!registry_callback (hInf, L"AddReg", FALSE))
+    if (!registry_callback(hInf, L"AddReg", FALSE))
     {
-      DPRINT1("registry_callback() failed\n");
+        DPRINT1("registry_callback() failed\n");
     }
 
-  if (!registry_callback (hInf, L"AddReg.NT" Architecture, FALSE))
+    if (!registry_callback(hInf, L"AddReg.NT" Architecture, FALSE))
     {
-      DPRINT1("registry_callback() failed\n");
+        DPRINT1("registry_callback() failed\n");
     }
 
-  InfCloseFile (hInf);
+    InfCloseFile(hInf);
 
-  return TRUE;
+    return TRUE;
 }
 
 
 BOOLEAN
-SetInstallPathValue(PUNICODE_STRING InstallPath)
+SetInstallPathValue(
+    PUNICODE_STRING InstallPath)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE");
-  UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath");
-  HANDLE KeyHandle;
-  NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE");
+    UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath");
+    HANDLE KeyHandle;
+    NTSTATUS Status;
 
-  /* Create the 'secret' InstallPath key */
-  InitializeObjectAttributes (&ObjectAttributes,
-                              &KeyName,
-                              OBJ_CASE_INSENSITIVE,
-                              NULL,
-                              NULL);
-  Status =  NtOpenKey (&KeyHandle,
-                       KEY_ALL_ACCESS,
-                       &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
+    /* Create the 'secret' InstallPath key */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status =  NtOpenKey(&KeyHandle,
+                        KEY_ALL_ACCESS,
+                        &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
-      return FALSE;
+        DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
+        return FALSE;
     }
 
-  Status = NtSetValueKey (KeyHandle,
-                          &ValueName,
-                          0,
-                          REG_SZ,
-                          (PVOID)InstallPath->Buffer,
-                          InstallPath->Length + sizeof(WCHAR));
-  NtClose(KeyHandle);
-  if (!NT_SUCCESS(Status))
+    Status = NtSetValueKey(KeyHandle,
+                           &ValueName,
+                           0,
+                           REG_SZ,
+                           (PVOID)InstallPath->Buffer,
+                           InstallPath->Length + sizeof(WCHAR));
+    NtClose(KeyHandle);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
-      return FALSE;
+        DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
+        return FALSE;
     }
 
-  return TRUE;
+    return TRUE;
 }
 
+
 BOOLEAN
-SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset)
+SetMountedDeviceValue(
+    CHAR Letter,
+    ULONG Signature,
+    LARGE_INTEGER StartingOffset)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  WCHAR ValueNameBuffer[16];
-  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
-  UNICODE_STRING ValueName;
-  REG_DISK_MOUNT_INFO MountInfo;
-  NTSTATUS Status;
-  HANDLE KeyHandle;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    WCHAR ValueNameBuffer[16];
+    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
+    UNICODE_STRING ValueName;
+    REG_DISK_MOUNT_INFO MountInfo;
+    NTSTATUS Status;
+    HANDLE KeyHandle;
 
-  swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter);
-  RtlInitUnicodeString(&ValueName, ValueNameBuffer);
+    swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter);
+    RtlInitUnicodeString(&ValueName, ValueNameBuffer);
 
-  InitializeObjectAttributes (&ObjectAttributes,
-                              &KeyName,
-                              OBJ_CASE_INSENSITIVE,
-                              NULL,
-                              NULL);
-  Status =  NtOpenKey (&KeyHandle,
-                       KEY_ALL_ACCESS,
-                       &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status =  NtOpenKey(&KeyHandle,
+                        KEY_ALL_ACCESS,
+                        &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
     {
-      Status = NtCreateKey(&KeyHandle,
-                           KEY_ALL_ACCESS,
-                           &ObjectAttributes,
-                           0,
-                           NULL,
-                           REG_OPTION_NON_VOLATILE,
-                           NULL);
+        Status = NtCreateKey(&KeyHandle,
+                             KEY_ALL_ACCESS,
+                             &ObjectAttributes,
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             NULL);
     }
 
-  if (!NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
-      return FALSE;
+        DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
+        return FALSE;
     }
 
-  MountInfo.Signature = Signature;
-  MountInfo.StartingOffset = StartingOffset;
-  Status = NtSetValueKey (KeyHandle,
-                          &ValueName,
-                          0,
-                          REG_BINARY,
-                          (PVOID)&MountInfo,
-                          sizeof(MountInfo));
-  NtClose(KeyHandle);
-  if (!NT_SUCCESS(Status))
+    MountInfo.Signature = Signature;
+    MountInfo.StartingOffset = StartingOffset;
+    Status = NtSetValueKey(KeyHandle,
+                           &ValueName,
+                           0,
+                           REG_BINARY,
+                           (PVOID)&MountInfo,
+                           sizeof(MountInfo));
+    NtClose(KeyHandle);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
-      return FALSE;
+        DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
+        return FALSE;
     }
 
-  return TRUE;
+    return TRUE;
 }
 
 
 VOID
-SetDefaultPagefile(WCHAR Drive)
+SetDefaultPagefile(
+    WCHAR Drive)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
index 2b23cd8..de02b0e 100644 (file)
 #pragma once
 
 BOOLEAN
-ImportRegistryFile(PWSTR Filename,
-                  PWSTR Section,
-                  LCID LocaleId,
-                  BOOLEAN Delete);
+ImportRegistryFile(
+    PWSTR Filename,
+    PWSTR Section,
+    LCID LocaleId,
+    BOOLEAN Delete);
 
 BOOLEAN
-SetInstallPathValue(PUNICODE_STRING InstallPath);
+SetInstallPathValue(
+    PUNICODE_STRING InstallPath);
 
 BOOLEAN
-SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset);
+SetMountedDeviceValue(
+    CHAR Letter,
+    ULONG Signature,
+    LARGE_INTEGER StartingOffset);
 
 VOID
-SetDefaultPagefile(WCHAR Drive);
+SetDefaultPagefile(
+    WCHAR Drive);
 
 /* EOF */
index 7dcb329..0346167 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/* GLOBALS ******************************************************************/
+
+ULONG DefaultLanguageIndex = 0;
+
 /* FUNCTIONS ****************************************************************/
 
-static BOOLEAN
+static
+BOOLEAN
 IsAcpiComputer(VOID)
 {
-   UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
-   UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
-   UNICODE_STRING AcpiBiosIdentifier = RTL_CONSTANT_STRING(L"ACPI BIOS");
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
-   ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
-   PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
-   ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
-   ULONG RequiredSize;
-   ULONG IndexDevice = 0;
-   UNICODE_STRING DeviceName, ValueName;
-   HANDLE hDevicesKey = NULL;
-   HANDLE hDeviceKey = NULL;
-   NTSTATUS Status;
-   BOOLEAN ret = FALSE;
-
-   InitializeObjectAttributes(&ObjectAttributes, &MultiKeyPathU, OBJ_CASE_INSENSITIVE, NULL, NULL);
-   Status = NtOpenKey(&hDevicesKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status);
-      goto cleanup;
-   }
+    UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
+    UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
+    UNICODE_STRING AcpiBiosIdentifier = RTL_CONSTANT_STRING(L"ACPI BIOS");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
+    ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
+    PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
+    ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
+    ULONG RequiredSize;
+    ULONG IndexDevice = 0;
+    UNICODE_STRING DeviceName, ValueName;
+    HANDLE hDevicesKey = NULL;
+    HANDLE hDeviceKey = NULL;
+    NTSTATUS Status;
+    BOOLEAN ret = FALSE;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &MultiKeyPathU,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&hDevicesKey,
+                       KEY_ENUMERATE_SUB_KEYS,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status);
+        goto cleanup;
+    }
 
    pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength);
    if (!pDeviceInformation)
@@ -170,9 +181,11 @@ cleanup:
 }
 
 
-static BOOLEAN
-GetComputerIdentifier(PWSTR Identifier,
-                      ULONG IdentifierLength)
+static
+BOOLEAN
+GetComputerIdentifier(
+    PWSTR Identifier,
+    ULONG IdentifierLength)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -212,14 +225,12 @@ GetComputerIdentifier(PWSTR Identifier,
     }
 
     /* Get number of subkeys */
-    Status = NtQueryKey(
-        ProcessorsKey,
-        KeyFullInformation,
-        pFullInfo,
-        Size,
-        &Size);
+    Status = NtQueryKey(ProcessorsKey,
+                        KeyFullInformation,
+                        pFullInfo,
+                        Size,
+                        &Size);
     NtClose(ProcessorsKey);
-
     if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
     {
         DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
@@ -276,7 +287,8 @@ GetComputerIdentifier(PWSTR Identifier,
 
 
 PGENERIC_LIST
-CreateComputerTypeList(HINF InfFile)
+CreateComputerTypeList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -364,8 +376,10 @@ CreateComputerTypeList(HINF InfFile)
 }
 
 
-static BOOLEAN
-GetDisplayIdentifier(PWSTR Identifier,
+static
+BOOLEAN
+GetDisplayIdentifier(
+    PWSTR Identifier,
     ULONG IdentifierLength)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -530,7 +544,8 @@ GetDisplayIdentifier(PWSTR Identifier,
 
 
 PGENERIC_LIST
-CreateDisplayDriverList(HINF InfFile)
+CreateDisplayDriverList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -630,8 +645,12 @@ CreateDisplayDriverList(HINF InfFile)
     return List;
 }
 
+
 BOOLEAN
-ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName)
+ProcessComputerFiles(
+    HINF InfFile,
+    PGENERIC_LIST List,
+    PWCHAR *AdditionalSectionName)
 {
     PGENERIC_LIST_ENTRY Entry;
     static WCHAR SectionName[128];
@@ -654,7 +673,9 @@ ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSection
 
 
 BOOLEAN
-ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
+ProcessDisplayRegistry(
+    HINF InfFile,
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     INFCONTEXT Context;
@@ -692,12 +713,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     StartValue = 1;
     Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
-        ServiceName,
-        L"Start",
-        REG_DWORD,
-        &StartValue,
-        sizeof(ULONG));
-
+                                   ServiceName,
+                                   L"Start",
+                                   REG_DWORD,
+                                   &StartValue,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -715,11 +735,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Width = wcstoul(Buffer, NULL, 10);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.XResolution",
-        REG_DWORD,
-        &Width,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.XResolution",
+                                   REG_DWORD,
+                                   &Width,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -734,11 +754,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Height = wcstoul(Buffer, 0, 0);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.YResolution",
-        REG_DWORD,
-        &Height,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.YResolution",
+                                   REG_DWORD,
+                                   &Height,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -753,11 +773,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Bpp = wcstoul(Buffer, 0, 0);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.BitsPerPel",
-        REG_DWORD,
-        &Bpp,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.BitsPerPel",
+                                   REG_DWORD,
+                                   &Bpp,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -771,7 +791,8 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
 
 BOOLEAN
-ProcessLocaleRegistry(PGENERIC_LIST List)
+ProcessLocaleRegistry(
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     PWCHAR LanguageId;
@@ -807,7 +828,6 @@ ProcessLocaleRegistry(PGENERIC_LIST List)
     Status =  NtOpenKey(&KeyHandle,
                         KEY_SET_VALUE,
                         &ObjectAttributes);
-
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
@@ -851,7 +871,8 @@ ProcessLocaleRegistry(PGENERIC_LIST List)
 
 
 PGENERIC_LIST
-CreateKeyboardDriverList(HINF InfFile)
+CreateKeyboardDriverList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -879,9 +900,9 @@ CreateKeyboardDriverList(HINF InfFile)
             break;
         }
 
-        UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                            0,
-                                            (wcslen(KeyName) + 1) * sizeof(WCHAR));
+        UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                           0,
+                                           (wcslen(KeyName) + 1) * sizeof(WCHAR));
         if (UserData == NULL)
         {
             /* FIXME: Handle error! */
@@ -896,7 +917,6 @@ CreateKeyboardDriverList(HINF InfFile)
     return List;
 }
 
-ULONG DefaultLanguageIndex = 0;
 
 ULONG
 GetDefaultLanguageIndex(VOID)
@@ -904,8 +924,11 @@ GetDefaultLanguageIndex(VOID)
     return DefaultLanguageIndex;
 }
 
+
 PGENERIC_LIST
-CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage) 
+CreateLanguageList(
+    HINF InfFile,
+    WCHAR *DefaultLanguage) 
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -980,8 +1003,11 @@ CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
     return List;
 }
 
+
 PGENERIC_LIST
-CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
+CreateKeyboardLayoutList(
+    HINF InfFile,
+    WCHAR *DefaultKBLayout)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -1028,10 +1054,9 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
 
             if (_wcsicmp(LayoutsList[uIndex].LayoutID, KeyName) == 0)
             {
-                UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                                0,
-                                                (wcslen(KeyName) + 1) * sizeof(WCHAR));
-
+                UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                   0,
+                                                   (wcslen(KeyName) + 1) * sizeof(WCHAR));
                 if (UserData == NULL)
                 {
                     /* FIXME: Handle error! */
@@ -1067,8 +1092,10 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
     return List;
 }
 
+
 BOOLEAN
-ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
+ProcessKeyboardLayoutRegistry(
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     PWCHAR LayoutId;
@@ -1117,14 +1144,17 @@ ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
 
 #if 0
 BOOLEAN
-ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
+ProcessKeyboardLayoutFiles(
+    PGENERIC_LIST List)
 {
     return TRUE;
 }
 #endif
 
+
 BOOLEAN
-SetGeoID(PWCHAR Id)
+SetGeoID(
+    PWCHAR Id)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -1133,6 +1163,7 @@ SetGeoID(PWCHAR Id)
     WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
     WCHAR szValueName[] = L"Nation";
     NTSTATUS Status;
+
     RtlInitUnicodeString(&KeyName,
                          szKeyName);
     InitializeObjectAttributes(&ObjectAttributes,
@@ -1143,24 +1174,25 @@ SetGeoID(PWCHAR Id)
 
     Status =  NtOpenKey(&KeyHandle,
                         KEY_SET_VALUE,
-                         &ObjectAttributes);
+                        &ObjectAttributes);
     if(!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
         return FALSE;
     }
+
     RtlInitUnicodeString(&ValueName, szValueName);
     Status = NtSetValueKey(KeyHandle,
-                                   &ValueName,
-                                   0,
-                                   REG_SZ,
-                                   (PVOID)Id,
-                                   (wcslen(Id) + 1) * sizeof(WCHAR));
+                           &ValueName,
+                           0,
+                           REG_SZ,
+                           (PVOID)Id,
+                           (wcslen(Id) + 1) * sizeof(WCHAR));
     NtClose(KeyHandle);
     if (!NT_SUCCESS(Status))
     {
-         DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
-         return FALSE;
+        DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
+        return FALSE;
     }
 
     return TRUE;
index fb8cd3c..5282474 100644 (file)
 #pragma once
 
 PGENERIC_LIST
-CreateComputerTypeList(HINF InfFile);
+CreateComputerTypeList(
+    HINF InfFile);
 
 PGENERIC_LIST
-CreateDisplayDriverList(HINF InfFile);
+CreateDisplayDriverList(
+    HINF InfFile);
 
 BOOLEAN
-ProcessComputerFiles(HINF InfFile,
-                      PGENERIC_LIST List,
-                      PWCHAR* AdditionalSectionName);
+ProcessComputerFiles(
+    HINF InfFile,
+    PGENERIC_LIST List,
+    PWCHAR *AdditionalSectionName);
 
 BOOLEAN
-ProcessDisplayRegistry(HINF InfFile,
-                      PGENERIC_LIST List);
+ProcessDisplayRegistry(
+    HINF InfFile,
+    PGENERIC_LIST List);
 
 PGENERIC_LIST
-CreateKeyboardDriverList(HINF InfFile);
+CreateKeyboardDriverList(
+    HINF InfFile);
 
 PGENERIC_LIST
-CreateKeyboardLayoutList(HINF InfFile, WCHAR *DefaultKBLayout);
+CreateKeyboardLayoutList(
+    HINF InfFile,
+    WCHAR *DefaultKBLayout);
 
-PGENERIC_LIST 
-CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage);
+PGENERIC_LIST
+CreateLanguageList(
+    HINF InfFile,
+    WCHAR *DefaultLanguage);
 
 ULONG
 GetDefaultLanguageIndex(VOID);
 
 BOOLEAN
-ProcessLocaleRegistry(PGENERIC_LIST List);
+ProcessLocaleRegistry(
+    PGENERIC_LIST List);
 
 BOOLEAN
-ProcessKeyboardLayoutRegistry(PGENERIC_LIST List);
+ProcessKeyboardLayoutRegistry(
+    PGENERIC_LIST List);
 
 BOOLEAN
-ProcessKeyboardLayoutFiles(PGENERIC_LIST List);
+ProcessKeyboardLayoutFiles(
+    PGENERIC_LIST List);
 
 BOOLEAN
-SetGeoID(PWCHAR Id);
+SetGeoID(
+    PWCHAR Id);
 
 /* EOF */
index 2dfb99b..dd88ca8 100644 (file)
@@ -113,43 +113,43 @@ extern BOOLEAN InfGetStringField(PINFCONTEXT Context,
 #define _PAGE_NUMBER_DEFINED
 typedef enum _PAGE_NUMBER
 {
-  START_PAGE,
-  LANGUAGE_PAGE,
-  INTRO_PAGE,
-  LICENSE_PAGE,
-  INSTALL_INTRO_PAGE,
-
-//  SCSI_CONTROLLER_PAGE,
-
-  DEVICE_SETTINGS_PAGE,
-  COMPUTER_SETTINGS_PAGE,
-  DISPLAY_SETTINGS_PAGE,
-  KEYBOARD_SETTINGS_PAGE,
-  LAYOUT_SETTINGS_PAGE,
-
-  SELECT_PARTITION_PAGE,
-  CREATE_PARTITION_PAGE,
-  DELETE_PARTITION_PAGE,
-
-  SELECT_FILE_SYSTEM_PAGE,
-  FORMAT_PARTITION_PAGE,
-  CHECK_FILE_SYSTEM_PAGE,
-
-  PREPARE_COPY_PAGE,
-  INSTALL_DIRECTORY_PAGE,
-  FILE_COPY_PAGE,
-  REGISTRY_PAGE,
-  BOOT_LOADER_PAGE,
-  BOOT_LOADER_FLOPPY_PAGE,
-  BOOT_LOADER_HARDDISK_MBR_PAGE,
-  BOOT_LOADER_HARDDISK_VBR_PAGE,
-
-  REPAIR_INTRO_PAGE,
-
-  SUCCESS_PAGE,
-  QUIT_PAGE,
-  FLUSH_PAGE,
-  REBOOT_PAGE,                 /* virtual page */
+    START_PAGE,
+    LANGUAGE_PAGE,
+    INTRO_PAGE,
+    LICENSE_PAGE,
+    INSTALL_INTRO_PAGE,
+
+//    SCSI_CONTROLLER_PAGE,
+
+    DEVICE_SETTINGS_PAGE,
+    COMPUTER_SETTINGS_PAGE,
+    DISPLAY_SETTINGS_PAGE,
+    KEYBOARD_SETTINGS_PAGE,
+    LAYOUT_SETTINGS_PAGE,
+
+    SELECT_PARTITION_PAGE,
+    CREATE_PARTITION_PAGE,
+    DELETE_PARTITION_PAGE,
+
+    SELECT_FILE_SYSTEM_PAGE,
+    FORMAT_PARTITION_PAGE,
+    CHECK_FILE_SYSTEM_PAGE,
+
+    PREPARE_COPY_PAGE,
+    INSTALL_DIRECTORY_PAGE,
+    FILE_COPY_PAGE,
+    REGISTRY_PAGE,
+    BOOT_LOADER_PAGE,
+    BOOT_LOADER_FLOPPY_PAGE,
+    BOOT_LOADER_HARDDISK_MBR_PAGE,
+    BOOT_LOADER_HARDDISK_VBR_PAGE,
+
+    REPAIR_INTRO_PAGE,
+
+    SUCCESS_PAGE,
+    QUIT_PAGE,
+    FLUSH_PAGE,
+    REBOOT_PAGE,               /* virtual page */
 } PAGE_NUMBER, *PPAGE_NUMBER;
 #endif
 
index 9a1528d..657dcb7 100644 (file)
@@ -4,24 +4,24 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
 
 IDD_WELCOMEPAGE DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "ReactOS Kur, VMWare(r)'de çalıştığını algıladı.", -1, 117, 8, 140, 24
-    LTEXT "VMware(r) SVGA sürücüsünü kurmak için ""İleri"" düğmesine tıklayınız. Eğer sürücüyü kurmak istemiyorsanız ""İptal"" düğmesine tıklayınız.", -1, 117, 140, 140, 24
+    LTEXT "ReactOS Kur, sizin ReactOS'u VMWare(r)'de çalıştırdığınızı algıladı.", -1, 117, 8, 140, 24
+    LTEXT "Eğer VMware(r) SVGA sürücüsünü kurmayı istiyorsanız ""İleri""ye tıklayınız, yoksa ""İptal""e tıklayınız.", -1, 117, 140, 140, 24
 END
 
 IDD_INSERT_VMWARE_TOOLS DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsüyle birlikte gelmez.\n\nBu yüzden, VMWare(r)'de bulunan ""Install VMware tools..."" seçeneğine tıklayınız.\n\n\nİşlemi sürdürmek için ""İleri"" düğmesine, sürücünün kurulumunu atlamak için ""İptal"" düğmesine tıklayınız.", -1, 25, 25, 225, 85
+    LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsüyle gelmez.\n\nBu yüzden VMWare(r) seçke çubuğunuzdaki ""VM""ye gidiniz ve ""Install VMware tools...""u seçiniz.\n\n\nSürdürmek için ""İleri""ye ya da SVGA sürücüsünün kurulumunu atlamak için ""İptal""e tıklayınız.", -1, 25, 25, 225, 85
 END
 
 IDD_INSTALLING_VMWARE_TOOLS DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     LTEXT "{STATUS}", IDC_INSTALLINGSTATUS, 25, 68, 225, 8
@@ -30,10 +30,10 @@ END
 
 IDD_CONFIG DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "VMware(r) SVGA sürücüsü, başarılı bir şekilde kuruldu. Aşağıdaki çözünürlüklerden birini seçiniz:", -1, 25, 5, 225, 20
+    LTEXT "VMware(r) SVGA sürücüsü, başarılı bir şekilde kuruldu. Lütfen gözde görüntülük çözünürlüğünüzü seçiniz:", -1, 25, 5, 225, 20
     PUSHBUTTON "640x480", 1120, 25, 30, 65, 15, BS_AUTORADIOBUTTON
     PUSHBUTTON "800x600", 1400, 25, 45, 65, 15, BS_AUTORADIOBUTTON
     PUSHBUTTON "1024x768", 1792, 25, 60, 65, 15, BS_AUTORADIOBUTTON
@@ -45,89 +45,89 @@ BEGIN
     PUSHBUTTON "1792x1344", 3136, 195, 30, 65, 15, BS_AUTORADIOBUTTON
     PUSHBUTTON "1856x1392", 3248, 195, 45, 65, 15, BS_AUTORADIOBUTTON
     PUSHBUTTON "1920x1440", 3360, 195, 60, 50, 15, BS_AUTORADIOBUTTON
-    LTEXT "Aşağıdaki derinliklerden birini seçiniz:", -1, 25, 93, 225, 12
+    LTEXT "Lütfen gözde renk derinliğinizi seçiniz:", -1, 25, 93, 225, 12
     COMBOBOX IDC_COLORQUALITY, 25, 105, 75, 80, CBS_DROPDOWNLIST | WS_TABSTOP
 END
 
 IDD_INSTALLATION_FAILED DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kuramadı.\n\n\nReactOS kurulumunu sürdürmek için ""Bitir"" düğmesine tıklayınız.", -1, 25, 25, 225, 85
+    LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kuramadı.\n\n\nKurulum işlemini sürdürmek için ""Bitir""e tıklayınız.", -1, 25, 25, 225, 85
 END
 
 IDD_CHOOSEACTION DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "VMware(r) SVGA sürücüsü, daha önceden kurulmuş.\n\nNe yapmak istediğinizi seçiniz:", -1, 25, 5, 225, 30
-    PUSHBUTTON "Görüntülük Ayarlarını Yapılandırmak", IDC_CONFIGSETTINGS, 25, 40, 200, 15, BS_AUTORADIOBUTTON
-    PUSHBUTTON "Başka Bir Görüntülük Sürücüsü Kurmak", IDC_USEOTHERDRIVER, 25, 55, 200, 15, BS_AUTORADIOBUTTON
-    PUSHBUTTON "VMware(r) SVGA Sürücüsünü Kaldırmak", IDC_UNINSTALL, 25, 70, 200, 15, BS_AUTORADIOBUTTON
-    LTEXT "Sürdürmek için ""İleri"" düğmesine, çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 93, 225, 19
+    LTEXT "VMware(r) SVGA sürücüsü önceden kurulmuş.\n\nLütfen ne yapmak istediğinizi seçiniz:", -1, 25, 5, 225, 30
+    PUSHBUTTON "Görüntülük Ayarlarını Yapılandırma", IDC_CONFIGSETTINGS, 25, 40, 200, 15, BS_AUTORADIOBUTTON
+    PUSHBUTTON "Başka Bir Çizge Sürücüsü Kurma", IDC_USEOTHERDRIVER, 25, 55, 200, 15, BS_AUTORADIOBUTTON
+    PUSHBUTTON "VMware(r) SVGA Sürücüsünü Kaldırma", IDC_UNINSTALL, 25, 70, 200, 15, BS_AUTORADIOBUTTON
+    LTEXT "Sürdürmek için ""İleri""ye ya da büyücüden çıkmak için ""İptal""e tıklayınız.", -1, 25, 93, 225, 19
 END
 
 IDD_SELECTDRIVER DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "Kullanmak istediğiniz görüntülük sürücüsünü seçiniz:", -1, 25, 25, 225, 15
+    LTEXT "Lütfen kullanmak istediğiniz çizge sürücüsünü seçiniz:", -1, 25, 25, 225, 15
     PUSHBUTTON "ReactOS VGA Sürücüsü", IDC_VGA, 25, 40, 225, 15, BS_AUTORADIOBUTTON
     PUSHBUTTON "ReactOS VBE Sürücüsü (SVGA)", IDC_VBE, 25, 55, 225, 15, BS_AUTORADIOBUTTON
-    LTEXT "İşlemi bitirmek için ""Bitir"" düğmesine, hiçbir değişiklik yapmadan çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 93, 225, 20
+    LTEXT "İşlemi bitirmek için ""Bitir""e ya da değişiklik yapmadan kurulumdan çıkmak için ""İptal""e tıklayınız.", -1, 25, 93, 225, 20
 END
 
 IDD_DOUNINSTALL DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Görüntülük Sürücüsü Kurulumu"
+CAPTION "Vidyo Sürücüsü Kurulumu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kaldırmak üzere.\n\n\nKaldırmayı bitirmek için ""Bitir"" düğmesine, hiçbir değişiklik yapılmadan çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 25, 225, 85
+    LTEXT "ReactOS Kur, VMware(r) SVGA sürücünüzü kaldırmak üzere.\n\n\nSürücüyü kaldırmak için ""Bitir""e ya da onu olduğu gibi bırakmak için ""İptal""e tıklayınız.", -1, 25, 25, 225, 85
 END
 
 STRINGTABLE
 BEGIN
     IDS_WIZARD_NAME "VMware(r) algılandı."
-    IDS_FAILEDTOLOCATEDRIVERS "ReactOS Kur, gerekli kütükleri bulamadı.\nVMWare(r) Araç CD'sini bağladığınızı doğrulayınız."
-    IDS_FAILEDTOCOPYFILES "ReactOS Kur, gerekli kütükleri çoğaltamadı.\nVMWare(r) Araç CD'sini bağladığınızı doğrulayınız.\n"
-    IDS_FAILEDTOACTIVATEDRIVER "VMware(r) SVGA sürücüsünün etkinleştirilmesi başarısız oldu."
-    IDS_FAILEDTOSELVGADRIVER "ReactOS VGA sürücüsünün etkinleştirilmesi başarısız oldu."
-    IDS_FAILEDTOSELVBEDRIVER "ReactOS VBE sürücüsünün etkinleştirilmesi başarısız oldu."
-    IDS_UNINSTNOTICE "VMware(r) SVGA sürücüsünün kütükleri silinmedi.\nOnları, dizgeyi yeniden başlatma sonrasında siliniz."
-    IDS_FAILEDTOADDREGENTRIES "VMware(r) SVGA sürücüsünün değerleri oluşturulamadı."
+    IDS_FAILEDTOLOCATEDRIVERS "ReactOS Kur gerekli kütükleri bulamadı.\nVMWare(r) Araç CD-ROM'unun takılı olduğundan emin olunuz."
+    IDS_FAILEDTOCOPYFILES "ReactOS Kur gerekli kütükleri çoğaltamadı.\nVMWare(r) Araç CD-ROM'unun takılı olduğundan emin olunuz.\n"
+    IDS_FAILEDTOACTIVATEDRIVER "VMware(r) SVGA sürücüsünü etkinleştirme başarısız oldu."
+    IDS_FAILEDTOSELVGADRIVER "ReactOS VGA sürücüsünü etkinleştirme başarısız oldu."
+    IDS_FAILEDTOSELVBEDRIVER "ReactOS VBE sürücüsünü etkinleştirme başarısız oldu."
+    IDS_UNINSTNOTICE "VMware(r) SVGA sürücüsünün kütükleri daha silinmedi.\nLütfen onları bir yeniden başlatmadan sonra elle siliniz."
+    IDS_FAILEDTOADDREGENTRIES "VMware(r) SVGA sürücüsü için değer defteri girdilerinin oluşturulması başarısız oldu."
 END
 
 STRINGTABLE
 BEGIN
-    10001 "Düşük (8 İkillik)"
-    10002 "Orta (16 İkillik)"
-    10003 "Yüksek (32 İkillik)"
+    10001 "En Düşük (Her Noktada 8 Bit)"
+    10002 "Orta (Her Noktada 16 Bit)"
+    10003 "En Yüksek (Her Noktada 32 Bit)"
 END
 
 STRINGTABLE
 BEGIN
-    IDS_SEARCHINGFORCDROM "VMWare(r) Araç CD'si aranıyor..."
+    IDS_SEARCHINGFORCDROM "VMWare(r) Araç CD-ROM'u aranıyor..."
     IDS_COPYINGFILES "Kütükler çoğaltılıyor..."
     IDS_ENABLINGDRIVER "VMware(r) SVGA sürücüsü etkinleştiriliyor..."
 END
 
 STRINGTABLE
 BEGIN
-    IDD_INSERT_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
-    IDD_INSERT_VMWARE_TOOLSSUBTITLE "VMWare(r) Araç CD'sini bağlayınız."
-    IDD_INSTALLING_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
-    IDD_INSTALLING_VMWARE_TOOLSSUBTITLE "VMware(r) SVGA sürücüsünü bulunuz ve çoğaltınız."
-    IDD_CONFIGTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
-    IDD_CONFIGSUBTITLE "Çözünürlüklerden birini seçiniz."
-    IDD_INSTALLATION_FAILEDTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
+    IDD_INSERT_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
+    IDD_INSERT_VMWARE_TOOLSSUBTITLE "Lütfen VMWare(r) Araç CD-ROM'unu takınız."
+    IDD_INSTALLING_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
+    IDD_INSTALLING_VMWARE_TOOLSSUBTITLE "VMware(r) SVGA sürücüsünü arayınız ve çoğaltınız."
+    IDD_CONFIGTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
+    IDD_CONFIGSUBTITLE "Gözde görüntülük çözünürlüğünüzü seçiniz."
+    IDD_INSTALLATION_FAILEDTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
     IDD_INSTALLATION_FAILEDSUBTITLE "VMware(r) SVGA sürücüsünün kurulumu başarısız oldu."
-    IDD_CHOOSEACTIONTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
+    IDD_CHOOSEACTIONTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
     IDD_CHOOSEACTIONSUBTITLE "Ne yapmak istediğinizi seçiniz."
-    IDD_SELECTDRIVERTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
+    IDD_SELECTDRIVERTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
     IDD_SELECTDRIVERSUBTITLE "Bir sürücü seçiniz."
-    IDD_DOUNINSTALLTITLE "VMware(r) SVGA Sürücüsünün Kurulumu"
+    IDD_DOUNINSTALLTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü"
     IDD_DOUNINSTALLSUBTITLE "Sürücüyü kaldırınız."
 END
index 6ff883b..835aa28 100644 (file)
@@ -77,12 +77,12 @@ IDB_HEADER BITMAP "resources/header.bmp"
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
-#ifdef LANGUAGE_SV_SE
-    #include "lang/sv-SE.rc"
-#endif
 #ifdef LANGUAGE_SQ_AL
     #include "lang/sq-AL.rc"
 #endif
+#ifdef LANGUAGE_SV_SE
+    #include "lang/sv-SE.rc"
+#endif
 #ifdef LANGUAGE_TR_TR
     #include "lang/tr-TR.rc"
 #endif
index d91b208..78802c6 100644 (file)
@@ -7,10 +7,10 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
 /* Default settings */
 STRINGTABLE
 BEGIN
-    IDS_APPTITLE "ReactOS - Hoşgeldiniz Uygulaması"
-    IDS_DEFAULTTOPICTITLE "ReactOS - Hoşgeldiniz Uygulaması"
-    IDS_DEFAULTTOPICDESC "React İşletim Dizgesi'ne hoşgeldiniz.\n\nFârenizi, soldaki herhangi bir seçeneğe götürebilirsiniz."
-//    IDS_CHECKTEXT "Bir sonraki sefere bu pencereyi göster."
+    IDS_APPTITLE "ReactOS - Hoşgeldiniz"
+    IDS_DEFAULTTOPICTITLE "ReactOS"
+    IDS_DEFAULTTOPICDESC "React İşletim Dizgesi'ne hoşgeldiniz.\n\nSolda bir konuya tıklayınız."
+//    IDS_CHECKTEXT "Bu iletiyi yine göster."
 //    IDS_CLOSETEXT "Çıkış"
 END
 
@@ -18,7 +18,7 @@ END
 STRINGTABLE
 BEGIN
     IDS_TOPICBUTTON0 "ReactOS'u Kur"
-    IDS_TOPICBUTTON1 "CD'nin İçini Araştır"
+    IDS_TOPICBUTTON1 "Bu CD'yi Araştır"
     IDS_TOPICBUTTON2 "Çıkış"
 //    IDS_TOPICBUTTON3 "Empty Topic 3"
 //    IDS_TOPICBUTTON4 "Empty Topic 4"
@@ -33,7 +33,7 @@ END
 STRINGTABLE
 BEGIN
     IDS_TOPICTITLE0 "ReactOS'u Kur"
-    IDS_TOPICTITLE1 "CD'nin İçini Araştır"
+    IDS_TOPICTITLE1 "Bu CD'yi Araştır"
     IDS_TOPICTITLE2 "Çıkış"
 //    IDS_TOPICTITLE3 "Empty Topic Title 3"
 //    IDS_TOPICTITLE4 "Empty Topic Title 4"
@@ -47,9 +47,9 @@ END
 /* Topic descriptions */
 STRINGTABLE
 BEGIN
-    IDS_TOPICDESC0 "Bu seçenek ile bilgisayarınıza ReactOS yükleyebilir ya da bilgisayarınızda var olan bir ReactOS yüklemesini yükseltebilirsiniz."
-    IDS_TOPICDESC1 "CD'deki kütükleri gösterir."
-    IDS_TOPICDESC2 "Bu uygulamadan çıkar."
+    IDS_TOPICDESC0 "Bilgisayarınıza yeni bir ReactOS yükleyiniz ya da var olan bir yüklemeyi yükseltiniz."
+    IDS_TOPICDESC1 "CD'yi araştır."
+    IDS_TOPICDESC2 "Bu uygulamadan çıkmak için tıklayınız."
 //    IDS_TOPICDESC3 "Topic description 3.\n\nDescribe topic 3 here."
 //    IDS_TOPICDESC4 "Topic description 4.\n\nDescribe topic 4 here."
 //    IDS_TOPICDESC5 "Topic description 5.\n\nDescribe topic 5 here."
index 655fcf2..2391afe 100644 (file)
@@ -116,6 +116,9 @@ END
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
+#ifdef LANGUAGE_SQ_AL
+    #include "lang/sq-AL.rc"
+#endif
 #ifdef LANGUAGE_SV_SE
     #include "lang/sv-SE.rc"
 #endif
@@ -125,9 +128,6 @@ END
 #ifdef LANGUAGE_TR_TR
     #include "lang/tr-TR.rc"
 #endif
-#ifdef LANGUAGE_SQ_AL
-    #include "lang/sq-AL.rc"
-#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index a5f896d..c5c127f 100644 (file)
@@ -200,7 +200,7 @@ copy(TCHAR source[MAX_PATH],
     }
 
     /* A page-aligned buffer usually give more speed */
-    buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE);
+    buffer = VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE);
     if (buffer == NULL)
     {
         CloseHandle (hFileDest);
index 4b139c8..864e3fb 100644 (file)
@@ -160,7 +160,7 @@ INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *d
     }
 
     /* Get buffer for the copy process */
-    buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE);
+    buffer = VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE);
     if (buffer == NULL)
     {
         CloseHandle (hFileDest);
@@ -188,7 +188,7 @@ INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *d
         if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT))
         {
             ConOutResPuts(STRING_COPY_ERROR3);
-            cmd_free (buffer);
+            VirtualFree (buffer, 0, MEM_RELEASE);
             CloseHandle (hFileDest);
             CloseHandle (hFileSrc);
             nErrorLevel = 1;
index 5258cae..95ea952 100644 (file)
@@ -11,8 +11,8 @@ BEGIN
         MENUITEM "&Bildirimleri Husûsileştir...", ID_SHELL_CMD_CUST_NOTIF
         MENUITEM SEPARATOR
         MENUITEM "&Pencereleri Basamakla", ID_SHELL_CMD_CASCADE_WND
-        MENUITEM "P&encereleri Üst Üste Sırala", ID_SHELL_CMD_TILE_WND_H
-        MENUITEM "Pe&ncereleri Yan Yana Sırala", ID_SHELL_CMD_TILE_WND_V
+        MENUITEM "P&encereleri Yatay Olarak Döşe", ID_SHELL_CMD_TILE_WND_H
+        MENUITEM "Pe&ncereleri Dikey Olarak Döşe", ID_SHELL_CMD_TILE_WND_V
         MENUITEM "&Masaüstünü Göster", ID_SHELL_CMD_SHOW_DESKTOP
         MENUITEM "&Geri Al", ID_SHELL_CMD_UNDO_ACTION
         MENUITEM SEPARATOR
@@ -28,11 +28,11 @@ BEGIN
     POPUP ""
     BEGIN
         MENUITEM "", -1, MFT_SEPARATOR
-        POPUP "&Yazılımlar", IDM_PROGRAMS
+        POPUP "&İzlenceler", IDM_PROGRAMS
         BEGIN
             MENUITEM "(Boş)", -1, MFT_STRING, MFS_GRAYED
         END
-        POPUP "Y&er İmleri", IDM_FAVORITES
+        POPUP "&Yer İmleri", IDM_FAVORITES
         BEGIN
             MENUITEM "(Boş)", -1, MFT_STRING, MFS_GRAYED
         END
@@ -56,11 +56,11 @@ BEGIN
         MENUITEM "Yar&dım ve Destek", IDM_HELPANDSUPPORT, MFT_STRING, MFS_ENABLED
         MENUITEM "&Çalıştır...", IDM_RUN, MFT_STRING, MFS_ENABLED
         MENUITEM "", 450, MFT_SEPARATOR, MFS_ENABLED
-        MENUITEM "E&şle", IDM_SYNCHRONIZE, MFT_STRING, MFS_ENABLED
-        MENUITEM "&Oturumu Kapat %s...", IDM_LOGOFF, MFT_STRING, MFS_ENABLED
+        MENUITEM "&Eşle", IDM_SYNCHRONIZE, MFT_STRING, MFS_ENABLED
+        MENUITEM "&Oturumu Kapat: %s...", IDM_LOGOFF, MFT_STRING, MFS_ENABLED
         MENUITEM "Ba&ğlantıyı Kes...", IDM_DISCONNECT, MFT_STRING, MFS_ENABLED
         MENUITEM "B&ilgisayarı Ayır", IDM_UNDOCKCOMPUTER, MFT_STRING, MFS_ENABLED
-        MENUITEM "Bi&lgisayarı Kapat...", IDM_SHUTDOWN, MFT_STRING, MFS_ENABLED
+        MENUITEM "&Kapat...", IDM_SHUTDOWN, MFT_STRING, MFS_ENABLED
     END
 END
 
@@ -69,7 +69,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT
 CAPTION "Görev Çubuğu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
-    GROUPBOX "Görev Çubuğunun Görünümü", IDC_STATIC, 6, 6, 240, 104
+    GROUPBOX "Görev Çubuğu Görünümü", IDC_STATIC, 6, 6, 240, 104
     CONTROL "", IDC_TASKBARPROP_TASKBARBITMAP, "Static", SS_BITMAP | SS_SUNKEN, 13, 18, 224, 21
     AUTOCHECKBOX "&Görev Çubuğunu Kilitle", IDC_TASKBARPROP_LOCK, 13, 45, 200, 10
     AUTOCHECKBOX "G&örev Çubuğunu Kendiliğinden Gizle", IDC_TASKBARPROP_HIDE, 13, 58, 200, 10
@@ -83,15 +83,15 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT
 CAPTION "Başlat Seçkesi"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
-    AUTORADIOBUTTON "&Gelişmiş Başlat Seçkesi", IDC_TASKBARPROP_STARTMENU, 7, 7, 105, 10
-    LTEXT "Gelişmiş Başlat Seçkesi; dizinlere, sık kullanılan yazılımlara ve aramaya kolayca ulaşmanıza olanak sağlar.", IDC_STATIC, 20, 17, 150, 24, WS_DISABLED
+    AUTORADIOBUTTON "&Başlat Seçkesi", IDC_TASKBARPROP_STARTMENU, 7, 7, 105, 10
+    LTEXT "Bu seçke türü; size dizinlerinize, sık kullanılan izlencelere ve aramaya kolay erişim verir.", IDC_STATIC, 20, 17, 150, 24, WS_DISABLED
     PUSHBUTTON "&Husûsileştir...", IDC_TASKBARPROP_STARTMENUCUST, 192, 4, 53, 14, WS_DISABLED
-    AUTORADIOBUTTON "&Eski Başlat Seçkesi", IDC_TASKBARPROP_STARTMENUCLASSIC, 7, 47, 105, 10, WS_DISABLED
-    LTEXT "Eski Başlat Seçkesi, eski görünüm ve eski işlevliği sağlar.", -1, 20, 57, 150, 24, WS_DISABLED
+    AUTORADIOBUTTON "&Geleneklik Başlat Seçkesi", IDC_TASKBARPROP_STARTMENUCLASSIC, 7, 47, 105, 10, WS_DISABLED
+    LTEXT "Bu seçke türü, size geleneklik görünümü ve geleneklik işlevliliği sağlar.", -1, 20, 57, 150, 24, WS_DISABLED
     PUSHBUTTON "H&usûsileştir...", IDC_TASKBARPROP_STARTMENUCLASSICCUST, 192, 44, 53, 14, WS_DISABLED
     GROUPBOX "Gizlilik", IDC_STATIC, 7, 100, 238, 42
-    AUTOCHECKBOX "&Son Kullanılan Kütüklerin Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFILES, 14, 114, 224, 10, WS_DISABLED
-    AUTOCHECKBOX "S&on Kullanılan Yazılımların Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFOLDERS, 14, 128, 224, 10, WS_DISABLED
+    AUTOCHECKBOX "&Son Zamanlarda Açılan Kütüklerin Bir Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFILES, 14, 114, 224, 10, WS_DISABLED
+    AUTOCHECKBOX "S&on Zamanlarda Açılan Yazılımların Bir Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFOLDERS, 14, 128, 224, 10, WS_DISABLED
 END
 
 IDD_TASKBARPROP_NOTIFICATION DIALOGEX 0, 0, 252, 218
@@ -101,13 +101,13 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
     CONTROL "", IDC_TASKBARPROP_NOTIFICATIONBITMAP, "Static", SS_BITMAP | SS_SUNKEN,7, 6, 238, 21, WS_DISABLED
     GROUPBOX "Simgeler", IDC_STATIC, 6, 33, 240, 58, WS_DISABLED
-    LTEXT "Yakın zamanda kullanmadığınız simgeleri gizleyerek bildirim alanının şişmesini önleyebilirsiniz.", IDC_STATIC, 13, 48, 223, 16, WS_DISABLED
+    LTEXT "Son zamanlarda tıklamadığınız simgeleri gizleyerek bildirim alanını düzenli tutabilirsiniz.", IDC_STATIC, 13, 48, 223, 16, WS_DISABLED
     AUTOCHECKBOX "E&dilgin Simgeleri Gizle", IDC_TASKBARPROP_HIDEICONS, 13, 70, 125, 10, WS_DISABLED
     PUSHBUTTON "&Husûsileştir...", IDC_TASKBARPROP_ICONCUST, 188, 70, 50, 14, WS_DISABLED
     GROUPBOX "Dizge Simgeleri", IDC_STATIC, 6, 97, 240, 84, WS_DISABLED
-    LTEXT "Sürekli görüntülenecek dizge simgelerini seçiniz:", IDC_STATIC, 13, 112, 223, 16, WS_DISABLED
+    LTEXT "Sürekli göstermek için dizge simgelerini seçiniz:", IDC_STATIC, 13, 112, 223, 16, WS_DISABLED
     AUTOCHECKBOX "&Saat", IDC_TASKBARPROP_CLOCK, 13, 126, 200, 10, WS_DISABLED
-    AUTOCHECKBOX "S&es Ayârı", IDC_TASKBARPROP_VOLUME, 13, 139, 200, 10, WS_DISABLED
+    AUTOCHECKBOX "S&es Düzeyi", IDC_TASKBARPROP_VOLUME, 13, 139, 200, 10, WS_DISABLED
     AUTOCHECKBOX "&Ağ", IDC_TASKBARPROP_NETWORK, 13, 152, 200, 10, WS_DISABLED
     AUTOCHECKBOX "&Güç", IDC_TASKBARPROP_POWER, 13, 164, 200, 10, WS_DISABLED
 END
@@ -117,7 +117,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT
 CAPTION "Araç Çubukları"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
-    LTEXT "Görev çubuğuna hangi araç çubuklarının ekleneceğini seçebilirsiniz:", IDC_STATIC, 7, 7, 223, 12, WS_DISABLED
+    LTEXT "Görev çubuğuna eklemek için araç çubuklarını seçiniz:", IDC_STATIC, 7, 7, 223, 12, WS_DISABLED
     CONTROL "", IDC_TASKBARPROP_DESKBANDLIST, "SysTreeView32", WS_BORDER | WS_TABSTOP | WS_DISABLED, 7, 20, 236, 160, WS_EX_CLIENTEDGE
 END
 
@@ -137,7 +137,7 @@ BEGIN
     IDS_PROPERTIES "&Husûsiyetler"
     IDS_OPEN_ALL_USERS "&Tüm Kullanıcılar'da Aç"
     IDS_EXPLORE_ALL_USERS "T&üm Kullanıcılar'da Araştır"
-    IDS_STARTUP_ERROR "Dizge, gerekli değerlerin, bozuk olduğundan ya da olmadığından Gezgin'i başlatamadı."
+    IDS_STARTUP_ERROR "Dizge, değer defterinin, bozuk ya da olmadığından gezgini başlatamadı."
 END
 
 STRINGTABLE
index e061384..c2027c3 100644 (file)
@@ -8,38 +8,38 @@ BEGIN
     BEGIN
         MENUITEM "&Spustit...", ID_EXECUTE
         MENUITEM SEPARATOR
-        MENUITEM "&Ukonèit", ID_FILE_EXIT
+        MENUITEM "&Ukončit", ID_FILE_EXIT
     END
-    POPUP "&Zobrazení"
+    POPUP "&Zobrazení"
     BEGIN
-        MENUITEM "Panel &nástrojù", ID_VIEW_TOOL_BAR
+        MENUITEM "Panel &nástrojů", ID_VIEW_TOOL_BAR
         MENUITEM "Panel &extra", ID_VIEW_EXTRA_BAR
-        MENUITEM "L&i\9ata diskù", ID_VIEW_DRIVE_BAR
-        MENUITEM "&Boèní panel", ID_VIEW_SIDE_BAR
-        MENUITEM "&Stavový øádek", ID_VIEW_STATUSBAR
+        MENUITEM "L&išta disků", ID_VIEW_DRIVE_BAR
+        MENUITEM "&Boční panel", ID_VIEW_SIDE_BAR
+        MENUITEM "&Stavový řádek", ID_VIEW_STATUSBAR
         MENUITEM SEPARATOR
         MENUITEM "&Aktualizovat\tF5", ID_REFRESH
-        MENUITEM "&Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN
+        MENUITEM "&Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN
         MENUITEM "SDI", ID_VIEW_SDI
     END
     POPUP "&Okno"
     BEGIN
-        MENUITEM "&Nové Okno", ID_WINDOW_NEW
-        MENUITEM "&Kaskádovat\tShift+F5", ID_WINDOW_CASCADE
-        MENUITEM "&Uspoøádat vodorovnì", ID_WINDOW_TILE_HORZ
-        MENUITEM "U&spoøádat svisle\tShift+F4", ID_WINDOW_TILE_VERT
-        MENUITEM "Us&poøádat automaticky", ID_WINDOW_AUTOSORT
-        MENUITEM "Usp&oøádat symboly", ID_WINDOW_ARRANGE
+        MENUITEM "&Nové Okno", ID_WINDOW_NEW
+        MENUITEM "&Kaskádovat\tShift+F5", ID_WINDOW_CASCADE
+        MENUITEM "&Uspořádat vodorovně", ID_WINDOW_TILE_HORZ
+        MENUITEM "U&spořádat svisle\tShift+F4", ID_WINDOW_TILE_VERT
+        MENUITEM "Us&pořádat automaticky", ID_WINDOW_AUTOSORT
+        MENUITEM "Usp&ořádat symboly", ID_WINDOW_ARRANGE
     END
-    POPUP "&Nástroje"
+    POPUP "&Nástroje"
     BEGIN
-        MENUITEM "&Mo\9enosti", ID_TOOLS_OPTIONS
+        MENUITEM "&Možnosti", ID_TOOLS_OPTIONS
     END
-    POPUP "Ná&povìda"
+    POPUP "Ná&pověda"
     BEGIN
-        MENUITEM "&Prùzkumník &FAQ", ID_EXPLORER_FAQ
-        MENUITEM "O P&rùzkumníku", ID_ABOUT_EXPLORER
-        MENUITEM "&O operaèním systému", ID_ABOUT_WINDOWS
+        MENUITEM "&Průzkumník &FAQ", ID_EXPLORER_FAQ
+        MENUITEM "O P&růzkumníku", ID_ABOUT_EXPLORER
+        MENUITEM "&O operačním systému", ID_ABOUT_WINDOWS
     END
 END
 
@@ -47,10 +47,10 @@ IDM_DESKTOPBAR MENU
 BEGIN
     POPUP ""
     BEGIN
-        MENUITEM "&Nastavení", ID_DESKTOPBAR_SETTINGS
-        MENUITEM "&Správce úloh", ID_TASKMGR
+        MENUITEM "&Nastavení", ID_DESKTOPBAR_SETTINGS
+        MENUITEM "&Správce úloh", ID_TASKMGR
         MENUITEM SEPARATOR
-        MENUITEM "&O Prùzkumníku", ID_ABOUT_EXPLORER
+        MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER
     END
 END
 
@@ -58,7 +58,7 @@ IDM_VOLUME MENU
 BEGIN
     POPUP ""
     BEGIN
-        MENUITEM "&Otevøít ovládání hlasitosti", ID_TRAY_VOLUME
+        MENUITEM "&Otevřít ovládání hlasitosti", ID_TRAY_VOLUME
         MENUITEM "&Upravit vlastnosti zvuku", ID_VOLUME_PROPERTIES
     END
 END
@@ -67,12 +67,12 @@ IDM_NOTIFYAREA MENU
 BEGIN
     POPUP ""
     BEGIN
-        MENUITEM "&Zobrazit skryté ikony", ID_SHOW_HIDDEN_ICONS
-        MENUITEM "Z&obrazit ikonu tlaèítka", ID_SHOW_ICON_BUTTON
-        MENUITEM "&Nastavit upozornìní", ID_CONFIG_NOTIFYAREA
-        MENUITEM "N&astavit datum a èas", ID_CONFIG_TIME
+        MENUITEM "&Zobrazit skryté ikony", ID_SHOW_HIDDEN_ICONS
+        MENUITEM "Z&obrazit ikonu tlačítka", ID_SHOW_ICON_BUTTON
+        MENUITEM "&Nastavit upozornění", ID_CONFIG_NOTIFYAREA
+        MENUITEM "N&astavit datum a čas", ID_CONFIG_TIME
         MENUITEM SEPARATOR
-        MENUITEM "&O Prùzkumníku", ID_ABOUT_EXPLORER
+        MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER
     END
 END
 
@@ -82,27 +82,27 @@ BEGIN
     BEGIN
         MENUITEM "&Spustit...", ID_EXECUTE
         MENUITEM SEPARATOR
-        MENUITEM "&Ukonèit", ID_FILE_EXIT
+        MENUITEM "&Ukončit", ID_FILE_EXIT
     END
-    POPUP "&Zobrazení"
+    POPUP "&Zobrazení"
     BEGIN
-        MENUITEM "Panel &nástrojù", ID_VIEW_TOOL_BAR
-        MENUITEM "&Boèní panel", ID_VIEW_SIDE_BAR, GRAYED
-        MENUITEM "&Stavový øádek", ID_VIEW_STATUSBAR
+        MENUITEM "Panel &nástrojů", ID_VIEW_TOOL_BAR
+        MENUITEM "&Boční panel", ID_VIEW_SIDE_BAR, GRAYED
+        MENUITEM "&Stavový řádek", ID_VIEW_STATUSBAR
         MENUITEM SEPARATOR
         MENUITEM "&Aktualizovat\tF5", ID_REFRESH
-        MENUITEM "Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN
+        MENUITEM "Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN
         MENUITEM "&MDI", ID_VIEW_MDI
     END
-    POPUP "&Nástroje"
+    POPUP "&Nástroje"
     BEGIN
-        MENUITEM "&Nastavení", ID_TOOLS_OPTIONS
+        MENUITEM "&Nastavení", ID_TOOLS_OPTIONS
     END
-    POPUP "Ná&povìda"
+    POPUP "Ná&pověda"
     BEGIN
-        MENUITEM "Prùzkumník &FAQ", ID_EXPLORER_FAQ
-        MENUITEM "O &Prùzkumníku", ID_ABOUT_EXPLORER
-        MENUITEM "O &Operaèním systému", ID_ABOUT_WINDOWS
+        MENUITEM "Průzkumník &FAQ", ID_EXPLORER_FAQ
+        MENUITEM "O &Průzkumníku", ID_ABOUT_EXPLORER
+        MENUITEM "O &Operačním systému", ID_ABOUT_WINDOWS
     END
 END
 
@@ -114,18 +114,18 @@ CAPTION "Spustit"
 FONT 8, "MS Shell Dlg"
 BEGIN
     CONTROL "", 101, "Static", SS_SIMPLE | SS_NOPREFIX, 3, 6, 162, 10
-    CONTROL "&Pøíkaz:", -1, "Static", SS_LEFTNOWORDWRAP | WS_GROUP, 3, 18, 60, 10
+    CONTROL "&Příkaz:", -1, "Static", SS_LEFTNOWORDWRAP | WS_GROUP, 3, 18, 60, 10
     EDITTEXT 201, 3, 29, 134, 12, ES_AUTOHSCROLL
     CONTROL "Jako &symbol", 214, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 3, 45, 71, 12
     DEFPUSHBUTTON "&Spustit", 1, 158, 6, 47, 14
     PUSHBUTTON "&Storno", 2, 158, 23, 47, 14
-    PUSHBUTTON "Ná&povìda", 254, 158, 43, 47, 14
+    PUSHBUTTON "Ná&pověda", 254, 158, 43, 47, 14
 END
 
 IDD_SEARCH_PROGRAM DIALOGEX 0, 0, 200, 65
 STYLE DS_SHELLFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
 EXSTYLE WS_EX_APPWINDOW
-CAPTION "Hledat program v nabídce Start"
+CAPTION "Hledat program v nabídce Start"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
     LTEXT "&Filtr:", IDC_STATIC, 7, 9, 18, 8
@@ -140,7 +140,7 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
 CAPTION "Vlastnosti plochy"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Prosím zvolte si zpùsob zarovnání ikon:", IDC_STATIC, 7, 7, 166, 8
+    LTEXT "Prosím zvolte si způsob zarovnání ikon:", IDC_STATIC, 7, 7, 166, 8
     CONTROL "vlevo/n. d.", IDC_ICON_ALIGN_0, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 7, 25, 46, 44
     CONTROL "vlevo/n. p.", IDC_ICON_ALIGN_1, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 57, 25, 46, 44
     CONTROL "vpravo/n. l.", IDC_ICON_ALIGN_2, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 110, 25, 46, 44
@@ -158,17 +158,17 @@ END
 
 IDD_DESKBAR_TASKBAR DIALOGEX 0, 0, 210, 194
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Vlastnosti panelu úloh"
+CAPTION "Vlastnosti panelu úloh"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    CONTROL "&Zobrazit èas", ID_SHOW_CLOCK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 152, 52, 10
-    CONTROL "&Skrýt neaktivní ikony", ID_HIDE_INACTIVE_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 174, 111, 10
-    PUSHBUTTON "&Upozornìní...", ID_CONFIG_NOTIFYAREA, 153, 173, 50, 14
+    CONTROL "&Zobrazit čas", ID_SHOW_CLOCK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 152, 52, 10
+    CONTROL "&Skrýt neaktivní ikony", ID_HIDE_INACTIVE_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 174, 111, 10
+    PUSHBUTTON "&Upozornění...", ID_CONFIG_NOTIFYAREA, 153, 173, 50, 14
 END
 
 IDD_DESKBAR_STARTMENU DIALOGEX 0, 0, 210, 194
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Vlastnosti nabídky Start"
+CAPTION "Vlastnosti nabídky Start"
 FONT 8, "MS Shell Dlg"
 BEGIN
 END
@@ -176,24 +176,24 @@ END
 IDD_NOTIFYAREA DIALOGEX 0, 0, 208, 174
 STYLE DS_SHELLFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
 EXSTYLE WS_EX_APPWINDOW
-CAPTION "Nastavení ikon v oblasti upozoròování"
+CAPTION "Nastavení ikon v oblasti upozorňování"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
     CONTROL "Tree1", IDC_NOTIFY_ICONS, "SysTreeView32", TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 7, 7, 194, 31
     LTEXT "&Text popisku:", IDC_LABEL1, 7, 44, 40, 8
     EDITTEXT IDC_NOTIFY_TOOLTIP, 58, 42, 143, 14, ES_AUTOHSCROLL
-    LTEXT "&Název okna:", IDC_LABEL2, 7, 63, 44, 8
+    LTEXT "&Název okna:", IDC_LABEL2, 7, 63, 44, 8
     EDITTEXT IDC_NOTIFY_TITLE, 58, 60, 143, 14, ES_AUTOHSCROLL
     LTEXT "&Cesta:", IDC_LABEL3, 7, 81, 80, 8
     EDITTEXT IDC_NOTIFY_MODULE, 58, 78, 143, 14, ES_AUTOHSCROLL
-    GROUPBOX "&Zobrazení", IDC_LABEL4, 7, 96, 157, 28
+    GROUPBOX "&Zobrazení", IDC_LABEL4, 7, 96, 157, 28
     CONTROL "z&obrazit", IDC_NOTIFY_SHOW, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 15, 108, 45, 10
-    CONTROL "&skrýt", IDC_NOTIFY_HIDE, "Button", BS_AUTORADIOBUTTON, 66, 108, 29, 10
+    CONTROL "&skrýt", IDC_NOTIFY_HIDE, "Button", BS_AUTORADIOBUTTON, 66, 108, 29, 10
     CONTROL "&automaticky", IDC_NOTIFY_AUTOHIDE, "Button", BS_AUTORADIOBUTTON, 104, 108, 55, 10
     ICON "", IDC_PICTURE, 173, 101, 21, 20
-    LTEXT "&Poslední zmìna:", IDC_LABEL6, 7, 132, 60, 8
+    LTEXT "&Poslední změna:", IDC_LABEL6, 7, 132, 60, 8
     EDITTEXT IDC_LAST_CHANGE, 59, 129, 105, 14, ES_AUTOHSCROLL | ES_READONLY
-    CONTROL "zob&razit skryté", ID_SHOW_HIDDEN_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 158, 57, 10
+    CONTROL "zob&razit skryté", ID_SHOW_HIDDEN_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 158, 57, 10
     DEFPUSHBUTTON "&OK", IDOK, 91, 153, 50, 14, WS_GROUP
     PUSHBUTTON "&Storno", IDCANCEL, 151, 153, 50, 14
 END
@@ -201,26 +201,26 @@ END
 IDD_MDI_SDI DIALOGEX 0, 0, 194, 157
 STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_APPWINDOW
-CAPTION "Volba MDI / SDI módu"
+CAPTION "Volba MDI / SDI módu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x1
 BEGIN
-    LTEXT "Prosím zvolte si Vámi upøednostòovaný zpùsob zobrazení oken Prùzkumníka:", IDC_STATIC, 7, 7, 160, 8
-    CONTROL "&MDI (Mnoho dokumentový interface)", IDC_MDI, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 7, 31, 125, 10
-    CONTROL "&SDI (Jedno dokumentový interface)", IDC_SDI, "Button", BS_AUTORADIOBUTTON, 7, 62, 125, 10
+    LTEXT "Prosím zvolte si Vámi upřednostňovaný způsob zobrazení oken Průzkumníka:", IDC_STATIC, 7, 7, 160, 8
+    CONTROL "&MDI (Mnoho dokumentový interface)", IDC_MDI, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 7, 31, 125, 10
+    CONTROL "&SDI (Jedno dokumentový interface)", IDC_SDI, "Button", BS_AUTORADIOBUTTON, 7, 62, 125, 10
     CONTROL 170, IDC_STATIC, "Static", SS_BITMAP, 145, 23, 15, 13
     CONTROL 171, IDC_STATIC, "Static", SS_BITMAP, 145, 57, 15, 13
-    CONTROL "&Otevírat slo\9eky v novém oknì", IDC_SEPARATE_SUBFOLDERS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 90, 135, 10
-    LTEXT "Toto nastavení bude pou\9eito jako výchozí pro v\9aechna okna Prùzkumníka.", IDC_STATIC, 7, 111, 174, 22
+    CONTROL "&Otevírat složky v novém okně", IDC_SEPARATE_SUBFOLDERS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 90, 135, 10
+    LTEXT "Toto nastavení bude použito jako výchozí pro všechna okna Průzkumníka.", IDC_STATIC, 7, 111, 174, 22
     DEFPUSHBUTTON "&OK", IDOK, 29, 136, 50, 14, WS_GROUP
     PUSHBUTTON "&Storno", IDCANCEL, 106, 136, 50, 14
 END
 
 IDD_ABOUT_EXPLORER DIALOGEX 0, 0, 199, 106
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "O ReactOS Prùzkumníku"
+CAPTION "O ReactOS Průzkumníku"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "ReactOS Prùzkumník", IDC_ROS_EXPLORER, 91, 13, 104, 11
+    LTEXT "ReactOS Průzkumník", IDC_ROS_EXPLORER, 91, 13, 104, 11
     LTEXT "V 0.9", IDC_VERSION_TXT, 91, 27, 104, 8
     LTEXT "(c) 2003-2005 Martin Fuchs", IDC_STATIC, 91, 42, 104, 8
     LTEXT "", IDC_WIN_VERSION, 91, 58, 98, 22
@@ -232,61 +232,61 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_TITLE "ReactOS Prùzkumník"
+    IDS_TITLE "ReactOS Průzkumník"
     IDS_START "Start"
-    IDS_LOGOFF "Odhlásit se..."
+    IDS_LOGOFF "Odhlásit se..."
     IDS_SHUTDOWN "Vypnout..."
     IDS_RESTART "Restartovat..."
     IDS_LAUNCH "Spustit..."
-    IDS_START_HELP "Nápovìda"
+    IDS_START_HELP "Nápověda"
     IDS_SEARCH_FILES "Hledat"
     IDS_DOCUMENTS "Dokumenty"
-    IDS_FAVORITES "Oblíbené"
+    IDS_FAVORITES "Oblíbené"
     IDS_PROGRAMS "Programy"
-    IDS_SETTINGS "Nastavení"
+    IDS_SETTINGS "Nastavení"
     IDS_EXPLORE "Prozkoumat"
-    IDS_EMPTY "(Prázdné)"
-    IDS_RECENT "Nedávné dokumenty"
-    IDS_ADMIN "Systémové nástroje"
+    IDS_EMPTY "(Prázdné)"
+    IDS_RECENT "Nedávné dokumenty"
+    IDS_ADMIN "Systémové nástroje"
 END
 
 STRINGTABLE
 BEGIN
-    IDS_STARTMENU "Nabídka Start"
-    IDS_MINIMIZE_ALL "minimalizovat v\9aechna okna"
+    IDS_STARTMENU "Nabídka Start"
+    IDS_MINIMIZE_ALL "minimalizovat všechna okna"
     IDS_DESKTOP_NUM "Plocha %d"
     IDS_VOLUME "Hlasitost"
-    IDS_ITEMS_CUR "souèasné polo\9eky"
-    IDS_ITEMS_CONFIGURED "nastavení"
-    IDS_ITEMS_VISIBLE "viditelné"
-    IDS_ITEMS_HIDDEN "skryté"
+    IDS_ITEMS_CUR "současné položky"
+    IDS_ITEMS_CONFIGURED "nastavení"
+    IDS_ITEMS_VISIBLE "viditelné"
+    IDS_ITEMS_HIDDEN "skryté"
     IDS_NOTIFY_SHOW "zobrazit"
-    IDS_NOTIFY_HIDE "skrýt"
-    IDS_NOTIFY_AUTOHIDE "skrývat automaticky"
-    IDS_SHOW_HIDDEN_ICONS "Zobrazit skryté ikony"
-    IDS_HIDE_ICONS "Skrýt ikony"
-    IDS_TERMINATE "Ukonèit ReactOS Prùzkumníka"
+    IDS_NOTIFY_HIDE "skrýt"
+    IDS_NOTIFY_AUTOHIDE "skrývat automaticky"
+    IDS_SHOW_HIDDEN_ICONS "Zobrazit skryté ikony"
+    IDS_HIDE_ICONS "Skrýt ikony"
+    IDS_TERMINATE "Ukončit ReactOS Průzkumníka"
 END
 
 STRINGTABLE
 BEGIN
-    IDS_NETWORK "Sí\9d"
-    IDS_CONNECTIONS "Sí\9dové spojení"
+    IDS_NETWORK "Síť"
+    IDS_CONNECTIONS "Síťové spojení"
     IDS_DRIVES "Disky"
-    IDS_SEARCH_COMPUTER "Hledat poèítaè"
-    IDS_SETTINGS_MENU "Nastavení"
-    IDS_CONTROL_PANEL "Ovládací panel"
-    IDS_PRINTERS "Tiskárny"
-    IDS_BROWSE "Prohlí\9eet soubory"
+    IDS_SEARCH_COMPUTER "Hledat počítač"
+    IDS_SETTINGS_MENU "Nastavení"
+    IDS_CONTROL_PANEL "Ovládací panel"
+    IDS_PRINTERS "Tiskárny"
+    IDS_BROWSE "Prohlížet soubory"
     IDS_SEARCH_PRG "Hledat programy"
-    IDS_ALL_USERS "V\9aichni u\9eivatelé\\"
+    IDS_ALL_USERS "Všichni uživatelé\\"
     IDS_SEARCH "Hledat"
-    IDS_ABOUT_EXPLORER "&O Prùzkumníku"
-    IDS_LAUNCH_MANY_PROGRAMS "Bylo vybráno více programù.\nPøejete si je spustit v\9aechny?"
-    IDS_DESKTOPBAR_SETTINGS "Nastavení plochy"
+    IDS_ABOUT_EXPLORER "&O Průzkumníku"
+    IDS_LAUNCH_MANY_PROGRAMS "Bylo vybráno více programů.\nPřejete si je spustit všechny?"
+    IDS_DESKTOPBAR_SETTINGS "Nastavení plochy"
     IDS_DESKTOP "Plocha"
-    IDS_TASKBAR "Panel úloh"
-    IDS_NAMECOLUMN "Název"
+    IDS_TASKBAR "Panel úloh"
+    IDS_NAMECOLUMN "Název"
     IDS_PATHCOLUMN "Cesta"
     IDS_MENUCOLUMN "Menu path"
 END
index 53d232b..13882b1 100644 (file)
@@ -27,19 +27,19 @@ IDB_SDI BITMAP "res/sdi.bmp"
 
 /* Accelerators */
 
-IDA_EXPLORER ACCELERATORS    
+IDA_EXPLORER ACCELERATORS
 BEGIN
     "S", ID_VIEW_FULLSCREEN, VIRTKEY, SHIFT, CONTROL, NOINVERT
     VK_F5, ID_REFRESH, VIRTKEY, NOINVERT
     "X", ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT
 END
 
-IDA_SEARCH_PROGRAM ACCELERATORS    
+IDA_SEARCH_PROGRAM ACCELERATORS
 BEGIN
     VK_F5, ID_REFRESH, VIRTKEY, NOINVERT
 END
 
-IDA_TRAYNOTIFY ACCELERATORS    
+IDA_TRAYNOTIFY ACCELERATORS
 BEGIN
     VK_F5, ID_REFRESH, VIRTKEY, NOINVERT
 END
@@ -112,9 +112,6 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "explorer.exe.manifest"
 #ifdef LANGUAGE_BG_BG
     #include "explorer-bg.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "explorer-cz.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "explorer-de.rc"
 #endif
@@ -164,6 +161,9 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "explorer.exe.manifest"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "explorer-cz.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "explorer-he.rc"
 #endif
index 65b747e..e33c668 100644 (file)
@@ -3,6 +3,6 @@
 LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
 STRINGTABLE
 BEGIN
-    IDS_DllNotLoaded """%s"" kitaplığı yüklenemedi."
-    IDS_MissingEntry "%s giriş noktası %s içinde bulunamadı."
+    IDS_DllNotLoaded "LoadLibrary, ""%s"" kitaplığını yüklemede başarısız oldu."
+    IDS_MissingEntry "%s içinde %s giriş noktası eksik."
 END
index 3a4b4de..19f7703 100644 (file)
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
+#ifdef LANGUAGE_SQ_AL
+    #include "lang/sq-AL.rc"
+#endif
 #ifdef LANGUAGE_TH_TH
     #include "lang/th-TH.rc"
 #endif
 #ifdef LANGUAGE_TR_TR
     #include "lang/tr-TR.rc"
 #endif
-#ifdef LANGUAGE_SQ_AL
-    #include "lang/sq-AL.rc"
-#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index 1e629c8..76de1ea 100644 (file)
@@ -7,7 +7,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS
 CAPTION "ReactOS Kur"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "ReactOS, şimdi aşağıdaki ayarlamaları yapıyor:", -1, 38, 8, 196, 18
+    LTEXT "ReactOS şimdi aşağıdaki öğeleri kuruyor:", -1, 38, 8, 196, 18
     LISTBOX IDC_COMP_LIST, 36, 32, 197, 131, LBS_OWNERDRAWVARIABLE | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
     ICON IDI_ICON, -1, 5, 6, 21, 20
 END
index 5ed0a8f..3ca6be6 100644 (file)
@@ -48,12 +48,12 @@ IDI_ICON ICON "res/icon.ico"
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
-#ifdef LANGUAGE_TR_TR
-    #include "lang/tr-TR.rc"
-#endif
 #ifdef LANGUAGE_SQ_AL
     #include "lang/sq-AL.rc"
 #endif
+#ifdef LANGUAGE_TR_TR
+    #include "lang/tr-TR.rc"
+#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index c7d2d06..870c00f 100644 (file)
@@ -4,5 +4,5 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
 
 STRINGTABLE
 BEGIN
-    STRING_USERINIT_FAIL "Userinit, kabuğu başlatamadı!\n"
+    STRING_USERINIT_FAIL "Userinit, kabuğu başlatmada başarısız oldu!\n"
 END
index 20f5fa5..5b573e5 100644 (file)
@@ -70,6 +70,9 @@
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
+#ifdef LANGUAGE_SQ_AL
+    #include "lang/sq-AL.rc"
+#endif
 #ifdef LANGUAGE_SV_SE
     #include "lang/sv-SE.rc"
 #endif
@@ -79,9 +82,6 @@
 #ifdef LANGUAGE_TR_TR
     #include "lang/tr-TR.rc"
 #endif
-#ifdef LANGUAGE_SQ_AL
-    #include "lang/sq-AL.rc"
-#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index 8ea502e..b919dcb 100644 (file)
@@ -7,7 +7,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPT
 CAPTION "Bilgisayarı Kapat"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Şimdi bilgisayarınızı kapatabilirsiniz.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8
+    LTEXT "Şimdi bilgisayarınızı kapatmak güvenlidir.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8
     ICON IDI_WINLOGON, IDC_SHTDOWNICON, 6, 7, 18, 20
     DEFPUSHBUTTON "&Yeniden Başlat", IDC_BTNSHTDOWNCOMPUTER, 62, 32, 40, 14
 END
@@ -17,8 +17,8 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPT
 CAPTION "Kullanıcı Arayüzü Yanlışlığı"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Oturum Açma Kullanıcı Arayüzü DLL'si (%s) yüklenemedi.", IDC_GINALOADFAILED, 39, 16, 156, 24
-    LTEXT "DLL'nin yenilenmesi için dizge yöneticinize başvurunuz.", IDC_GINALOADFAILEDCONTACT, 39, 53, 151, 25
+    LTEXT "Oturum Açma Kullanıcı Arayüzü %s DLL'si yüklemede başarısız oldu.", IDC_GINALOADFAILED, 39, 16, 156, 24
+    LTEXT "DLL'yi yenisiyle değiştirmek veyâ özgün DLL'yi onarmak için dizge yöneticinize başvurunuz.", IDC_GINALOADFAILEDCONTACT, 39, 53, 151, 25
     DEFPUSHBUTTON "&Yeniden Başlat", 1, 80, 91, 68, 14
 END
 
@@ -26,21 +26,21 @@ STRINGTABLE
 BEGIN
     IDS_PREPARENETWORKCONNECTIONS "Ağ Bağlantıları Anıklanıyor..."
     IDS_APPLYINGCOMPUTERSETTINGS "Bilgisayar Ayarları Uygulanıyor..."
-    IDS_RUNNINGSTARTUPSCRIPTS "Bilgisayarı Açma Betikleri Çalıştırılıyor..."
-    IDS_RUNNINGSHUTDOWNSCRIPTS "Bilgisayarı Kapama Betikleri Çalıştırılıyor..."
-    IDS_APPLYINGYOURPERSONALSETTINGS "Kullanıcı Ayarlarınız Uygulanıyor..."
+    IDS_RUNNINGSTARTUPSCRIPTS "Açılış Betikleri Çalıştırılıyor..."
+    IDS_RUNNINGSHUTDOWNSCRIPTS "Kapanış Betikleri Çalıştırılıyor..."
+    IDS_APPLYINGYOURPERSONALSETTINGS "Şahsî Ayarlarınız Uygulanıyor..."
     IDS_RUNNINGLOGOFFSCRIPTS "Oturum Kapama Betikleri Çalıştırılıyor..."
     IDS_RUNNINGLOGONSCRIPTS "Oturum Açma Betikleri Çalıştırılıyor..."
-    IDS_LOADINGYOURPERSONALSETTINGS "Kullanıcı Ayarlarınız Yükleniyor..."
+    IDS_LOADINGYOURPERSONALSETTINGS "Şahsî Ayarlarınız Yükleniyor..."
     IDS_CLOSINGNETWORKCONNECTIONS "Ağ Bağlantıları Kapatılıyor..."
     IDS_REACTOSISSHUTTINGDOWN "ReactOS Kapatılıyor..."
-    IDS_PREPARETOSTANDBY "Uyku Kipine Geçiliyor..."
-    IDS_PREPARETOHIBERNATE "Anıkta Beklemeye Geçiliyor..."
+    IDS_PREPARETOSTANDBY "Beklemeye Anıklanıyor..."
+    IDS_PREPARETOHIBERNATE "Anıkta Beklemeye Anıklanıyor..."
     IDS_SAVEYOURSETTINGS "Ayarlarınız Kaydediliyor..."
     IDS_REACTOSISSTARTINGUP "ReactOS Başlatılıyor..."
 END
 
 STRINGTABLE
 BEGIN
-    IDS_FAILEDACTIVATEUSERSHELL "Winlogon, kullanıcı kabuğunu etkinleştiremedi."
+    IDS_FAILEDACTIVATEUSERSHELL "Winlogon, kullanıcı kabuğunu etkinleştirmede başarısız oldu."
 END
index 1a68945..d3c4747 100644 (file)
@@ -74,18 +74,18 @@ IDI_WINLOGON ICON "resources/winlogon.ico"
 #ifdef LANGUAGE_RU_RU
     #include "lang/ru-RU.rc"
 #endif
-#ifdef LANGUAGE_SV_SE
-    #include "lang/sv-SE.rc"
-#endif
 #ifdef LANGUAGE_SK_SK
     #include "lang/sk-SK.rc"
 #endif
-#ifdef LANGUAGE_TR_TR
-    #include "lang/tr-TR.rc"
-#endif
 #ifdef LANGUAGE_SQ_AL
     #include "lang/sq-AL.rc"
 #endif
+#ifdef LANGUAGE_SV_SE
+    #include "lang/sv-SE.rc"
+#endif
+#ifdef LANGUAGE_TR_TR
+    #include "lang/tr-TR.rc"
+#endif
 #ifdef LANGUAGE_UK_UA
     #include "lang/uk-UA.rc"
 #endif
index 18121ba..7d3cedd 100644 (file)
@@ -56,7 +56,8 @@ add_compile_flags("/wd4290")
 # - C4163: 'identifier': not available as an intrinsic function
 # - C4229: modifiers on data are ignored
 # - C4700: uninitialized variable usage
-add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700")
+# - C4603: macro is not defined or definition is different after precompiled header use
+add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700 /we4603")
 
 # Enable warnings above the default level, but don't treat them as errors:
 # - C4115: named type definition in parentheses
index 614340b..3f9530a 100644 (file)
@@ -19,9 +19,6 @@ IDI_CPLACCESS ICON "resources/applet.ico"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
@@ -62,6 +59,9 @@ IDI_CPLACCESS ICON "resources/applet.ico"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
index a7c5147..0b29558 100644 (file)
@@ -2,25 +2,25 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 IDD_PROPPAGEKEYBOARD DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Klávesnice"
+CAPTION "Klávesnice"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    GROUPBOX "Jedním prstem", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
-    LTEXT "Tuto funkci pou\9eijte, pokud chcete pou\9eívat Shift, Ctrl nebo Alt stisknutím pouze jedné klávesy najednou.",
+    GROUPBOX "Jedním prstem", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
+    LTEXT "Tuto funkci použijte, pokud chcete používat Shift, Ctrl nebo Alt stisknutím pouze jedné klávesy najednou.",
           -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "Pou\9eívat funkci &Jedním prstem", IDC_STICKY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "&Nastavení", IDC_STICKY_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
-    GROUPBOX "Filtrování kláves", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2
-    LTEXT "Pou\9eijte funkci Filtrování kláves, pokud chcete, aby ReactOS ignoroval náhodná nebo opakovaná stisknutí kláves.",
+    AUTOCHECKBOX "Používat funkci &Jedním prstem", IDC_STICKY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "&Nastavení", IDC_STICKY_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
+    GROUPBOX "Filtrování kláves", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2
+    LTEXT "Použijte funkci Filtrování kláves, pokud chcete, aby ReactOS ignoroval náhodná nebo opakovaná stisknutí kláves.",
           -1, PROPSHEETPADDING(2), LABELLINE(10) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "Pou\9eívat funkci &Filtrování kláves", IDC_FILTER_BOX, PROPSHEETPADDING(2), LABELLINE(13) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "N&astavení", IDC_FILTER_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(13) + 2, PROPSHEETPADDING(15), 14
-    GROUPBOX "Ozvuèení kláves", -1, PROPSHEETPADDING(1), LABELLINE(16) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
-    LTEXT "Pou\9eijte funkci Ozvuèení kláves, chcete-li být upozornìni na stisk kláves Caps Lock, Num Lock a Scroll Lock zvukovým signálem.",
+    AUTOCHECKBOX "Používat funkci &Filtrování kláves", IDC_FILTER_BOX, PROPSHEETPADDING(2), LABELLINE(13) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "N&astavení", IDC_FILTER_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(13) + 2, PROPSHEETPADDING(15), 14
+    GROUPBOX "Ozvučení kláves", -1, PROPSHEETPADDING(1), LABELLINE(16) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
+    LTEXT "Použijte funkci Ozvučení kláves, chcete-li být upozorněni na stisk kláves Caps Lock, Num Lock a Scroll Lock zvukovým signálem.",
           -1, PROPSHEETPADDING(2), LABELLINE(18) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2) + 6
-    AUTOCHECKBOX "Pou\9eívat funkci O&zvuèení kláves", IDC_TOGGLE_BOX, PROPSHEETPADDING(2), LABELLINE(20) + 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "Na&stavení", IDC_TOGGLE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(20) + 4, PROPSHEETPADDING(15), 14
-    AUTOCHECKBOX "&V programech zobrazovat dodateènou nápovìdu ke klávesám.", IDC_KEYBOARD_EXTRA,
+    AUTOCHECKBOX "Používat funkci O&zvučení kláves", IDC_TOGGLE_BOX, PROPSHEETPADDING(2), LABELLINE(20) + 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "Na&stavení", IDC_TOGGLE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(20) + 4, PROPSHEETPADDING(15), 14
+    AUTOCHECKBOX "&V programech zobrazovat dodatečnou nápovědu ke klávesám.", IDC_KEYBOARD_EXTRA,
                  PROPSHEETPADDING(1), LABELLINE(23) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), 14
 END
 
@@ -30,28 +30,28 @@ CAPTION "Zvuk"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     GROUPBOX "Funkce Popis zvuku", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(10) + PROPSHEETPADDING(1)
-    LTEXT "Pou\9eijte funkci Zobrazení zvuku, pokud chcete aby ReactOS vizuálnì upozoròoval na ka\9edý zvuk vydaný systémem.",
+    LTEXT "Použijte funkci Zobrazení zvuku, pokud chcete aby ReactOS vizuálně upozorňoval na každý zvuk vydaný systémem.",
           -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "&Pou\9eívat funkci Popis zvuku", IDC_SENTRY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETPADDING(20), 14
+    AUTOCHECKBOX "&Používat funkci Popis zvuku", IDC_SENTRY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETPADDING(20), 14
     LTEXT "Use the following warning:", IDC_SENTRY_TEXT, PROPSHEETPADDING(2), LABELLINE(8) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(1)
     COMBOBOX IDC_SENTRY_COMBO, PROPSHEETPADDING(2), LABELLINE(9), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(6),
              CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP
-    GROUPBOX "Funkce Zobrazení zvuku", -1, PROPSHEETPADDING(1), LABELLINE(12) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2
-    LTEXT "Pou\9eijte Zobrazení zvuku, aby programy zobrazovaly textový popis zároveò se zvukem.",
+    GROUPBOX "Funkce Zobrazení zvuku", -1, PROPSHEETPADDING(1), LABELLINE(12) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2
+    LTEXT "Použijte Zobrazení zvuku, aby programy zobrazovaly textový popis zároveň se zvukem.",
           -1, PROPSHEETPADDING(2), LABELLINE(14) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "Pou\9eívat funkci &Zobrazení zvuku", IDC_SSHOW_BOX, PROPSHEETPADDING(2), LABELLINE(16) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
+    AUTOCHECKBOX "Používat funkci &Zobrazení zvuku", IDC_SSHOW_BOX, PROPSHEETPADDING(2), LABELLINE(16) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
 END
 
 IDD_PROPPAGEDISPLAY DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Zobrazení"
+CAPTION "Zobrazení"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    GROUPBOX "Funkce Vysoký kontrast", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
-    LTEXT "Vyberte tuto mo\9enost pokud chcete, aby Reactos pou\9eíval barvy a písma urèené pro snadnou èitelnost.",
+    GROUPBOX "Funkce Vysoký kontrast", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
+    LTEXT "Vyberte tuto možnost pokud chcete, aby Reactos používal barvy a písma určené pro snadnou čitelnost.",
           -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "&Pou\9eít funkci Vysoký kontrast", IDC_CONTRAST_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "&Nastavení", IDC_CONTRAST_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
+    AUTOCHECKBOX "&Použít funkci Vysoký kontrast", IDC_CONTRAST_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "&Nastavení", IDC_CONTRAST_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
     GROUPBOX "Cursor options", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(13)
     LTEXT "Use the track bars to modify the blinking speed of the cursor and its width.",
           -1, PROPSHEETPADDING(2), LABELLINE(9) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2)
@@ -70,40 +70,40 @@ END
 
 IDD_PROPPAGEMOUSE DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "My\9a"
+CAPTION "Myš"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    GROUPBOX "Funkce My\9a klávesnicí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
-    LTEXT "Vyberte tuto mo\9enost, pokud chcete ovládat my\9a pomocí \9aipek na numerické klávesnici.",
+    GROUPBOX "Funkce Myš klávesnicí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
+    LTEXT "Vyberte tuto možnost, pokud chcete ovládat myš pomocí šipek na numerické klávesnici.",
           -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3)
-    AUTOCHECKBOX "Pou\9eít funkci &My\9a klávesnicí", IDC_MOUSE_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "&Nastavení", IDC_MOUSE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
+    AUTOCHECKBOX "Použít funkci &Myš klávesnicí", IDC_MOUSE_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "&Nastavení", IDC_MOUSE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14
 END
 
 IDD_PROPPAGEGENERAL DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Obecné"
+CAPTION "Obecné"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    GROUPBOX "Automatické vypnutí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
-    AUTOCHECKBOX "Vypnout &funkce usnadnìní po neèinnosti del\9aí ne\9e:",
+    GROUPBOX "Automatické vypnutí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
+    AUTOCHECKBOX "Vypnout &funkce usnadnění po nečinnosti delší než:",
                  IDC_RESET_BOX, PROPSHEETPADDING(2), LABELLINE(2) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
     COMBOBOX IDC_RESET_COMBO, PROPSHEETPADDING(4), LABELLINE(4), PROPSHEETPADDING(10), LABELLINE(5),
              CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP
-    GROUPBOX "Upozornìní", -1, PROPSHEETPADDING(1), LABELLINE(7) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
-    AUTOCHECKBOX "Pøi zapnutí funkce zobrazit upozornìní.", IDC_NOTIFICATION_MESSAGE,
+    GROUPBOX "Upozornění", -1, PROPSHEETPADDING(1), LABELLINE(7) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
+    AUTOCHECKBOX "Při zapnutí funkce zobrazit upozornění.", IDC_NOTIFICATION_MESSAGE,
                  PROPSHEETPADDING(2), LABELLINE(8) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
-    AUTOCHECKBOX "Upozornit na zapnutí nebo vypnutí funkce usnadnìní zvukem.", IDC_NOTIFICATION_SOUND,
+    AUTOCHECKBOX "Upozornit na zapnutí nebo vypnutí funkce usnadnění zvukem.", IDC_NOTIFICATION_SOUND,
                  PROPSHEETPADDING(2), LABELLINE(10) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
     GROUPBOX "Funkce SerialKey", -1, PROPSHEETPADDING(1), LABELLINE(13) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
-    LTEXT "Funkce SerialKey Vám umo\9ení alternativní pøístup k funkcím my\9ai a klávesnice.",
+    LTEXT "Funkce SerialKey Vám umožní alternativní přístup k funkcím myši a klávesnice.",
           -1, PROPSHEETPADDING(2), LABELLINE(14) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2)
-    AUTOCHECKBOX "Pou\9eít funkci &SerialKey", IDC_SERIAL_BOX, PROPSHEETPADDING(2), LABELLINE(16) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
-    PUSHBUTTON "Na&stavení", IDC_SERIAL_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(16) - 4, PROPSHEETPADDING(15), 14
-    GROUPBOX "Mo\9enosti správy", -1, PROPSHEETPADDING(1), LABELLINE(19) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
-    AUTOCHECKBOX "Pou\9eít &nastavení pøi pøihlá\9aení.", IDC_ADMIN_LOGON_BOX,
+    AUTOCHECKBOX "Použít funkci &SerialKey", IDC_SERIAL_BOX, PROPSHEETPADDING(2), LABELLINE(16) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14
+    PUSHBUTTON "Na&stavení", IDC_SERIAL_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(16) - 4, PROPSHEETPADDING(15), 14
+    GROUPBOX "Možnosti správy", -1, PROPSHEETPADDING(1), LABELLINE(19) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
+    AUTOCHECKBOX "Použít &nastavení při přihlášení.", IDC_ADMIN_LOGON_BOX,
                  PROPSHEETPADDING(2), LABELLINE(20) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
-    AUTOCHECKBOX "Po&u\9eít nastavení jako výchozí pro nové u\9eivatele.", IDC_ADMIN_USERS_BOX,
+    AUTOCHECKBOX "Po&užít nastavení jako výchozí pro nové uživatele.", IDC_ADMIN_USERS_BOX,
                  PROPSHEETPADDING(2), LABELLINE(22) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14
 END
 
@@ -280,8 +280,8 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLSYSTEMNAME "Mo\9enosti usnadnìní"
-    IDS_CPLSYSTEMDESCRIPTION "Upraví mo\9enosti usnadnìní pro tento poèítaè."
+    IDS_CPLSYSTEMNAME "Možnosti usnadnění"
+    IDS_CPLSYSTEMDESCRIPTION "Upraví možnosti usnadnění pro tento počítač."
     IDS_SENTRY_NONE "[None]"
     IDS_SENTRY_TITLE "Flash the titlebar"
     IDS_SENTRY_WINDOW "Flash the active window"
index 48d3922..ad82b37 100644 (file)
@@ -25,9 +25,6 @@ IDB_HEADER BITMAP "resources/header.bmp"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
@@ -80,6 +77,9 @@ IDB_HEADER BITMAP "resources/header.bmp"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
index b2680d1..c0b30f2 100644 (file)
@@ -1,27 +1,27 @@
 /* FILE:       dll/cpl/hdwwiz/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2009-02-03 
+ * UPDATED:    2014-04-25 
  */
 
 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 IDD_STARTPAGE DIALOG 0, 0, 317, 186
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Vítejte v Prùvodci pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
-    LTEXT "Tento prùvodce vám pomù\9ee:", -1, 114, 40, 182, 8
-    LTEXT "1) Nainstalovat software pro podporu hardwaru pøidaného do poèítaèe.", -1, 121, 56, 184, 16
-    LTEXT "2) Vyøe\9ait problémy, které mù\9eete s va\9aím hardwarem mít.", -1, 121, 78, 185, 16
+    LTEXT "Vítejte v Průvodci přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
+    LTEXT "Tento průvodce vám pomůže:", -1, 114, 40, 182, 8
+    LTEXT "1) Nainstalovat software pro podporu hardwaru přidaného do počítače.", -1, 121, 56, 184, 16
+    LTEXT "2) Vyřešit problémy, které můžete s vaším hardwarem mít.", -1, 121, 78, 185, 16
     ICON IDI_WARNINGICON, IDC_WARNINGICON, 124, 109, 20, 20
-    LTEXT "Pokud bylo k hardwaru pøibaleno instalaèní CD, doporuèuje se ukonèit tohoto prùvodce klepnutím na tlaèítko Storno a pou\9eít k instalaci hardwaru toto CD.", 503, 150, 106, 155, 50
-    LTEXT "Pokraèujte klepnutím na tlaèítko Dal\9aí.", -1, 114, 166, 193, 8
+    LTEXT "Pokud bylo k hardwaru přibaleno instalační CD, doporučuje se ukončit tohoto průvodce klepnutím na tlačítko Storno a použít k instalaci hardwaru toto CD.", 503, 150, 106, 155, 50
+    LTEXT "Pokračujte klepnutím na tlačítko Další.", -1, 114, 166, 193, 8
 END
 
 IDD_SEARCHPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
     LTEXT "", IDC_STATUSTEXT, 21, 8, 275, 32
@@ -30,63 +30,63 @@ END
 
 IDD_ISCONNECTEDPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Byl ji\9e tento hardware pøipojen k tomuto poèítaèi?", -1, 20, 11, 275, 8
-    AUTORADIOBUTTON "&Ano, ji\9e byl pøipojen", IDC_CONNECTED, 29, 23, 266, 8, WS_GROUP
-    AUTORADIOBUTTON "&Ne, je\9atì nebyl pøidán", IDC_NOTCONNECTED, 29, 35, 266, 8
+    LTEXT "Byl již tento hardware připojen k tomuto počítači?", -1, 20, 11, 275, 8
+    AUTORADIOBUTTON "&Ano, již byl připojen", IDC_CONNECTED, 29, 23, 266, 8, WS_GROUP
+    AUTORADIOBUTTON "&Ne, ještě nebyl přidán", IDC_NOTCONNECTED, 29, 35, 266, 8
 END
 
 IDD_PROBELISTPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Vyberte nainstalované zaøízení ze seznamu ní\9ee, poté lze klepnutím na tlaèítko Dal\9aí zkontrolovat jeho vlastnosti nebo zjistit øe\9aení mo\9ených problémù.", -1, 21, 8, 275, 22
-    LTEXT "Klepnutím na ""Pøidat nové zaøízení."" pøidáte hardware, který se v tomto seznamu nenachází.", -1, 21, 32, 275, 24
-    LTEXT "Nai&nstalovaný hardware:", -1, 21, 62, 140, 8
+    LTEXT "Vyberte nainstalované zařízení ze seznamu níže, poté lze klepnutím na tlačítko Další zkontrolovat jeho vlastnosti nebo zjistit řešení možných problémů.", -1, 21, 8, 275, 22
+    LTEXT "Klepnutím na ""Přidat nové zařízení."" přidáte hardware, který se v tomto seznamu nenachází.", -1, 21, 32, 275, 24
+    LTEXT "Nai&nstalovaný hardware:", -1, 21, 62, 140, 8
     CONTROL "", IDC_PROBELIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 72, 275, 66
 END
 
 IDD_SELECTWAYPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Prùvodce mù\9ee vyhledat dal\9aí hardware a automaticky ho nainstalovat, nebo jej mù\9eete vybrat ze seznamu, pokud víte o který model se jedná.", -1, 21, 8, 280, 24
-    LTEXT "Co má prùvodce udìlat?", -1, 23, 40, 275, 8
-    AUTORADIOBUTTON "&Vyhledat a automaticky nainstalovat hardware (doporuèeno)", IDC_AUTOINSTALL, 30, 55, 266, 8, WS_GROUP | NOT WS_TABSTOP
-    AUTORADIOBUTTON "Nainstalovat hardware, který si &ruènì zvolím ze seznamu (pokroèilé)", IDC_MANUALLYINST, 30, 70, 266, 8, NOT WS_TABSTOP
+    LTEXT "Průvodce může vyhledat další hardware a automaticky ho nainstalovat, nebo jej můžete vybrat ze seznamu, pokud víte o který model se jedná.", -1, 21, 8, 280, 24
+    LTEXT "Co má průvodce udělat?", -1, 23, 40, 275, 8
+    AUTORADIOBUTTON "&Vyhledat a automaticky nainstalovat hardware (doporučeno)", IDC_AUTOINSTALL, 30, 55, 266, 8, WS_GROUP | NOT WS_TABSTOP
+    AUTORADIOBUTTON "Nainstalovat hardware, který si &ručně zvolím ze seznamu (pokročilé)", IDC_MANUALLYINST, 30, 70, 266, 8, NOT WS_TABSTOP
 END
 
 IDD_DETECTEDHWPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
     LTEXT "", IDC_STATUSTEXT, 21, 9, 275, 40
-    LTEXT "Detekovaný hardware:", IDC_DETECTEDHWTEXT, 21, 53, 176, 8
+    LTEXT "Detekovaný hardware:", IDC_DETECTEDHWTEXT, 21, 53, 176, 8
     CONTROL "", IDC_DETECTEDHWLIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 65, 275, 70
 END
 
 IDD_HWTYPESPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Pokud nevidíte vámi hledaný typ hardwaru, klepnìte na Zobrazit v\9aechna zaøízení.", IDC_STATUSTEXT, 21, 9, 275, 18
-    LTEXT "Bì\9e typy &hardwaru:", IDC_HWTYPESTEXT, 21, 31, 180, 8
+    LTEXT "Pokud nevidíte vámi hledaný typ hardwaru, klepněte na Zobrazit všechna zařízení.", IDC_STATUSTEXT, 21, 9, 275, 18
+    LTEXT "Běžné typy &hardwaru:", IDC_HWTYPESTEXT, 21, 31, 180, 8
     CONTROL "", IDC_HWTYPESLIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 42, 275, 92
 END
 
 IDD_PROGRESSPAGE DIALOG 0, 0, 317, 143
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Vyhledávání hardwaru mù\9ee trvat nìkolik minut.", -1, 21, 8, 275, 15
-    LTEXT "Celkový postup:", IDC_TPROGRESSTEXT, 21, 25, 275, 8
+    LTEXT "Vyhledávání hardwaru může trvat několik minut.", -1, 21, 8, 275, 15
+    LTEXT "Celkový postup:", IDC_TPROGRESSTEXT, 21, 25, 275, 8
     CONTROL "", IDC_TPROGRESSBAR, "msctls_progress32", 0, 21, 37, 275, 14
     LTEXT "", IDC_PROGRESSTEXT, 58, 58, 200, 8, SS_NOPREFIX
     CONTROL "", IDC_PROGRESSBAR, "msctls_progress32", 0, 58, 70, 200, 8
@@ -94,59 +94,59 @@ END
 
 IDD_FINISHPAGE DIALOG 0, 0, 317, 186
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Dokonèení Prùvodce pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
-    LTEXT "Prùvodce pøidáním hardwaru byl úspì\9anì dokonèen.", -1, 114, 32, 193, 19
+    LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
+    LTEXT "Průvodce přidáním hardwaru byl úspěšně dokončen.", -1, 114, 32, 193, 19
     LTEXT "", IDC_STATUSTEXT, 114, 70, 193, 92
-    LTEXT "Klepnutím na Dokonèit uzavøete prùvodce.", -1, 114, 166, 132, 8
+    LTEXT "Klepnutím na Dokončit uzavřete průvodce.", -1, 114, 166, 132, 8
 END
 
 IDD_ISFOUNDPAGE DIALOG 0, 0, 317, 186
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Dokonèení Prùvodce pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
-    LTEXT "Prùvodce na\9ael následující hardware pøipojený k tomuto poèítaèi:", -1, 114, 32, 193, 19
-    LTEXT "Klepnutím na Dokonèit uzavøete prùvodce.", -1, 114, 166, 132, 8
+    LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
+    LTEXT "Průvodce našel následující hardware připojený k tomuto počítači:", -1, 114, 32, 193, 19
+    LTEXT "Klepnutím na Dokončit uzavřete průvodce.", -1, 114, 166, 132, 8
     CONTROL "", IDC_FOUNDHARDWARELIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS, 114, 56, 193, 78
 END
 
 IDD_HWSTATUSPAGE DIALOG 0, 0, 317, 186
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Dokonèení Prùvodce pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 195, 28
-    LTEXT "Souèasný stav zvoleného hardwaru:", -1, 114, 40, 193, 19
+    LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 195, 28
+    LTEXT "Současný stav zvoleného hardwaru:", -1, 114, 40, 193, 19
     EDITTEXT IDC_HWSTATUSEDIT, 114, 60, 193, 70, ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP
-    LTEXT "Klepnutím na Dokonèit lze zaèít øe\9ait mo\9ené problémy.", -1, 114, 136, 193, 16
-    LTEXT "Klepnutím na Storno ukonèíte prùvodce.", IDC_STATUSTEXT, 114, 166, 132, 8
+    LTEXT "Klepnutím na Dokončit lze začít řešit možné problémy.", -1, 114, 136, 193, 16
+    LTEXT "Klepnutím na Storno ukončíte průvodce.", IDC_STATUSTEXT, 114, 166, 132, 8
 END
 
 IDD_NOTCONNECTEDPAGE DIALOG 0, 0, 317, 186
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Nelze pokraèovat v Prùvodci pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 28
-    LTEXT "Pokraèovat lze po pøipojení hardwaru k poèítaèi.", -1, 114, 40, 193, 16
-    AUTOCHECKBOX "Vypnou&t poèítaè po klepnutí na tlaèítko Dokonèit, aby mohl být hardware pøipojen.", IDC_TURNOFFCHECKBOX, 114, 64, 203, 20, BS_TOP | BS_MULTILINE
-    LTEXT "Ve vìt\9ainì pøípadù ReactOS automaticky nainstaluje hardware po jeho pøipojení. Pokud jej ReactOS nenajde, lze tohoto prùvodce znovu spustit a nainstalovat podpùrný software.", -1, 114, 98, 193, 32
-    LTEXT "Klepnutím na tlaèítko Dokonèit ukonèíte prùvodce.", IDC_STATUSTEXT, 114, 166, 193, 8
+    LTEXT "Nelze pokračovat v Průvodci přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 28
+    LTEXT "Pokračovat lze po připojení hardwaru k počítači.", -1, 114, 40, 193, 16
+    AUTOCHECKBOX "Vypnou&t počítač po klepnutí na tlačítko Dokončit, aby mohl být hardware připojen.", IDC_TURNOFFCHECKBOX, 114, 64, 203, 20, BS_TOP | BS_MULTILINE
+    LTEXT "Ve většině případů ReactOS automaticky nainstaluje hardware po jeho připojení. Pokud jej ReactOS nenajde, lze tohoto průvodce znovu spustit a nainstalovat podpůrný software.", -1, 114, 98, 193, 32
+    LTEXT "Klepnutím na tlačítko Dokončit ukončíte průvodce.", IDC_STATUSTEXT, 114, 166, 193, 8
 END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLNAME "Pøidat hardware"
-    IDS_CPLDESCRIPTION "Pøidá hardware do tohoto poèítaèe."
-    IDS_SEARCHTITLE "Èekejte, prosím, prùvodce hledá..."
-    IDS_SEARCHTEXT "Tento prùvodce hledá hardware, který byl nedávno pøipojen k tomuto poèítaèi, ale je\9atì nebyl nainstalován."
-    IDS_ISCONNECTED "Je hardware pøipojen?"
-    IDS_PROBELISTTITLE "Následující hardware ji\9e je nainstalován na tomto poèítaèi"
-    IDS_ADDNEWDEVICE "Pøidat nové hardwarové zaøízení"
-    IDS_SELECTWAYTITLE "Prùvodce vám mù\9ee pomoci nainstalovat jiný hardware"
-    IDS_HDTYPESTITLE "Ze seznamu ní\9ee zvolte typ instalovaného hardwaru"
+    IDS_CPLNAME "Přidat hardware"
+    IDS_CPLDESCRIPTION "Přidá hardware do tohoto počítače."
+    IDS_SEARCHTITLE "Čekejte, prosím, průvodce hledá..."
+    IDS_SEARCHTEXT "Tento průvodce hledá hardware, který byl nedávno připojen k tomuto počítači, ale ještě nebyl nainstalován."
+    IDS_ISCONNECTED "Je hardware připojen?"
+    IDS_PROBELISTTITLE "Následující hardware již je nainstalován na tomto počítači"
+    IDS_ADDNEWDEVICE "Přidat nové hardwarové zařízení"
+    IDS_SELECTWAYTITLE "Průvodce vám může pomoci nainstalovat jiný hardware"
+    IDS_HDTYPESTITLE "Ze seznamu níže zvolte typ instalovaného hardwaru"
 END
index b509fce..c44f7c6 100644 (file)
@@ -27,6 +27,9 @@
 
 #include <reactos/manifest_dll.rc>
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
diff --git a/dll/cpl/inetcpl/lang/cs-CZ.rc b/dll/cpl/inetcpl/lang/cs-CZ.rc
new file mode 100644 (file)
index 0000000..6684727
--- /dev/null
@@ -0,0 +1,99 @@
+/* FILE:       dll/cpl/inetcpl/lang/cs-CZ.rc
+ * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
+ * UPDATED:    2014-04-21
+ */
+ /* UTF-8 */
+ #pragma code_page(65001)
+
+ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+
+/* "General" propsheet */
+IDD_GENERAL DIALOG  0, 0, 320, 220
+STYLE WS_CAPTION | WS_CHILD | WS_DISABLED
+FONT 8, "MS Shell Dlg"
+CAPTION "Obecné"
+BEGIN
+
+    GROUPBOX    " Domovská stránka ", IDC_STATIC, 4, 4, 312, 52
+    LTEXT       "Zvolená adresa bude uložena jako domovská stránka.",
+                IDC_STATIC, 58, 10, 252, 10
+    EDITTEXT    IDC_HOME_EDIT, 58, 22, 252, 12, WS_VISIBLE | ES_AUTOHSCROLL
+    PUSHBUTTON  "&Aktuální stránka", IDC_HOME_CURRENT, 58, 36, 80, 14
+    PUSHBUTTON  "&Výchozí stránka", IDC_HOME_DEFAULT, 144, 36, 80, 14
+    PUSHBUTTON  "&Prázdná stránka", IDC_HOME_BLANK, 230, 36, 80, 14
+    GROUPBOX    " Historie prohlížení ", IDC_STATIC, 4, 60, 312, 46
+    LTEXT       "Lze smazat stránky v mezipaměti, cookies a další data.",
+                IDC_STATIC, 58, 72, 252, 10
+    PUSHBUTTON  "Smazat &soubory...", IDC_HISTORY_DELETE, 144, 86, 80, 14
+    PUSHBUTTON  "&Nastavení...", IDC_HISTORY_SETTINGS, 230, 86, 80, 14
+
+END
+
+/* "Delete browsing history" dialog */
+IDD_DELETE_HISTORY DIALOG  0, 0, 250, 250
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+CAPTION "Smazat historii prohlížení"
+BEGIN
+
+    AUTOCHECKBOX   "Dočasné internetové soubory\nUložené kopie webových stránek, obrázků a certifikátů.",
+                    IDC_DELETE_TEMP_FILES, 10, 8, 230, 30, BS_TOP | BS_MULTILINE
+    AUTOCHECKBOX   "Cookies\nSoubory uložené na počítači webovými stránkami, ve kterých jsou uložené například uživatelské předvolby nebo přihlašovací údaje.",
+                    IDC_DELETE_COOKIES, 10, 38, 230, 30, BS_TOP | BS_MULTILINE
+    AUTOCHECKBOX   "Historie\nSeznam navštívených webových stránek.",
+                    IDC_DELETE_HISTORY, 10, 68, 230, 30, BS_TOP | BS_MULTILINE
+    AUTOCHECKBOX   "Data formulářů\nUživatelská jména a další údaje, které byly zadány do formulářů.",
+                    IDC_DELETE_FORM_DATA, 10, 98, 230, 30, BS_TOP | BS_MULTILINE
+    AUTOCHECKBOX   "Hesla\nUložená hesla, která byla zadána do formulářů.",
+                    IDC_DELETE_PASSWORDS, 10, 128, 230, 30, BS_TOP | BS_MULTILINE
+    DEFPUSHBUTTON  "Storno", IDCANCEL, 185, 230, 60, 15, WS_GROUP
+    PUSHBUTTON     "Smazat", IDOK, 120, 230, 60, 15, WS_GROUP
+
+END
+
+/* "Security" propsheet */
+IDD_SECURITY DIALOG  0, 0, 320, 220
+STYLE WS_CAPTION | WS_CHILD | WS_DISABLED
+FONT 8, "MS Shell Dlg"
+CAPTION "Zabezpečení"
+BEGIN
+
+    CONTROL     "Listview", IDC_SEC_LISTVIEW, "SysListView32",
+                LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | WS_VSCROLL,
+                4, 4, 312, 58
+    LTEXT       "", IDC_SEC_ZONE_INFO, 4, 68, 312, 20
+    GROUPBOX    "", IDC_SEC_GROUP, 4, 88, 312, 126
+    CONTROL     "trackbar", IDC_SEC_TRACKBAR, "msctls_trackbar32",
+                TBS_VERT | TBS_AUTOTICKS | TBS_BOTH | TBS_REVERSED, 8, 98, 32, 100
+    LTEXT       "", IDC_SEC_LEVEL, 48, 102, 180, 12
+    LTEXT       "", IDC_SEC_LEVEL_INFO, 48, 114, 260, 80
+END
+
+/* "Content" propsheet */
+IDD_CONTENT DIALOG  0, 0, 320, 220
+STYLE WS_CAPTION | WS_CHILD | WS_DISABLED
+FONT 8, "MS Shell Dlg"
+CAPTION "Obsah"
+BEGIN
+
+    GROUPBOX    " Certifikáty ", IDC_STATIC, 4, 4, 312, 50
+    LTEXT       "Certifikáty slouží k osobní identifikaci a k identifikaci certifikačních autorit a vydavatelů.",
+                IDC_STATIC, 58, 14, 252, 18
+    PUSHBUTTON  "Certifikáty...", IDC_CERT, 146, 34, 80, 14
+    PUSHBUTTON "Vydavatelé...", IDC_CERT_PUBLISHER, 230, 34, 80, 14
+
+END
+
+STRINGTABLE
+BEGIN
+    IDS_CPL_NAME        "Nastavení Internetu"
+    IDS_CPL_INFO        "Konfigurovat Internetový prohlížeč Wine a související nastavení"
+    IDS_SEC_SETTINGS    "Nastavení zabezpečení pro zónu: "
+    IDS_SEC_LEVEL0      "Vlastní"
+    IDS_SEC_LEVEL1      "Velmi nízké"
+    IDS_SEC_LEVEL2      "Nízké"
+    IDS_SEC_LEVEL3      "Střední"
+    IDS_SEC_LEVEL4      "Zvýšené"
+    IDS_SEC_LEVEL5      "Vysoké"
+END
index 0536869..7637ab0 100644 (file)
@@ -18,9 +18,6 @@ IDI_CPLSYSTEM ICON "resources/applet.ico"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
@@ -55,6 +52,9 @@ IDI_CPLSYSTEM ICON "resources/applet.ico"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
index 603132d..c737c3d 100644 (file)
@@ -1,6 +1,6 @@
 /* FILE:       dll/cpl/joy/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2009-01-10
+ * UPDATED:    2014-04-25
  */
 
 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
@@ -8,35 +8,35 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 IDD_PROPPAGEMAIN DIALOGEX 0, 0, 252, 205
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
 EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Herní ovladaèe"
+CAPTION "Herní ovladače"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_CPLSYSTEM, -1, 7, 7, 20, 20
-    LTEXT "Tato nastavení pomáhají konfigurovat herní ovladaèe nainstalované na tomto poèítaèi.", -1, 33, 7, 214, 20, NOT WS_GROUP
-    GROUPBOX "Nai&nstalované herní ovladaèe", -1, 7, 34, 238, 117
+    LTEXT "Tato nastavení pomáhají konfigurovat herní ovladače nainstalované na tomto počítači.", -1, 33, 7, 214, 20, NOT WS_GROUP
+    GROUPBOX "Nai&nstalované herní ovladače", -1, 7, 34, 238, 117
     CONTROL "List1", IDC_CONTROLLER_LIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | 0x0000808D, 14, 44, 224, 80
-    PUSHBUTTON "&Pøidat...", IDC_ADD_BUTTON, 35, 129, 65, 14
+    PUSHBUTTON "&Přidat...", IDC_ADD_BUTTON, 35, 129, 65, 14
     PUSHBUTTON "&Odebrat", IDC_REMOVE_BUTTON, 104, 129, 65, 14, WS_DISABLED
     PUSHBUTTON "&Vlastnosti", IDC_PROPERTIES_BUTTON, 173, 129, 65, 14, WS_DISABLED
-    PUSHBUTTON "&Roz\9aíøené...", IDC_ADVANCED_BUTTON, 111, 157, 65, 14
-    PUSHBUTTON "Ø&e\9aení problémù...", IDC_TROUBLESHOOT_BUTTON, 180, 157, 65, 14
+    PUSHBUTTON "&Rozšířené...", IDC_ADVANCED_BUTTON, 111, 157, 65, 14
+    PUSHBUTTON "Ř&ešení problémů...", IDC_TROUBLESHOOT_BUTTON, 180, 157, 65, 14
     PUSHBUTTON "OK", IDOK, 195, 185, 50, 14
 END
 
 IDD_ADD DIALOGEX 0, 0, 265, 200
 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_CAPTION
 EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Pøidat herní ovladaè"
+CAPTION "Přidat herní ovladač"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_CPLSYSTEM, -1, 8, 7, 20, 20
-    LTEXT "Vyberte herní ovladaè ze seznamu ní\9ee, poté kliknìte na tlaèítko OK. Pokud se vá\9a ovladaè v seznamu nenachází, kliknìte na tlaèítko Vlastní.", -1, 35, 7, 210, 33
-    LTEXT "&Herní ovladaèe:", -1, 8, 45, 126, 8
+    LTEXT "Vyberte herní ovladač ze seznamu níže, poté klikněte na tlačítko OK. Pokud se váš ovladač v seznamu nenachází, klikněte na tlačítko Vlastní.", -1, 35, 7, 210, 33
+    LTEXT "&Herní ovladače:", -1, 8, 45, 126, 8
     LISTBOX IDC_GAME_CONTROLLERS_LIST, 7, 55, 251, 57, LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | WS_HSCROLL | WS_TABSTOP
-    AUTOCHECKBOX "&Zapnout kormidlo a pedály", IDC_ENABLE_RUDDERS_CHECKBOX, 7, 114, 100, 10, WS_GROUP
+    AUTOCHECKBOX "&Zapnout kormidlo a pedály", IDC_ENABLE_RUDDERS_CHECKBOX, 7, 114, 100, 10, WS_GROUP
     LTEXT "&Port:", -1, 7, 134, 38, 8, NOT WS_VISIBLE
     COMBOBOX IDC_GAME_PORT_COMBO, 7, 147, 140, 50, CBS_DROPDOWNLIST | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL
-    PUSHBUTTON "&Vlastní...", IDC_CUSTOM_BUTTON, 208, 147, 50, 14
+    PUSHBUTTON "&Vlastní...", IDC_CUSTOM_BUTTON, 208, 147, 50, 14
     CONTROL "", -25525, "STATIC", SS_ETCHEDHORZ, 7, 170, 251, 1
     DEFPUSHBUTTON "OK", IDOK, 155, 179, 50, 14
     PUSHBUTTON "Storno", IDCANCEL, 208, 179, 50, 14
@@ -45,22 +45,22 @@ END
 IDD_CUSTOM DIALOGEX 0, 0, 265, 183, 0
 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_CAPTION
 EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Vlastní herní ovladaè"
+CAPTION "Vlastní herní ovladač"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    GROUPBOX "Zvlá\9atní charakteristiky", -1, 7, 7, 245, 52
+    GROUPBOX "Zvláštní charakteristiky", -1, 7, 7, 245, 52
     AUTORADIOBUTTON "&Joystick", IDC_JOYSTICK_RADIO, 17, 23, 55, 10
-    AUTORADIOBUTTON "&Letecká øídící páka nebo kormidlo", IDC_FLIGHT_YOKE_RADIO, 147, 23, 89, 10
+    AUTORADIOBUTTON "&Letecká řídící páka nebo kormidlo", IDC_FLIGHT_YOKE_RADIO, 147, 23, 89, 10
     AUTORADIOBUTTON "&Gamepad", IDC_GAME_PAD_RADIO, 17, 40, 65, 10
-    AUTORADIOBUTTON "Øízení &auta", IDC_RACE_CAR_RADIO, 147, 40, 93, 10
+    AUTORADIOBUTTON "Řízení &auta", IDC_RACE_CAR_RADIO, 147, 40, 93, 10
     GROUPBOX "&Osy", -1, 7, 67, 116, 44, WS_GROUP
     COMBOBOX IDC_AXES_COMBO, 37, 79, 48, 50, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL
-    AUTORADIOBUTTON "Kormidlo/Pedály", IDC_RUDDER_PEDALS_RADIO, 14, 97, 63, 10, NOT WS_VISIBLE
+    AUTORADIOBUTTON "Kormidlo/Pedály", IDC_RUDDER_PEDALS_RADIO, 14, 97, 63, 10, NOT WS_VISIBLE
     AUTORADIOBUTTON "Osa Z", IDC_Z_AXIS_RADIO, 81, 97, 35, 10, NOT WS_VISIBLE
-    GROUPBOX "&Tlaèítka", -1, 137, 67, 116, 44
+    GROUPBOX "&Tlačítka", -1, 137, 67, 116, 44
     COMBOBOX IDC_BUTTONS_COMBO, 178, 79, 48, 50, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL, WS_EX_CLIENTEDGE
-    AUTOCHECKBOX "Obsahuje øízení zo&rného úhlu", IDC_INC_POINT_CHECKBOX, 7, 123, 115, 10
-    LTEXT "Název herního &ovladaèe:", -1, 7, 139, 200, 9
+    AUTOCHECKBOX "Obsahuje řízení zo&rného úhlu", IDC_INC_POINT_CHECKBOX, 7, 123, 115, 10
+    LTEXT "Název herního &ovladače:", -1, 7, 139, 200, 9
     EDITTEXT IDC_CONTROLLER_NAME_EDIT, 7, 150, 116, 15, ES_AUTOHSCROLL, WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
     DEFPUSHBUTTON "OK", IDOK, 137, 150, 50, 14
     PUSHBUTTON "Storno", IDCANCEL, 203, 150, 50, 14
@@ -69,21 +69,21 @@ END
 IDD_ADVANCED DIALOGEX 0, 0, 220, 86
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
 EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Roz\9aíøené nastavení"
+CAPTION "Rozšířené nastavení"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_CPLSYSTEM, -1, 7, 24, 20, 20
     DEFPUSHBUTTON "OK", IDOK, 106, 65, 50, 14
     PUSHBUTTON "Storno", IDCANCEL, 163, 65, 50, 14
-    LTEXT "Vyberte zaøízení, které chcete pou\9eívat se star\9aími programy.", -1, 7, 7, 208, 10
-    LTEXT "&Preferované zaøízení:", -1, 34, 24, 70, 10
+    LTEXT "Vyberte zařízení, které chcete používat se staršími programy.", -1, 7, 7, 208, 10
+    LTEXT "&Preferované zařízení:", -1, 34, 24, 70, 10
     COMBOBOX IDC_PREFERRED_DEV_COMBO, 34, 38, 179, 75, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL
 END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLSYSTEMNAME "Herní ovladaèe"
-    IDS_CPLSYSTEMDESCRIPTION "Pøidat, odebrat a konfigurovat herní ovladaèe jako napøíklad joysticky nebo gamepady."
-    IDS_CONTROLLER "Ovladaè"
+    IDS_CPLSYSTEMNAME "Herní ovladače"
+    IDS_CPLSYSTEMDESCRIPTION "Přidat, odebrat a konfigurovat herní ovladače jako například joysticky nebo gamepady."
+    IDS_CONTROLLER "Ovladač"
     IDS_STATUS "Stav"
 END
index e020710..364fb40 100644 (file)
@@ -1,6 +1,6 @@
 /* FILE:       dll/cpl/mmsys/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2009-02-02
+ * UPDATED:    2014-04-25
  */
 
 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
@@ -12,19 +12,19 @@ FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_CPLICON, IDI_CPLICON, 8, 5, 32, 32
     LTEXT "", IDC_DEVICE_NAME, 40, 10, 194, 36
-    GROUPBOX "Hlasitost zaøízení", -1, 7, 30, 230, 100
+    GROUPBOX "Hlasitost zařízení", -1, 7, 30, 230, 100
     CONTROL "", IDC_MUTE_ICON, "Static", SS_ICON | WS_VISIBLE, 17, 45, 32, 32
     CONTROL "", IDC_VOLUME_TRACKBAR, "msctls_trackbar32", TBS_AUTOTICKS | TBS_ENABLESELRANGE | TBS_BOTTOM | TBS_HORZ | WS_TABSTOP, 65, 45, 140, 14
-    LTEXT "Nízká", -1, 62, 66, 30, 17
-    LTEXT "Vysoká", -1, 195, 66, 30, 17
+    LTEXT "Nízká", -1, 62, 66, 30, 17
+    LTEXT "Vysoká", -1, 195, 66, 30, 17
     CHECKBOX "&Ztlumit", IDC_MUTE_CHECKBOX, 50, 78, 140, 10
-    CHECKBOX "Umístit &ikonu hlasitosti na panel úloh", IDC_ICON_IN_TASKBAR, 50, 92, 140, 10
-    PUSHBUTTON "&Upøesnit...", IDC_ADVANCED_BTN, 150, 105, 75, 15
-    GROUPBOX "Nastavení reproduktorù", IDC_SPEAKER_SET_BTN, 7, 140, 230, 80
+    CHECKBOX "Umístit &ikonu hlasitosti na panel úloh", IDC_ICON_IN_TASKBAR, 50, 92, 140, 10
+    PUSHBUTTON "&Upřesnit...", IDC_ADVANCED_BTN, 150, 105, 75, 15
+    GROUPBOX "Nastavení reproduktorů", IDC_SPEAKER_SET_BTN, 7, 140, 230, 80
     CONTROL "", IDC_SPEAKIMG, "Static", SS_OWNERDRAW, 4, 160, 70, 70
-    LTEXT "Nastavení ní\9ee lze pou\9eít ke zmìnìní hlasitosti jednotlivých reproduktorù a dal\9aích nastavení.", -1, 70, 155, 150, 36
-    PUSHBUTTON "&Hlasitost reproduktorù...", IDC_SPEAKER_VOL_BTN, 70, 195, 75, 15
-    PUSHBUTTON "U&pøesnit...", IDC_ADVANCED2_BTN, 150, 195, 75, 15
+    LTEXT "Nastavení níže lze použít ke změnění hlasitosti jednotlivých reproduktorů a dalších nastavení.", -1, 70, 155, 150, 36
+    PUSHBUTTON "&Hlasitost reproduktorů...", IDC_SPEAKER_VOL_BTN, 70, 195, 75, 15
+    PUSHBUTTON "U&přesnit...", IDC_ADVANCED2_BTN, 150, 195, 75, 15
 END
 
 IDD_SOUNDS DIALOGEX 0, 0, 246, 228
@@ -32,18 +32,18 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
 CAPTION "Zvuky"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Zvukové schéma je soubor zvukù, které jsou pøehrávány pøi událostech v systému ReactOS a programech. Lze zvolit existující schéma nebo ulo\9eit jiné, upravené.", -1, 8, 7, 230, 40
-    LTEXT "Zvukové s&chéma:", -1, 8, 42, 150, 17
+    LTEXT "Zvukové schéma je soubor zvuků, které jsou přehrávány při událostech v systému ReactOS a programech. Lze zvolit existující schéma nebo uložit jiné, upravené.", -1, 8, 7, 230, 40
+    LTEXT "Zvukové s&chéma:", -1, 8, 42, 150, 17
     COMBOBOX IDC_SOUND_SCHEME, 8, 53, 230, 46, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    PUSHBUTTON "&Ulo\9eit jako...", IDC_SAVEAS_BTN, 134, 70, 50, 15
+    PUSHBUTTON "&Uložit jako...", IDC_SAVEAS_BTN, 134, 70, 50, 15
     PUSHBUTTON "&Smazat", IDC_DELETE_BTN, 188, 70, 50, 15
-    LTEXT "Zvuky lze mìnit kliknutím na programovou událost v následujícím seznamu a vybráním zvuku, který má být pøehrán. Zmìny lze ulo\9eit jako nové zvukové schéma.", -1, 8, 90, 230, 40
-    LTEXT "&Události programù:", -1, 8, 118, 150, 17
+    LTEXT "Zvuky lze měnit kliknutím na programovou událost v následujícím seznamu a vybráním zvuku, který má být přehrán. Změny lze uložit jako nové zvukové schéma.", -1, 8, 90, 230, 40
+    LTEXT "&Události programů:", -1, 8, 118, 150, 17
     CONTROL "", IDC_SCHEME_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 8, 130, 230, 60, WS_EX_CLIENTEDGE
     LTEXT "&Zvuky:", IDC_TEXT_SOUND, 8, 194, 80, 17, WS_DISABLED
     COMBOBOX IDC_SOUND_LIST, 8, 205, 155, 146, CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP | WS_DISABLED
     PUSHBUTTON "", IDC_PLAY_SOUND, 168, 205, 15, 15, WS_DISABLED | BS_ICON
-    PUSHBUTTON "&Procházet...", IDC_BROWSE_SOUND, 188, 205, 50, 15, WS_DISABLED
+    PUSHBUTTON "&Procházet...", IDC_BROWSE_SOUND, 188, 205, 50, 15, WS_DISABLED
 END
 
 IDD_AUDIO DIALOGEX 0, 0, 246, 228
@@ -51,25 +51,25 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
 CAPTION "Zvuk"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    GROUPBOX "Pøehrávání zvuku", -1, 7, 7, 230, 60
+    GROUPBOX "Přehrávání zvuku", -1, 7, 7, 230, 60
     ICON IDI_CPLICON, IDI_CPLICON, 15, 20, 32, 32
-    LTEXT "&Výchozí zaøízení:", -1, 50, 20, 80, 17
+    LTEXT "&Výchozí zařízení:", -1, 50, 20, 80, 17
     COMBOBOX IDC_DEVICE_PLAY_LIST, 50, 30, 180, 46, CBS_DROPDOWNLIST
     PUSHBUTTON "&Hlasitost...", IDC_VOLUME1_BTN, 85, 47, 70, 15
-    PUSHBUTTON "&Upøesnit...", IDC_ADV2_BTN, 160, 47, 70, 15
-    GROUPBOX "Záznam zvuku", -1, 7, 75, 230, 60
+    PUSHBUTTON "&Upřesnit...", IDC_ADV2_BTN, 160, 47, 70, 15
+    GROUPBOX "Záznam zvuku", -1, 7, 75, 230, 60
     ICON IDI_MICROPHONE_ICON, IDI_MICROPHONE_ICON, 15, 88, 32, 32
-    LTEXT "Vý&chozí zaøízení:", -1, 50, 88, 80, 17
+    LTEXT "Vý&chozí zařízení:", -1, 50, 88, 80, 17
     COMBOBOX IDC_DEVICE_REC_LIST, 50, 98, 180, 46, CBS_DROPDOWNLIST
     PUSHBUTTON "H&lasitost...", IDC_VOLUME2_BTN, 85, 115, 70, 15
-    PUSHBUTTON "U&pøesnit...", IDC_ADV1_BTN, 160, 115, 70, 15
-    GROUPBOX "Pøehrávání MIDI hudby", -1, 7, 145, 230, 60
+    PUSHBUTTON "U&přesnit...", IDC_ADV1_BTN, 160, 115, 70, 15
+    GROUPBOX "Přehrávání MIDI hudby", -1, 7, 145, 230, 60
     ICON IDI_MIDICON, IDI_MIDICON, 15, 158, 32, 32
-    LTEXT "Výcho&zí zaøízení:", -1, 50, 158, 80, 17
+    LTEXT "Výcho&zí zařízení:", -1, 50, 158, 80, 17
     COMBOBOX IDC_DEVICE_MIDI_LIST, 50, 168, 180, 46, CBS_DROPDOWNLIST
     PUSHBUTTON "Hl&asitost...", IDC_VOLUME3_BTN, 85, 185, 70, 15
     PUSHBUTTON "&O produktu...", IDC_ADV3_BTN, 160, 185, 70, 15
-    CHECKBOX "Pou\9eíva&t jen výchozí zaøízení", IDC_DEFAULT_DEV_CHECKBOX, 7, 212, 140, 10
+    CHECKBOX "Používa&t jen výchozí zařízení", IDC_DEFAULT_DEV_CHECKBOX, 7, 212, 140, 10
 END
 
 IDD_VOICE DIALOGEX 0, 0, 246, 228
@@ -77,19 +77,19 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
 CAPTION "Hlas"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Tato nastavení ovlivòují hlasitost a roz\9aíøené volby pro pøehrávání hlasu a zvolené záznamové zaøízení.", -1, 8, 7, 230, 40
-    GROUPBOX "Pøehrávání hlasu", -1, 7, 37, 230, 60
+    LTEXT "Tato nastavení ovlivňují hlasitost a rozšířené volby pro přehrávání hlasu a zvolené záznamové zařízení.", -1, 8, 7, 230, 40
+    GROUPBOX "Přehrávání hlasu", -1, 7, 37, 230, 60
     ICON IDI_CPLICON, IDI_CPLICON, 15, 50, 32, 32
-    LTEXT "&Výchozí zaøízení:", -1, 50, 50, 80, 17
+    LTEXT "&Výchozí zařízení:", -1, 50, 50, 80, 17
     COMBOBOX IDC_DEVICE_VOICE_LIST, 50, 60, 180, 46, CBS_DROPDOWNLIST
     PUSHBUTTON "&Hlasitost...", IDC_VOLUME4_BTN, 85, 77, 70, 15
-    PUSHBUTTON "&Upøesnit...", IDC_ADV4_BTN, 160, 77, 70, 15
-    GROUPBOX "Záznam hlasu", -1, 7, 105, 230, 60
+    PUSHBUTTON "&Upřesnit...", IDC_ADV4_BTN, 160, 77, 70, 15
+    GROUPBOX "Záznam hlasu", -1, 7, 105, 230, 60
     ICON IDI_MICROPHONE_ICON, IDI_MICROPHONE_ICON, 15, 118, 32, 32
-    LTEXT "Vý&chozí zaøízení:", -1, 50, 118, 80, 17
+    LTEXT "Vý&chozí zařízení:", -1, 50, 118, 80, 17
     COMBOBOX IDC_DEVICE_VOICE_REC_LIST, 50, 128, 180, 46, CBS_DROPDOWNLIST
     PUSHBUTTON "H&lasitost...", IDC_VOLUME5_BTN, 85, 145, 70, 15
-    PUSHBUTTON "U&pøesnit...", IDC_ADV5_BTN, 160, 145, 70, 15
+    PUSHBUTTON "U&přesnit...", IDC_ADV5_BTN, 160, 145, 70, 15
     PUSHBUTTON "&Otestovat hardware...", IDC_TEST_HARDWARE, 160, 175, 70, 15
 END
 
@@ -102,10 +102,10 @@ END
 
 IDD_SAVE_SCHEME_AS DIALOG 9, 23, 225, 54
 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
-CAPTION "Ulo\9eit schéma jako"
+CAPTION "Uložit schéma jako"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "&Ulo\9eit toto zvukové schéma jako:", -1, 7, 7, 212, 9
+    LTEXT "&Uložit toto zvukové schéma jako:", -1, 7, 7, 212, 9
     EDITTEXT 8960, 7, 17, 211, 14, ES_AUTOHSCROLL
     DEFPUSHBUTTON "OK", IDOK, 93, 36, 60, 14
     PUSHBUTTON "Storno", IDCANCEL, 157, 36, 60, 14
@@ -117,156 +117,156 @@ CAPTION "Reproduktory"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON 4379, -1, 7, 8, 20, 20
-    LTEXT "Zvolte rozmístìní reproduktorù, které nejvíce odpovídá souèasnému.", -1, 36, 8, 215, 27
+    LTEXT "Zvolte rozmístění reproduktorů, které nejvíce odpovídá současnému.", -1, 36, 8, 215, 27
     CONTROL 110, 5376, "STATIC", SS_BITMAP | SS_CENTERIMAGE, 37, 40, 209, 112, WS_EX_TRANSPARENT
-    LTEXT "&Rozmístìní reproduktorù:", 8502, 53, 169, 55, 10
+    LTEXT "&Rozmístění reproduktorů:", 8502, 53, 169, 55, 10
     COMBOBOX 5401, 52, 182, 170, 200, CBS_DROPDOWNLIST | WS_VSCROLL | NOT WS_TABSTOP
 END
 
 IDD_PERFORMANCE1 DIALOG 0, 0, 257, 218
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Výkon"
+CAPTION "Výkon"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Tato nastavení ovlivòují, jak systém ReactOS pøehrává zvuk. Mohou pomoci pøi øe\9aení problémù se zvukem.", 8492, 34, 7, 218, 23
-    GROUPBOX "Pøehrávání zvuku", 8494, 7, 32, 243, 152
+    LTEXT "Tato nastavení ovlivňují, jak systém ReactOS přehrává zvuk. Mohou pomoci při řešení problémů se zvukem.", 8492, 34, 7, 218, 23
+    GROUPBOX "Přehrávání zvuku", 8494, 7, 32, 243, 152
     ICON 4379, 8512, 8, 8, 20, 20
-    LTEXT "&Hardwarová akcelerace:", 8495, 13, 56, 111, 14
+    LTEXT "&Hardwarová akcelerace:", 8495, 13, 56, 111, 14
     CONTROL "Slider1", 5395, "MSCTLS_TRACKBAR32", WS_GROUP | WS_TABSTOP | 0x00000401, 150, 54, 62, 18
-    LTEXT "&Kvalita pøevodu vzorkování:", 8496, 13, 123, 103, 14
+    LTEXT "&Kvalita převodu vzorkování:", 8496, 13, 123, 103, 14
     CONTROL "Slider1", 5396, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 150, 121, 62, 18
-    PUSHBUTTON "&Obnovit výchozí", 5400, 7, 191, 110, 14
-    LTEXT "\8eádná", 8497, 128, 56, 21, 10
-    LTEXT "Plná", 8498, 214, 56, 21, 9
-    LTEXT "Dobrá", 8499, 128, 123, 21, 10
-    LTEXT "Nejlep\9aí", 8500, 214, 123, 23, 9
-    LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zaøízení", 5399, 13, 145, 227, 21
-    LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zaøízení", 5398, 13, 78, 227, 22
+    PUSHBUTTON "&Obnovit výchozí", 5400, 7, 191, 110, 14
+    LTEXT "Žádná", 8497, 128, 56, 21, 10
+    LTEXT "Plná", 8498, 214, 56, 21, 9
+    LTEXT "Dobrá", 8499, 128, 123, 21, 10
+    LTEXT "Nejlepší", 8500, 214, 123, 23, 9
+    LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zařízení", 5399, 13, 145, 227, 21
+    LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zařízení", 5398, 13, 78, 227, 22
 END
 
 IDD_PERFORMANCE2 DIALOG 0, 0, 257, 218
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Výkon"
+CAPTION "Výkon"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT "Tato nastavení ovlivòují, jak systém ReactOS zaznamenává zvuk. Mohou pomoci pøi øe\9aení problémù se zvukem.", 8492, 34, 7, 217, 20
-    GROUPBOX "Záznam zvuku", 8494, 7, 29, 242, 122
+    LTEXT "Tato nastavení ovlivňují, jak systém ReactOS zaznamenává zvuk. Mohou pomoci při řešení problémů se zvukem.", 8492, 34, 7, 217, 20
+    GROUPBOX "Záznam zvuku", 8494, 7, 29, 242, 122
     ICON 4380, 8512, 8, 7, 20, 20
-    LTEXT "&Hardwarová akcelerace:", 8495, 13, 46, 103, 17
+    LTEXT "&Hardwarová akcelerace:", 8495, 13, 46, 103, 17
     CONTROL "Slider1", 5395, "MSCTLS_TRACKBAR32", WS_GROUP | WS_TABSTOP | 0x00000401, 150, 43, 62, 18
-    LTEXT "&Kvalita pøevodu vzorkování:", 8496, 13, 103, 103, 17
+    LTEXT "&Kvalita převodu vzorkování:", 8496, 13, 103, 103, 17
     CONTROL "Slider1", 5396, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 150, 101, 62, 18
-    PUSHBUTTON "&Obnovit výchozí", 5400, 9, 158, 110, 14
-    LTEXT "\8eádná", 8497, 125, 46, 24, 10
-    LTEXT "Plná", 8498, 217, 46, 19, 9
-    LTEXT "Dobrá", 8499, 125, 103, 24, 10
-    LTEXT "Nejlep\9aí", 8500, 217, 103, 19, 9
-    LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zaøízení", 5399, 13, 125, 222, 21
-    LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zaøízení", 5398, 13, 68, 218, 24
+    PUSHBUTTON "&Obnovit výchozí", 5400, 9, 158, 110, 14
+    LTEXT "Žádná", 8497, 125, 46, 24, 10
+    LTEXT "Plná", 8498, 217, 46, 19, 9
+    LTEXT "Dobrá", 8499, 125, 103, 24, 10
+    LTEXT "Nejlepší", 8500, 217, 103, 19, 9
+    LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zařízení", 5399, 13, 125, 222, 21
+    LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zařízení", 5398, 13, 68, 218, 24
 END
 
 IDD_SETUP1 DIALOG 0, 0, 227, 206
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
-CAPTION "Nastavení"
+CAPTION "Nastavení"
 FONT 8, "MS Shell Dlg"
 BEGIN
     GROUPBOX "ReactOS zvuk", 10243, 7, 5, 213, 192
     ICON 4393, 10241, 26, 26, 20, 20
-    LTEXT "Tento poèítaè nemù\9ee pøehrávat zvuk, proto\9ee slu\9eba zvuku systému ReactOS není spu\9ana.", 10245, 60, 25, 150, 40
+    LTEXT "Tento počítač nemůže přehrávat zvuk, protože služba zvuku systému ReactOS není spuštěna.", 10245, 60, 25, 150, 40
     AUTOCHECKBOX "&Spustit ReactOS zvuk", 10253, 60, 68, 150, 9
-    LTEXT "Poznámky", 10246, 58, 87, 150, 11
-    LTEXT "1. Pro spu\9atìní této slu\9eby je tøeba být správcem poèítaèe. Pokud nejste pøihlá\9aeni jako správce, bude vy\9eádáno jméno a heslo správce.", 10247, 60, 100, 150, 40
-    LTEXT "2. Po spu\9atìní ReactOS zvuku bude tøeba restartovat poèítaè.", 10248, 60, 140, 150, 40
+    LTEXT "Poznámky", 10246, 58, 87, 150, 11
+    LTEXT "1. Pro spuštění této služby je třeba být správcem počítače. Pokud nejste přihlášeni jako správce, bude vyžádáno jméno a heslo správce.", 10247, 60, 100, 150, 40
+    LTEXT "2. Po spuštění ReactOS zvuku bude třeba restartovat počítač.", 10248, 60, 140, 150, 40
 END
 
 IDD_MULTICHANNEL DIALOG 0, 0, 227, 218
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
-CAPTION "Vícekanálový zvuk"
+CAPTION "Vícekanálový zvuk"
 FONT 8, "MS Shell Dlg"
 BEGIN
     LTEXT "Tady bude popis.", 9506, 8, 4, 212, 24
-    LTEXT "Nízká", 9473, 65, 31, 14, 8
+    LTEXT "Nízká", 9473, 65, 31, 14, 8
     LTEXT "", 9472, 5, 31, 55, 8
     CONTROL "Slider1", 9475, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 29, 108, 17
-    LTEXT "Vysoká", 9474, 202, 31, 17, 8
-    LTEXT "Nízká", 9477, 65, 50, 14, 8
+    LTEXT "Vysoká", 9474, 202, 31, 17, 8
+    LTEXT "Nízká", 9477, 65, 50, 14, 8
     LTEXT "", 9476, 5, 50, 55, 8
     CONTROL "Slider1", 9479, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 48, 108, 17
-    LTEXT "Vysoká", 9478, 202, 50, 17, 8
-    LTEXT "Nízká", 9481, 65, 69, 14, 8
+    LTEXT "Vysoká", 9478, 202, 50, 17, 8
+    LTEXT "Nízká", 9481, 65, 69, 14, 8
     LTEXT "", 9480, 5, 69, 55, 8
     CONTROL "Slider1", 9483, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 67, 108, 17
-    LTEXT "Vysoká", 9482, 202, 69, 17, 8
-    LTEXT "Nízká", 9485, 65, 88, 14, 8
+    LTEXT "Vysoká", 9482, 202, 69, 17, 8
+    LTEXT "Nízká", 9485, 65, 88, 14, 8
     LTEXT "", 9484, 5, 88, 55, 8
     CONTROL "Slider1", 9487, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 86, 108, 17
-    LTEXT "Vysoká", 9486, 202, 88, 17, 8
-    LTEXT "Nízká", 9489, 65, 107, 14, 8
+    LTEXT "Vysoká", 9486, 202, 88, 17, 8
+    LTEXT "Nízká", 9489, 65, 107, 14, 8
     LTEXT "", 9488, 5, 107, 55, 8
     CONTROL "Slider1", 9491, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 105, 108, 17
-    LTEXT "Vysoká", 9490, 202, 107, 17, 8
-    LTEXT "Nízká", 9493, 65, 126, 14, 8
+    LTEXT "Vysoká", 9490, 202, 107, 17, 8
+    LTEXT "Nízká", 9493, 65, 126, 14, 8
     LTEXT "", 9492, 5, 126, 55, 8
     CONTROL "Slider1", 9495, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 124, 108, 17
-    LTEXT "Vysoká", 9494, 202, 126, 17, 8
-    LTEXT "Nízká", 9497, 65, 145, 14, 8
+    LTEXT "Vysoká", 9494, 202, 126, 17, 8
+    LTEXT "Nízká", 9497, 65, 145, 14, 8
     LTEXT "", 9496, 5, 145, 55, 8
     CONTROL "Slider1", 9499, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 143, 108, 17
-    LTEXT "Vysoká", 9498, 202, 145, 17, 8
-    LTEXT "Nízká", 9501, 65, 164, 14, 8
+    LTEXT "Vysoká", 9498, 202, 145, 17, 8
+    LTEXT "Nízká", 9501, 65, 164, 14, 8
     LTEXT "", 9500, 5, 164, 55, 8
     CONTROL "Slider1", 9503, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 162, 108, 17
-    LTEXT "Vysoká", 9502, 202, 164, 17, 8
-    AUTOCHECKBOX "&Pohybovat v\9aemi posuvníky najednou", 9504, 5, 185, 216, 9
-    PUSHBUTTON "&Obnovit výchozí", 9505, 110, 199, 110, 14
+    LTEXT "Vysoká", 9502, 202, 164, 17, 8
+    AUTOCHECKBOX "&Pohybovat všemi posuvníky najednou", 9504, 5, 185, 216, 9
+    PUSHBUTTON "&Obnovit výchozí", 9505, 110, 199, 110, 14
 END
 
 IDD_SETUP2 DIALOG 0, 0, 227, 206
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
-CAPTION "Nastavení"
+CAPTION "Nastavení"
 FONT 8, "MS Shell Dlg"
 BEGIN
     GROUPBOX "ReactOS zvuk", 10259, 7, 5, 213, 192
     ICON 4394, 10257, 25, 25, 20, 20
-    LTEXT "Slu\9eba zvuku systému ReactOS je nyní spu\9atìna. Zvuk nicménì nemusí fungovat správnì, dokud nebude systém ReactOS restartován. Pokud chcete restartovat nyní, nejdøíve ulo\9ete svou práci a ukonèete v\9aechny spu\9atìné programy.", 10261, 60, 25, 150, 50
-    LTEXT "Klepnutím na tlaèítko OK restartujete systém ReactOS.", 10262, 60, 75, 150, 20
-    LTEXT "Pokud klepnete na tlaèítko Storno, bude tøeba poèítaè restartovat pozdìji, aby ReactOS zvuk fungoval správnì.", 10263, 60, 100, 150, 40
+    LTEXT "Služba zvuku systému ReactOS je nyní spuštěna. Zvuk nicméně nemusí fungovat správně, dokud nebude systém ReactOS restartován. Pokud chcete restartovat nyní, nejdříve uložte svou práci a ukončete všechny spuštěné programy.", 10261, 60, 25, 150, 50
+    LTEXT "Klepnutím na tlačítko OK restartujete systém ReactOS.", 10262, 60, 75, 150, 20
+    LTEXT "Pokud klepnete na tlačítko Storno, bude třeba počítač restartovat později, aby ReactOS zvuk fungoval správně.", 10263, 60, 100, 150, 40
 END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLNAME "Zvuky a zvuková zaøízení"
-    IDS_CPLDESCRIPTION "Upraví zvukové schéma Va\9aeho poèítaèe, nebo nastaví reproduktory a nahrávací zaøízení."
-    IDS_NO_SOUND "(Není)"
+    IDS_CPLNAME "Zvuky a zvuková zařízení"
+    IDS_CPLDESCRIPTION "Upraví zvukové schéma Vašeho počítače, nebo nastaví reproduktory a nahrávací zařízení."
+    IDS_NO_SOUND "(Není)"
     IDS_NO_DEVICES "No Devices"
     5825 "Chyba programu"
-    5826 "Ukonèení programu"
-    5827 "Varování pøi kritickém stavu baterie"
-    5828 "Pøipojení zaøízení"
-    5829 "Odpojení zaøízení"
-    5830 "Nezdaøené pøipojení zaøízení"
-    5831 "Vysypání ko\9ae"
-    5832 "Varování pøi nízkém stavu baterie"
+    5826 "Ukončení programu"
+    5827 "Varování při kritickém stavu baterie"
+    5828 "Připojení zařízení"
+    5829 "Odpojení zařízení"
+    5830 "Nezdařené připojení zařízení"
+    5831 "Vysypání koše"
+    5832 "Varování při nízkém stavu baterie"
     5833 "Maximalizace"
-    5834 "Vyvolání pøíkazu z nabídky"
-    5835 "Vyvolání nabídky"
+    5834 "Vyvolání příkazu z nabídky"
+    5835 "Vyvolání nabídky"
     5836 "Minimalizace"
-    5837 "Oznámení o nové po\9a"
-    5838 "Zahájení navigace"
-    5839 "Spu\9atìní programu"
-    5840 "Dokonèení tisku"
-    5841 "Obnovení z maximalizace"
-    5842 "Obnovení z minimalizace"
-    5843 "Hvìzdièka"
-    5844 "Výchozí nastavení zvuku"
-    5845 "Výstraha"
-    5846 "Ukonèení systému ReactOS"
-    5847 "Kritické zastavení"
-    5848 "Systémová oznámení"
-    5849 "Otázka"
-    5850 "Spu\9atìní systému ReactOS"
-    5851 "Otevøení nabídky Start"
-    5852 "Odhlá\9aení od systému ReactOS"
-    5853 "Pøihlá\9aení k systému ReactOS"
+    5837 "Oznámení o nové poště"
+    5838 "Zahájení navigace"
+    5839 "Spuštění programu"
+    5840 "Dokončení tisku"
+    5841 "Obnovení z maximalizace"
+    5842 "Obnovení z minimalizace"
+    5843 "Hvězdička"
+    5844 "Výchozí nastavení zvuku"
+    5845 "Výstraha"
+    5846 "Ukončení systému ReactOS"
+    5847 "Kritické zastavení"
+    5848 "Systémová oznámení"
+    5849 "Otázka"
+    5850 "Spuštění systému ReactOS"
+    5851 "Otevření nabídky Start"
+    5852 "Odhlášení od systému ReactOS"
+    5853 "Přihlášení k systému ReactOS"
     5854 "ReactOS Explorer"
 END
index b8992f7..0d2cc88 100644 (file)
@@ -66,9 +66,6 @@ IDB_SPEAKIMG BITMAP "resources/speaker.bmp"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
@@ -112,6 +109,9 @@ IDB_SPEAKIMG BITMAP "resources/speaker.bmp"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
index 52afc5b..5b747dc 100644 (file)
@@ -2,142 +2,142 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 IDD_PROPPAGEPOWERSHEMES DIALOGEX 0, 0, 252, 237
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Schémata napájení"
+CAPTION "Schémata napájení"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_ACDC, IDI_ACDC, 7, 7, 28, 22
-    LTEXT "Vyberte napájecí schéma, které se nejvíce hodí pro tento poèítaè. V\9aechny zmìny nastavení se ulo\9eí do vybraného schématu.", -1, 37, 6, 209, 36
-    GROUPBOX "&Schéma napájení", -1, 6, 43, 240, 50
+    LTEXT "Vyberte napájecí schéma, které se nejvíce hodí pro tento počítač. Všechny změny nastavení se uloží do vybraného schématu.", -1, 37, 6, 209, 36
+    GROUPBOX "&Schéma napájení", -1, 6, 43, 240, 50
     COMBOBOX IDC_ENERGYLIST, 14, 54, 224, 92, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL
-    PUSHBUTTON "&Ulo\9eit jako...", IDC_SAVEAS_BTN, 109, 72, 70, 14, WS_DISABLED
+    PUSHBUTTON "&Uložit jako...", IDC_SAVEAS_BTN, 109, 72, 70, 14, WS_DISABLED
     PUSHBUTTON "&Odstranit", IDC_DELETE_BTN, 183, 72, 55, 14, WS_DISABLED
-    GROUPBOX "Neznámý", IDC_GRPDETAIL, 6, 95, 240, 136
-    LTEXT "Pokud je poèítaè:", IDC_SAT, 12, 109, 60, 12
-    LTEXT "Pøipojen", IDC_SAC, 123, 110, 45, 15
+    GROUPBOX "Neznámý", IDC_GRPDETAIL, 6, 95, 240, 136
+    LTEXT "Pokud je počítač:", IDC_SAT, 12, 109, 60, 12
+    LTEXT "Připojen", IDC_SAC, 123, 110, 45, 15
     ICON IDI_AC, IDC_IAC, 97, 108, 21, 20
     LTEXT "Funguje na baterie", IDC_SDC, 195, 110, 45, 15
     ICON IDI_DC, IDC_IDC, 170, 108, 21, 20
     LTEXT "Vypnout &monitor:", IDC_MONITOR, 13, 148, 84, 10
     COMBOBOX IDC_MONITORACLIST, 100, 145, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     COMBOBOX IDC_MONITORDCLIST, 173, 145, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    LTEXT "Vypnout pevné &disky:", IDC_DISK, 13, 171, 84, 10
+    LTEXT "Vypnout pevné &disky:", IDC_DISK, 13, 171, 84, 10
     COMBOBOX IDC_DISKACLIST, 100, 167, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     COMBOBOX IDC_DISKDCLIST, 173, 167, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    LTEXT "Úsporný &re\9eim:", IDC_STANDBY, 13, 191, 84, 10
+    LTEXT "Úsporný &režim:", IDC_STANDBY, 13, 191, 84, 10
     COMBOBOX IDC_STANDBYACLIST, 100, 188, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     COMBOBOX IDC_STANDBYDCLIST, 173, 188, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    LTEXT "&Re\9eim spánku:", IDC_HYBERNATE, 13, 212, 84, 10
+    LTEXT "&Režim spánku:", IDC_HYBERNATE, 13, 212, 84, 10
     COMBOBOX IDC_HYBERNATEACLIST, 100, 209, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     COMBOBOX IDC_HYBERNATEDCLIST, 173, 209, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
 END
 
 IDD_PROPPAGEALARMS DIALOGEX 0, 0, 252, 237
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "Varování"
+CAPTION "Varování"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    GROUPBOX "Varování o nízkém stavu baterie", -1, 10, 15, 235, 95
-    CONTROL "Aktivovat &varování o nízkém stavu baterie, kdy\9e úroveò nabití dosáhne:", IDC_ALARM1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 17, 190, 15
-    LTEXT "neznámá", IDC_ALARMVALUE1, 209, 20, 33, 10
+    GROUPBOX "Varování o nízkém stavu baterie", -1, 10, 15, 235, 95
+    CONTROL "Aktivovat &varování o nízkém stavu baterie, když úroveň nabití dosáhne:", IDC_ALARM1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 17, 190, 15
+    LTEXT "neznámá", IDC_ALARMVALUE1, 209, 20, 33, 10
     LTEXT "0%", -1, 28, 43, 15, 10
     CONTROL "Slider1", IDC_ALARMBAR1, "msctls_trackbar32", TBS_HORZ | TBS_AUTOTICKS | WS_TABSTOP, 42, 45, 170, 15
     LTEXT "100%", -1, 214, 43, 25, 10
-    PUSHBUTTON "&Akce pøi varování...", -1, 17, 69, 70, 14, WS_DISABLED
-    LTEXT "Oznámení:", -1, 95, 71, 57, 10
-    LTEXT "Neznámé", IDC_ALARMMSG1, 154, 71, 84, 10
+    PUSHBUTTON "&Akce při varování...", -1, 17, 69, 70, 14, WS_DISABLED
+    LTEXT "Oznámení:", -1, 95, 71, 57, 10
+    LTEXT "Neznámé", IDC_ALARMMSG1, 154, 71, 84, 10
     LTEXT "Akce:", -1, 95, 83, 55, 10
-    LTEXT "Neznámá", IDC_ALARMAKTION1, 154, 83, 84, 10
+    LTEXT "Neznámá", IDC_ALARMAKTION1, 154, 83, 84, 10
     LTEXT "Spustit program:", -1, 95, 95, 55, 10
-    LTEXT "Neznámý", IDC_ALARMPROG1, 154, 95, 84, 10
-    GROUPBOX "Varování o kritickém stavu baterie", -1, 6, 120, 239, 106
-    CONTROL "Aktivovat varování o &kritickém stavu baterie, kdy\9e úroveò nabití dosáhne:", IDC_ALARM2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 131, 180, 15
-    LTEXT "neznámá", IDC_ALARMVALUE2, 209, 133, 33, 10
+    LTEXT "Neznámý", IDC_ALARMPROG1, 154, 95, 84, 10
+    GROUPBOX "Varování o kritickém stavu baterie", -1, 6, 120, 239, 106
+    CONTROL "Aktivovat varování o &kritickém stavu baterie, když úroveň nabití dosáhne:", IDC_ALARM2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 131, 180, 15
+    LTEXT "neznámá", IDC_ALARMVALUE2, 209, 133, 33, 10
     LTEXT "0%", -1, 28, 154, 15, 10
     CONTROL "Slider1", IDC_ALARMBAR2, "msctls_trackbar32", TBS_HORZ | TBS_AUTOTICKS | WS_TABSTOP, 42, 158, 170, 15
     LTEXT "100%", -1, 214, 154, 25, 10
-    PUSHBUTTON "Akce &pøi varování...", -1, 17, 183, 70, 14, WS_DISABLED
-    LTEXT "Oznámení:", -1, 95, 185, 50, 10
-    LTEXT "Neznámé", IDC_ALARMMSG2, 154, 185, 84, 10
+    PUSHBUTTON "Akce &při varování...", -1, 17, 183, 70, 14, WS_DISABLED
+    LTEXT "Oznámení:", -1, 95, 185, 50, 10
+    LTEXT "Neznámé", IDC_ALARMMSG2, 154, 185, 84, 10
     LTEXT "Akce:", -1, 95, 198, 45, 10
-    LTEXT "Neznámá", IDC_ALARMAKTION2, 154, 198, 84, 10
+    LTEXT "Neznámá", IDC_ALARMAKTION2, 154, 198, 84, 10
     LTEXT "Spustit program:", -1, 95, 211, 50, 10
-    LTEXT "Neznámý", IDC_ALARMPROG2, 154, 211, 84, 10
+    LTEXT "Neznámý", IDC_ALARMPROG2, 154, 211, 84, 10
 END
 
 IDD_PROPPAGEADVANCED DIALOGEX 0, 0, 252, 237
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "Upøesnit"
+CAPTION "Upřesnit"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_ACDC, IDI_ACDC, 7, 7, 20, 20
-    LTEXT "Vyberte, které nastavení sní\9eené spotøeby chcete pou\9eít.", -1, 37, 6, 207, 20
-    GROUPBOX "Mo\9enosti", -1, 6, 30, 240, 65
-    CONTROL "V\9edy zobrazovat &ikonu na hlavním panelu", IDC_SYSTRAYBATTERYMETER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 43, 220, 10
-    CONTROL "Dotázat se na &heslo pøi pøechodu z úsporného re\9eimu", IDC_PASSWORDLOGON, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 60, 220, 10
-    CONTROL "&Sní\9eit jas displeje pøi chodu na baterie.", IDC_VIDEODIMDISPLAY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 78, 220, 10
-    GROUPBOX "Tlaèítka napájení", -1, 6, 101, 240, 127
-    LTEXT "&Pøi sklopení displeje pøenosného poèítaèe:", IDC_SLIDCLOSE, 15, 115, 222, 10
+    LTEXT "Vyberte, které nastavení snížené spotřeby chcete použít.", -1, 37, 6, 207, 20
+    GROUPBOX "Možnosti", -1, 6, 30, 240, 65
+    CONTROL "Vždy zobrazovat &ikonu na hlavním panelu", IDC_SYSTRAYBATTERYMETER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 43, 220, 10
+    CONTROL "Dotázat se na &heslo při přechodu z úsporného režimu", IDC_PASSWORDLOGON, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 60, 220, 10
+    CONTROL "&Snížit jas displeje při chodu na baterie.", IDC_VIDEODIMDISPLAY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 78, 220, 10
+    GROUPBOX "Tlačítka napájení", -1, 6, 101, 240, 127
+    LTEXT "&Při sklopení displeje přenosného počítače:", IDC_SLIDCLOSE, 15, 115, 222, 10
     COMBOBOX IDC_LIDCLOSE, 15, 127, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
-    LTEXT "Pøi stisknutí tlaèítka &napájení:", IDC_SPOWERBUTTON, 15, 153, 222, 10
+    LTEXT "Při stisknutí tlačítka &napájení:", IDC_SPOWERBUTTON, 15, 153, 222, 10
     COMBOBOX IDC_POWERBUTTON, 15, 165, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
-    LTEXT "Pøi stisknutí tlaèítka re\9eimu &spánku:", IDC_SSLEEPBUTTON, 15, 191, 222, 10
+    LTEXT "Při stisknutí tlačítka režimu &spánku:", IDC_SSLEEPBUTTON, 15, 191, 222, 10
     COMBOBOX IDC_SLEEPBUTTON, 15, 203, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
 END
 
 IDD_PROPPAGEHIBERNATE DIALOGEX 0, 0, 252, 237
 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "Re\9eim spánku"
+CAPTION "Režim spánku"
 FONT 8, "MS Shell Dlg"
 BEGIN
     ICON IDI_HIBERNATE, IDI_HIBERNATE, 7, 7, 20, 20
-    LTEXT "Pokud Vá\9a poèítaè pøejde do re\9eimu spánku, ulo\9eí obsah své pamìti na pevný disk a vypne se. Po opìtovném spu\9atìní se vrátí do pùvodního stavu.", -1, 37, 6, 210, 35
-    GROUPBOX "Re\9eim spánku", -1, 6, 41, 240, 32
-    CONTROL "Zapnout funkci re\9eim &spánku", IDC_HIBERNATEFILE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 55, 210, 10
-    GROUPBOX "Místo na disku potøebné pro re\9eim spánku", -1, 6, 80, 240, 76
-    LTEXT "Volné místo:", -1, 15, 95, 140, 10
-    LTEXT "Neznámé", IDC_FREESPACE, 160, 95, 80, 10
-    LTEXT "Potøebné místo na disku:", -1, 15, 115, 140, 10
-    LTEXT "Neznámé", IDC_SPACEFORHIBERNATEFILE, 160, 115, 80, 10
-    LTEXT "Pro funkci re\9eim spánku musíte uvolnit místo na disku. ", IDC_TOLESSFREESPACE, 15, 135, 224, 20
+    LTEXT "Pokud Váš počítač přejde do režimu spánku, uloží obsah své paměti na pevný disk a vypne se. Po opětovném spuštění se vrátí do původního stavu.", -1, 37, 6, 210, 35
+    GROUPBOX "Režim spánku", -1, 6, 41, 240, 32
+    CONTROL "Zapnout funkci režim &spánku", IDC_HIBERNATEFILE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 55, 210, 10
+    GROUPBOX "Místo na disku potřebné pro režim spánku", -1, 6, 80, 240, 76
+    LTEXT "Volné místo:", -1, 15, 95, 140, 10
+    LTEXT "Neznámé", IDC_FREESPACE, 160, 95, 80, 10
+    LTEXT "Potřebné místo na disku:", -1, 15, 115, 140, 10
+    LTEXT "Neznámé", IDC_SPACEFORHIBERNATEFILE, 160, 115, 80, 10
+    LTEXT "Pro funkci režim spánku musíte uvolnit místo na disku. ", IDC_TOLESSFREESPACE, 15, 135, 224, 20
 END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLNAME_1 "Mo\9enosti napájení"
-    IDS_CPLDESCRIPTION_1 "Nastaví mo\9enosti napájení a \9aetøení energií pro tento poèítaè."
+    IDS_CPLNAME_1 "Možnosti napájení"
+    IDS_CPLDESCRIPTION_1 "Nastaví možnosti napájení a šetření energií pro tento počítač."
     IDS_PROCENT "%i%%"
     IDS_SOUND "Zvuk"
     IDS_TEXT "Text"
-    IDS_CONFIG1 "Nastavení pro schéma napájení %1"
-    IDS_CONFIG2 "Pokroèilá nastavení pro %1"
-    IDS_SIZEBYTS "%i bytù"
+    IDS_CONFIG1 "Nastavení pro schéma napájení %1"
+    IDS_CONFIG2 "Pokročilá nastavení pro %1"
+    IDS_SIZEBYTS "%i bytů"
     IDS_SIZEMB "%i MB"
-    IDS_NOACTION "Nedìlat nic"
-    IDS_PowerActionNone1 "\8eádná akce"
-    IDS_PowerActionUnknown "Neznámý"
-    IDS_PowerActionSleep "Úsporný re\9eim"
-    IDS_PowerActionHibernate "Re\9eim spánku"
+    IDS_NOACTION "Nedělat nic"
+    IDS_PowerActionNone1 "Žádná akce"
+    IDS_PowerActionUnknown "Neznámý"
+    IDS_PowerActionSleep "Úsporný režim"
+    IDS_PowerActionHibernate "Režim spánku"
     IDS_PowerActionShutdown "Vypnout"
     IDS_PowerActionRestart "Restartovat"
-    IDS_PowerActionShutdownOff "Vypnout a odpojit napájení"
-    IDS_PowerActionWarmEject "Zeptat se na po\9eadovanou akci"
-    IDS_PowerActionNone2 "Není"
-    IDS_TIMEOUT1 "Po 1 minutì"
-    IDS_TIMEOUT2 "Po 2 minutách"
-    IDS_TIMEOUT3 "Po 3 minutách"
-    IDS_TIMEOUT4 "Po 5 minutách"
-    IDS_TIMEOUT5 "Po 10 minutách"
-    IDS_TIMEOUT6 "Po 15 minutách"
-    IDS_TIMEOUT7 "Po 20 minutách"
-    IDS_TIMEOUT8 "Po 25 minutách"
-    IDS_TIMEOUT9 "Po 30 minutách"
-    IDS_TIMEOUT10 "Po 45 minutách"
-    IDS_TIMEOUT11 "Po 1 hodinì"
-    IDS_TIMEOUT12 "Po 2 hodinách"
-    IDS_TIMEOUT13 "Po 3 hodinách"
-    IDS_TIMEOUT14 "Po 4 hodinách"
-    IDS_TIMEOUT15 "Po 5 hodinách"
+    IDS_PowerActionShutdownOff "Vypnout a odpojit napájení"
+    IDS_PowerActionWarmEject "Zeptat se na požadovanou akci"
+    IDS_PowerActionNone2 "Není"
+    IDS_TIMEOUT1 "Po 1 minutě"
+    IDS_TIMEOUT2 "Po 2 minutách"
+    IDS_TIMEOUT3 "Po 3 minutách"
+    IDS_TIMEOUT4 "Po 5 minutách"
+    IDS_TIMEOUT5 "Po 10 minutách"
+    IDS_TIMEOUT6 "Po 15 minutách"
+    IDS_TIMEOUT7 "Po 20 minutách"
+    IDS_TIMEOUT8 "Po 25 minutách"
+    IDS_TIMEOUT9 "Po 30 minutách"
+    IDS_TIMEOUT10 "Po 45 minutách"
+    IDS_TIMEOUT11 "Po 1 hodině"
+    IDS_TIMEOUT12 "Po 2 hodinách"
+    IDS_TIMEOUT13 "Po 3 hodinách"
+    IDS_TIMEOUT14 "Po 4 hodinách"
+    IDS_TIMEOUT15 "Po 5 hodinách"
     IDS_TIMEOUT16 "Nikdy"
-    IDS_DEL_SCHEME "Opravdu si pøejete smazat toto schéma napájení?"
-    IDS_DEL_SCHEME_TITLE "Smazat schéma"
+    IDS_DEL_SCHEME "Opravdu si přejete smazat toto schéma napájení?"
+    IDS_DEL_SCHEME_TITLE "Smazat schéma"
 END
index 9446675..0a1e3ea 100644 (file)
@@ -23,9 +23,6 @@ IDI_HIBERNATE ICON "resources/hibernate.ico"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DE_DE
     #include "lang/de-DE.rc"
 #endif
@@ -72,6 +69,9 @@ IDI_HIBERNATE ICON "resources/hibernate.ico"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
index d747d5a..eb34743 100644 (file)
@@ -2,7 +2,7 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 IDD_DATETIMEPAGE DIALOGEX 0, 0, 252, 146
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Datum && Èas"
+CAPTION "Datum && Čas"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     GROUPBOX "&Datum", -1, 4, 2, 122, 125
@@ -11,7 +11,7 @@ BEGIN
     CONTROL "", IDC_YEAR, UPDOWN_CLASS, UDS_SETBUDDYINT | UDS_NOTHOUSANDS |
             UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_BORDER | WS_GROUP, 120, 17, 50, 12
     CONTROL "", IDC_MONTHCALENDAR, "MonthCalWnd", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 11, 37, 108, 80, WS_EX_CLIENTEDGE
-    GROUPBOX "&Èas", -1, 132, 2, 113, 125
+    GROUPBOX "&Čas", -1, 132, 2, 113, 125
     CONTROL "", IDC_TIMEPICKER, "SysDateTimePick32", DTS_TIMEFORMAT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 144, 105, 90, 12
     LTEXT "", IDC_TIMEZONE, 6, 132, 242, 11
     CONTROL "", IDC_CLOCKWND, "ClockWndClass", WS_CHILD | WS_VISIBLE, 138, 12, 102, 89
@@ -19,39 +19,39 @@ END
 
 IDD_TIMEZONEPAGE DIALOGEX 0, 0, 252, 146
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Èasové pásmo"
+CAPTION "Časové pásmo"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     COMBOBOX IDC_TIMEZONELIST, 5, 4, 241, 136, CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP
     CONTROL "", IDC_WORLD_BACKGROUND, "Static", SS_OWNERDRAW, 5, 20, 240, 110, WS_EX_STATICEDGE
-    AUTOCHECKBOX "Provádìt zmìnu na letní èas a zpìt automaticky",
+    AUTOCHECKBOX "Provádět změnu na letní čas a zpět automaticky",
                  IDC_AUTODAYLIGHT, 6, 132, 242, 11, WS_VISIBLE | WS_GROUP | WS_TABSTOP
 END
 
 IDD_INETTIMEPAGE DIALOGEX 0, 0, 252, 146
 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Èas v Internetu"
+CAPTION "Čas v Internetu"
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     COMBOBOX IDC_SERVERLIST, 65, 22, 117, 136, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    AUTOCHECKBOX "Automaticky synchronizovat èas s èasovým serverem v Internetu",
+    AUTOCHECKBOX "Automaticky synchronizovat čas s časovým serverem v Internetu",
                  IDC_AUTOSYNC, 11, 7, 241, 10, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
     LTEXT "Server:", IDC_SERVERTEXT, 34, 22, 28, 13
     PUSHBUTTON "Aktualizovat", IDC_UPDATEBUTTON, 187, 22, 49, 14
     LTEXT "", IDC_SUCSYNC, 16, 54, 214, 23
     LTEXT "", IDC_NEXTSYNC, 12, 96, 137, 12
-    LTEXT "Synchronizace mù\9ee probìhnout pouze v pøípadì, \9ee je poèítaè pøipojen k síti Internet.", -1, 12, 114, 225, 25
+    LTEXT "Synchronizace může proběhnout pouze v případě, že je počítač připojen k síti Internet.", -1, 12, 114, 225, 25
 END
 
 STRINGTABLE
 BEGIN
-    IDS_CPLNAME "Datum/Èas"
-    IDS_CPLDESCRIPTION "Nastavuje datum, èas a zmìny èasového pásma."
-    IDS_TIMEZONETEXT "Aktuální èasové pásmo: %s"
-    IDS_TIMEZONEINVALID "Neplatné"
-    IDS_TIMEZONEUNKNOWN "Neznámé"
-    IDS_INETTIMESUCSYNC "Èas byl úspì\9anì synchronizován z %s %s v %s"
-    IDS_INETTIMENEXTSYNC "Dal\9aí synchronizace: %s v %s"
-    IDS_INETTIMESYNCING "Prosím èekejte, zatímco systém ReactOS synchronizuje èas s %s"
-    IDS_INETTIMEERROR "Pøi synchronizaci èasu s %s nastala chyba"
+    IDS_CPLNAME "Datum/Čas"
+    IDS_CPLDESCRIPTION "Nastavuje datum, čas a změny časového pásma."
+    IDS_TIMEZONETEXT "Aktuální časové pásmo: %s"
+    IDS_TIMEZONEINVALID "Neplatné"
+    IDS_TIMEZONEUNKNOWN "Neznámé"
+    IDS_INETTIMESUCSYNC "Čas byl úspěšně synchronizován z %s %s v %s"
+    IDS_INETTIMENEXTSYNC "Další synchronizace: %s v %s"
+    IDS_INETTIMESYNCING "Prosím čekejte, zatímco systém ReactOS synchronizuje čas s %s"
+    IDS_INETTIMEERROR "Při synchronizaci času s %s nastala chyba"
 END
index 701c66f..34df498 100644 (file)
@@ -20,9 +20,6 @@ IDC_WORLD BITMAP "resources/world.bmp"
 #ifdef LANGUAGE_BG_BG
     #include "lang/bg-BG.rc"
 #endif
-#ifdef LANGUAGE_CS_CZ
-    #include "lang/cs-CZ.rc"
-#endif
 #ifdef LANGUAGE_DA_DK
     #include "lang/da-DK.rc"
 #endif
@@ -78,6 +75,9 @@ IDC_WORLD BITMAP "resources/world.bmp"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_HE_IL
     #include "lang/he-IL.rc"
 #endif
diff --git a/dll/cpl/usrmgr/lang/cs-CZ.rc b/dll/cpl/usrmgr/lang/cs-CZ.rc
new file mode 100644 (file)
index 0000000..96d2228
--- /dev/null
@@ -0,0 +1,218 @@
+/* FILE:       dll/cpl/usrmgr/lang/cs-CZ.rc
+ * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
+ * UPDATED:    2014-04-21
+ */
+
+ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+
+/* Dialogs */
+
+IDD_USERS DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Uživatelé"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    CONTROL "", IDC_USERS_LIST, "SysListView32", LVS_REPORT | LVS_EDITLABELS | LVS_SINGLESEL |
+            LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 7, 238, 85, WS_EX_CLIENTEDGE
+    PUSHBUTTON "&Přidat...", IDC_USERS_ADD, 87, 98, 50, 14
+    PUSHBUTTON "&Odebrat", IDC_USERS_REMOVE, 141, 98, 50, 14
+    PUSHBUTTON "&Vlastnosti", IDC_USERS_PROPERTIES, 195, 98, 50, 14
+    AUTOCHECKBOX "Vyžadovat uživatelské jméno a heslo při spuštění sytému.", IDC_USERS_STARTUP_REQUIRE, 10, 118, 200, 14, WS_DISABLED
+    PUSHBUTTON "Reset Password", IDC_USERS_RESET, 165, 200, 80, 14, WS_DISABLED
+END
+
+IDD_GROUPS DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Skupiny"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    CONTROL "", IDC_GROUPS_LIST, "SysListView32", LVS_REPORT | LVS_EDITLABELS | LVS_SINGLESEL |
+            LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 7, 238, 85, WS_EX_CLIENTEDGE
+    PUSHBUTTON "&Přidat...", IDC_GROUPS_ADD, 87, 98, 50, 14
+    PUSHBUTTON "&Odebrat", IDC_GROUPS_REMOVE, 141, 98, 50, 14
+    PUSHBUTTON "&Vlastnosti", IDC_GROUPS_PROPERTIES, 195, 98, 50, 14
+END
+
+IDD_EXTRA DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Další"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "Tady zatím nic není", IDC_STATIC, 66, 90, 112, 8
+END
+
+IDD_USER_GENERAL DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Obecné"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "", IDC_USER_GENERAL_NAME, 7, 12, 112, 8
+    LTEXT "Celé jméno:", -1, 7, 46, 63, 8
+    EDITTEXT IDC_USER_GENERAL_FULL_NAME, 77, 43, 168, 13, ES_AUTOHSCROLL
+    LTEXT "Popis:", -1, 7, 64, 63, 8
+    EDITTEXT IDC_USER_GENERAL_DESCRIPTION, 77, 61, 168, 13, ES_AUTOHSCROLL
+    AUTOCHECKBOX "Uživatel musí změnit heslo po prvním přihlášení", IDC_USER_GENERAL_FORCE_CHANGE, 7, 82, 210, 10
+    AUTOCHECKBOX "Uživatel nemůže měnit heslo", IDC_USER_GENERAL_CANNOT_CHANGE, 7, 95, 210, 10
+    AUTOCHECKBOX "Platnost hesla je neomezená", IDC_USER_GENERAL_NEVER_EXPIRES, 7, 108, 210, 10
+    AUTOCHECKBOX "Účet je vypnutý", IDC_USER_GENERAL_DISABLED, 7, 121, 210, 10
+    AUTOCHECKBOX "Účet je zamčený", IDC_USER_GENERAL_LOCKED, 7, 134, 210, 10
+END
+
+IDD_USER_MEMBERSHIP DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Členství"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "Člen:", -1, 7, 7, 56, 8
+    CONTROL "", IDC_USER_MEMBERSHIP_LIST, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER |
+            LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 18, 238, 173, WS_EX_CLIENTEDGE
+    PUSHBUTTON "Přidat...", IDC_USER_MEMBERSHIP_ADD, 7, 197, 50, 14
+    PUSHBUTTON "Odebrat", IDC_USER_MEMBERSHIP_REMOVE, 61, 197, 50, 14, WS_DISABLED
+END
+
+IDD_USER_PROFILE DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Profil"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    GROUPBOX "Uživatelský profil", -1, 7, 7, 238, 54
+    LTEXT "Cesta k profilu:", -1, 16, 22, 55, 8
+    EDITTEXT IDC_USER_PROFILE_PATH, 78, 19, 160, 13, ES_AUTOHSCROLL
+    LTEXT "Přihlašovací skript:", -1, 16, 40, 55, 8
+    EDITTEXT IDC_USER_PROFILE_SCRIPT, 78, 37, 160, 13, ES_AUTOHSCROLL
+    GROUPBOX "Domovský adresář", -1, 7, 68, 238, 54
+    AUTORADIOBUTTON "Místní cesta:", IDC_USER_PROFILE_LOCAL, 16, 83, 60, 10
+    AUTORADIOBUTTON "Připojit:", IDC_USER_PROFILE_REMOTE, 16, 100, 60, 10
+    EDITTEXT IDC_USER_PROFILE_LOCAL_PATH, 78, 81, 160, 13, ES_AUTOHSCROLL
+    COMBOBOX IDC_USER_PROFILE_DRIVE, 78, 99, 26, 160, CBS_DROPDOWNLIST | CBS_SORT |
+             WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL
+    LTEXT "k:", -1, 112, 101, 12, 8
+    EDITTEXT IDC_USER_PROFILE_REMOTE_PATH, 130, 99, 108, 13, ES_AUTOHSCROLL
+END
+
+IDD_GROUP_GENERAL DIALOGEX 0, 0, 252, 223
+STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Obecné"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "", IDC_GROUP_GENERAL_NAME, 7, 12, 112, 8
+    LTEXT "Popis:", -1, 7, 45, 46, 8
+    EDITTEXT IDC_GROUP_GENERAL_DESCRIPTION, 65, 42, 180, 13, ES_AUTOHSCROLL
+    LTEXT "Členové:", -1, 7, 63, 45, 8
+    CONTROL "", IDC_GROUP_GENERAL_MEMBERS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER |
+            LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 74, 238, 117, WS_EX_CLIENTEDGE
+    PUSHBUTTON "Přidat...", IDC_GROUP_GENERAL_ADD, 7, 197, 50, 14
+    PUSHBUTTON "Odebrat", IDC_GROUP_GENERAL_REMOVE, 61, 197, 50, 14, WS_DISABLED
+END
+
+IDD_CHANGE_PASSWORD DIALOGEX 0, 0, 267, 74
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT
+CAPTION "Změna hesla"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    EDITTEXT IDC_EDIT_PASSWORD1, 107, 7, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD
+    RTEXT "Nové heslo:", -1, 7, 10, 96, 8
+    EDITTEXT IDC_EDIT_PASSWORD2, 107, 25, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD
+    RTEXT "Nové heslo znovu:", -1, 7, 28, 96, 8
+    DEFPUSHBUTTON "OK", IDOK, 156, 53, 50, 14
+    PUSHBUTTON "Storno", IDCANCEL, 210, 53, 50, 14
+END
+
+IDD_USER_NEW DIALOGEX 0, 0, 267, 200
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT
+CAPTION "Nový uživatel"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    EDITTEXT IDC_USER_NEW_NAME, 107, 7, 153, 14, ES_AUTOHSCROLL
+    RTEXT "Uživatelské jméno:", -1, 7, 10, 96, 8
+    EDITTEXT IDC_USER_NEW_FULL_NAME, 107, 25, 153, 14, ES_AUTOHSCROLL
+    RTEXT "Celé jméno uživatele:", -1, 7, 28, 96, 8
+    EDITTEXT IDC_USER_NEW_DESCRIPTION, 107, 43, 153, 14, ES_AUTOHSCROLL
+    RTEXT "Popis:", -1, 7, 46, 96, 8
+    EDITTEXT IDC_USER_NEW_PASSWORD1, 107, 67, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD
+    RTEXT "Heslo:", -1, 7, 70, 96, 8
+    EDITTEXT IDC_USER_NEW_PASSWORD2, 107, 85, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD
+    RTEXT "Heslo znovu:", -1, 7, 88, 96, 8
+    AUTOCHECKBOX "Uživatel musí změnit heslo po prvním přihlášení", IDC_USER_NEW_FORCE_CHANGE, 7, 109, 200, 10
+    AUTOCHECKBOX "Uživatel nemůže měnit heslo", IDC_USER_NEW_CANNOT_CHANGE, 7, 123, 200, 10, WS_DISABLED
+    AUTOCHECKBOX "Platnost hesla je neomezená", IDC_USER_NEW_NEVER_EXPIRES, 7, 137, 200, 10, WS_DISABLED
+    AUTOCHECKBOX "Účet je vypnutý", IDC_USER_NEW_DISABLED, 7, 151, 200, 10
+    DEFPUSHBUTTON "OK", IDOK, 156, 179, 50, 14, WS_DISABLED
+    PUSHBUTTON "Storno", IDCANCEL, 210, 179, 50, 14
+END
+
+IDD_GROUP_NEW DIALOGEX 0, 0, 267, 74
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT
+CAPTION "Nová skupina"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    EDITTEXT IDC_GROUP_NEW_NAME, 107, 7, 153, 14, ES_AUTOHSCROLL
+    RTEXT "Jméno skupiny:", -1, 7, 10, 96, 8
+    EDITTEXT IDC_GROUP_NEW_DESCRIPTION, 107, 25, 153, 14, ES_AUTOHSCROLL
+    RTEXT "Popis:", -1, 7, 28, 96, 8
+    DEFPUSHBUTTON "OK", IDOK, 156, 53, 50, 14, WS_DISABLED
+    PUSHBUTTON "Storno", IDCANCEL, 210, 53, 50, 14
+END
+
+IDD_USER_ADD_MEMBERSHIP DIALOGEX 0, 0, 252, 223
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT
+CAPTION "Členství ve skupině"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT "Člen:", -1, 7, 7, 56, 8
+    CONTROL "", IDC_USER_ADD_MEMBERSHIP_LIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS |
+            LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 18, 238, 173, WS_EX_CLIENTEDGE
+    DEFPUSHBUTTON "OK", IDOK, 141, 197, 50, 14
+    PUSHBUTTON "Storno", IDCANCEL, 195, 197, 50, 14
+END
+
+/* Menus */
+
+IDM_POPUP_GROUP MENU
+BEGIN
+    POPUP ""
+    BEGIN
+        MENUITEM "Nová skupina...", IDM_GROUP_NEW
+    END
+    POPUP ""
+    BEGIN
+        MENUITEM "Přidat člena", IDM_GROUP_ADD_MEMBER, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "Odstranit", IDM_GROUP_DELETE
+        MENUITEM "Přejmenovat", IDM_GROUP_RENAME
+        MENUITEM SEPARATOR
+        MENUITEM "Vlastnosti", IDM_GROUP_PROPERTIES
+    END
+END
+
+IDM_POPUP_USER MENU
+BEGIN
+    POPUP ""
+    BEGIN
+        MENUITEM "Nový uživatel...", IDM_USER_NEW
+    END
+    POPUP ""
+    BEGIN
+        MENUITEM "Změnit heslo", IDM_USER_CHANGE_PASSWORD
+        MENUITEM SEPARATOR
+        MENUITEM "Odstranit", IDM_USER_DELETE
+        MENUITEM "Přejmenovat", IDM_USER_RENAME
+        MENUITEM SEPARATOR
+        MENUITEM "Vlastnosti", IDM_USER_PROPERTIES
+    END
+END
+
+/* Strings */
+
+STRINGTABLE
+BEGIN
+    IDS_CPLNAME "Uživatelské účty"
+    IDS_CPLDESCRIPTION "Spravuje uživatele a skupiny."
+END
+
+STRINGTABLE
+BEGIN
+    IDS_NAME "Jméno"
+    IDS_FULLNAME "Celé jméno"
+    IDS_DESCRIPTION "Popis"
+END
index 0fe2763..2cecdc4 100644 (file)
@@ -37,6 +37,9 @@ IDI_GROUP ICON "resources/group.ico"
 /* UTF-8 */
 #pragma code_page(65001)
 
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
 #ifdef LANGUAGE_PL_PL
     #include "lang/pl-PL.rc"
 #endif
index 48968b3..84c1ed9 100644 (file)
@@ -607,9 +607,9 @@ static HRESULT WINAPI IEnumDMO_fnNext(
         hres = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE) szValue, &len); 
         if (ERROR_SUCCESS == hres)
        {
-            Names[count] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue) + 1);
+            Names[count] = HeapAlloc(GetProcessHeap(), 0, (strlenW(szValue) + 1) * sizeof(WCHAR));
            if (Names[count])
-                strcmpW(Names[count], szValue);
+                strcpyW(Names[count], szValue);
        }
         wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
         CLSIDFromString(szGuidKey, &pCLSID[count]);
index f3c8ddc..f651cf7 100644 (file)
@@ -803,7 +803,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE
             TRACE("dwChunkId: %.4s\n", (const char *)&pIndex->dwChunkId);
             if (pIndex->dwReserved[0])
                 TRACE("dwReserved[0]: %u\n", pIndex->dwReserved[0]);
-            if (pIndex->dwReserved[2])
+            if (pIndex->dwReserved[1])
                 TRACE("dwReserved[1]: %u\n", pIndex->dwReserved[1]);
             if (pIndex->dwReserved[2])
                 TRACE("dwReserved[2]: %u\n", pIndex->dwReserved[2]);
index afa15fd..d990093 100644 (file)
@@ -40,6 +40,7 @@ add_library(ntdll SHARED
     ${SOURCE}
     ${ntdll_asm}
     def/ntdll.rc
+    ${CMAKE_CURRENT_BINARY_DIR}/ntdll_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/ntdll.def)
 
 set_module_type(ntdll win32dll HOTPATCHABLE ENTRYPOINT 0)
index d22644b..0a779ec 100644 (file)
@@ -101,6 +101,9 @@ CsrAllocateCaptureBuffer(IN ULONG ArgumentCount,
     /* Align it to a 4-byte boundary */
     BufferSize = (BufferSize + 3) & ~3;
 
+    /* Add the size of the alignment padding for each argument */
+    BufferSize += ArgumentCount * 3;
+
     /* Allocate memory from the port heap */
     CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize);
     if (CaptureBuffer == NULL) return NULL;
index 4ed630d..c649d57 100644 (file)
 @ stdcall NtGetCurrentProcessorNumber() ; 5.2 and higher
 @ stdcall NtGetDevicePowerState(ptr ptr)
 @ stdcall NtGetPlugPlayEvent(long long ptr long)
-;@ stdcall NtGetTickCount()
+@ stdcall NtGetTickCount() RtlGetTickCount
 @ stdcall NtGetWriteWatch(long long ptr long ptr ptr ptr)
 @ stdcall NtImpersonateAnonymousToken(ptr)
 @ stdcall NtImpersonateClientOfPort(ptr ptr)
 @ stdcall ZwGetCurrentProcessorNumber()
 @ stdcall ZwGetDevicePowerState(ptr ptr)
 @ stdcall ZwGetPlugPlayEvent(long long ptr long)
-;@ stdcall ZwGetTickCount() NtGetTickCount
+@ stdcall ZwGetTickCount() RtlGetTickCount
 @ stdcall ZwGetWriteWatch(long long ptr long ptr ptr ptr) NtGetWriteWatch
 @ stdcall ZwImpersonateAnonymousToken(ptr)
 @ stdcall ZwImpersonateClientOfPort(ptr ptr) NtImpersonateClientOfPort
index 9ceb2b0..69d58f3 100644 (file)
@@ -613,4 +613,32 @@ RtlpSafeCopyMemory(
     return STATUS_SUCCESS;
 }
 
+/* FIXME: code duplication with kernel32/client/time.c */
+ULONG
+NTAPI
+RtlGetTickCount(VOID)
+{
+    ULARGE_INTEGER TickCount;
+
+#ifdef _WIN64
+    TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
+#else
+    while (TRUE)
+    {
+        TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
+        TickCount.LowPart = SharedUserData->TickCount.LowPart;
+
+        if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
+            break;
+
+        YieldProcessor();
+    }
+#endif
+
+    return (ULONG)((UInt32x32To64(TickCount.LowPart,
+                                  SharedUserData->TickCountMultiplier) >> 24) +
+                    UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
+                                  SharedUserData->TickCountMultiplier));
+}
+
 /* EOF */
index 1d7d6bb..580e31c 100644 (file)
@@ -23,6 +23,5 @@ add_library(atl SHARED ${SOURCE} rsrc.rc)
 set_module_type(atl win32dll)
 target_link_libraries(atl uuid wine)
 add_importlibs(atl oleaut32 ole32 user32 gdi32 advapi32 msvcrt kernel32 ntdll)
-add_dependencies(atl atl_atliface_header)
 add_pch(atl precomp.h SOURCE)
 add_cd_file(TARGET atl DESTINATION reactos/system32 FOR all)
index ec60708..73e5ca0 100644 (file)
@@ -5242,6 +5242,10 @@ TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam)
        newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem);
        break;
 
+    case VK_RETURN:
+        TREEVIEW_SendSimpleNotify(infoPtr, NM_RETURN);
+    break;
+    
     case VK_HOME:
        newSelection = infoPtr->root->firstChild;
        break;
index 8257c11..187b310 100644 (file)
@@ -179,6 +179,7 @@ HANDLE WINAPI IcmpCreateFile(VOID)
 
     icp=HeapAlloc(GetProcessHeap(), 0, sizeof(*icp));
     if (icp==NULL) {
+        closesocket(sid);
         SetLastError(IP_NO_RESOURCES);
         return INVALID_HANDLE_VALUE;
     }
index f514165..5399cd5 100644 (file)
@@ -41,7 +41,7 @@ static HRESULT WINAPI ShellUIHelper2_QueryInterface(IShellUIHelper2 *iface, REFI
     }else if(IsEqualGUID(&IID_IShellUIHelper, riid)) {
         TRACE("(%p)->(IID_IShellUIHelper %p)\n", This, ppv);
         *ppv = &This->IShellUIHelper2_iface;
-    }else if(IsEqualGUID(&IID_IShellUIHelper, riid)) {
+    }else if(IsEqualGUID(&IID_IShellUIHelper2, riid)) {
         TRACE("(%p)->(IID_IShellUIHelper2 %p)\n", This, ppv);
         *ppv = &This->IShellUIHelper2_iface;
     }else {
index 0f3bc30..84bcd6d 100644 (file)
@@ -2301,7 +2301,7 @@ CreateProcessInternalW(IN HANDLE hUserToken,
     BOOLEAN InJob, SaferNeeded, UseLargePages, HavePrivilege;
     BOOLEAN QuerySection, SkipSaferAndAppCompat;
     CONTEXT Context;
-    BASE_API_MESSAGE CsrMsg;
+    BASE_API_MESSAGE CsrMsg[2];
     PBASE_CREATE_PROCESS CreateProcessMsg;
     PCSR_CAPTURE_BUFFER CaptureBuffer;
     PVOID BaseAddress, PrivilegeState, RealTimePrivilegeState;
@@ -2431,8 +2431,8 @@ CreateProcessInternalW(IN HANDLE hUserToken,
     IsWowApp = FALSE;
 
     /* Set message structures */
-    CreateProcessMsg = &CsrMsg.Data.CreateProcessRequest;
-    CheckVdmMsg = &CsrMsg.Data.CheckVDMRequest;
+    CreateProcessMsg = &CsrMsg[0].Data.CreateProcessRequest;
+    CheckVdmMsg = &CsrMsg[1].Data.CheckVDMRequest;
 
     /* Clear the more complex structures by zeroing out their entire memory */
     RtlZeroMemory(&Context, sizeof(Context));
@@ -3197,7 +3197,7 @@ StartScan:
                     /* Pick which kind of WOW mode we want to run in */
                     VdmBinaryType = (dwCreationFlags &
                                      CREATE_SEPARATE_WOW_VDM) ?
-                                     BINARY_TYPE_WOW : BINARY_TYPE_SEPARATE_WOW;
+                                     BINARY_TYPE_SEPARATE_WOW : BINARY_TYPE_WOW;
 
                     /* Get all the VDM settings and current status */
                     Status = BaseCheckVDM(VdmBinaryType,
@@ -3205,7 +3205,7 @@ StartScan:
                                           lpCommandLine,
                                           lpCurrentDirectory,
                                           &VdmAnsiEnv,
-                                          &CsrMsg,
+                                          &CsrMsg[1],
                                           &VdmTask,
                                           dwCreationFlags,
                                           &StartupInfo,
@@ -3342,7 +3342,7 @@ StartScan:
                                       lpCommandLine,
                                       lpCurrentDirectory,
                                       &VdmAnsiEnv,
-                                      &CsrMsg,
+                                      &CsrMsg[1],
                                       &VdmTask,
                                       dwCreationFlags,
                                       &StartupInfo,
@@ -3966,6 +3966,8 @@ StartScan:
                                     &VdmWaitObject,
                                     VdmTask,
                                     VdmBinaryType);
+
+        if (!Result)
         {
             /* Bail out on failure */
             DPRINT1("Failed to update VDM with wait object\n");
@@ -4335,7 +4337,7 @@ StartScan:
     }
 
     /* We are finally ready to call CSRSS to tell it about our new process! */
-    CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg,
+    CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg[0],
                         CaptureBuffer,
                         CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX,
                                               BasepCreateProcess),
@@ -4349,12 +4351,12 @@ StartScan:
     }
 
     /* Check if CSRSS failed to accept ownership of the new Windows process */
-    if (!NT_SUCCESS(CsrMsg.Status))
+    if (!NT_SUCCESS(CsrMsg[0].Status))
     {
         /* Terminate the process and enter failure path with the CSRSS status */
         DPRINT1("Failed to tell csrss about new process\n");
-        BaseSetLastNTError(CsrMsg.Status);
-        NtTerminateProcess(ProcessHandle, CsrMsg.Status);
+        BaseSetLastNTError(CsrMsg[0].Status);
+        NtTerminateProcess(ProcessHandle, CsrMsg[0].Status);
         Result = FALSE;
         goto Quickie;
     }
index aee6d8a..abba55b 100644 (file)
@@ -446,6 +446,9 @@ GetTickCount(VOID)
 {
     ULARGE_INTEGER TickCount;
 
+#ifdef _WIN64
+    TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
+#else
     while (TRUE)
     {
         TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
@@ -456,6 +459,7 @@ GetTickCount(VOID)
 
         YieldProcessor();
     }
+#endif
 
     return (ULONG)((UInt32x32To64(TickCount.LowPart,
                                   SharedUserData->TickCountMultiplier) >> 24) +
index 3ff2c46..c37a3cf 100644 (file)
@@ -64,7 +64,7 @@ BaseIsDosApplication(IN PUNICODE_STRING PathName,
     return 0;
 }
 
-BOOL
+NTSTATUS
 WINAPI
 BaseCheckVDM(IN ULONG BinaryType,
              IN PCWCH ApplicationName,
@@ -77,9 +77,354 @@ BaseCheckVDM(IN ULONG BinaryType,
              IN LPSTARTUPINFOW StartupInfo,
              IN HANDLE hUserToken OPTIONAL)
 {
-    /* This is not supported */
-    UNIMPLEMENTED;
-    return FALSE;
+    NTSTATUS Status;
+    PBASE_CHECK_VDM CheckVdm = &ApiMessage->Data.CheckVDMRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    PWCHAR CurrentDir = NULL;
+    PWCHAR ShortAppName = NULL;
+    PWCHAR ShortCurrentDir = NULL;
+    ULONG Length;
+    PCHAR AnsiCmdLine = NULL;
+    PCHAR AnsiAppName = NULL;
+    PCHAR AnsiCurDirectory = NULL;
+    PCHAR AnsiDesktop = NULL;
+    PCHAR AnsiTitle = NULL;
+    PCHAR AnsiReserved = NULL;
+    STARTUPINFOA AnsiStartupInfo;
+    ULONG NumStrings = 5;
+
+    if (CurrentDirectory == NULL)
+    {
+        /* Allocate memory for the current directory path */
+        Length = GetCurrentDirectoryW(0, NULL);
+        CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                             HEAP_ZERO_MEMORY,
+                                             Length * sizeof(WCHAR));
+        if (CurrentDir == NULL)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto Cleanup;
+        }
+
+        /* Get the current directory */
+        GetCurrentDirectoryW(Length, CurrentDir);
+        CurrentDirectory = CurrentDir;
+    }
+
+    /* Calculate the size of the short application name */
+    Length = GetShortPathNameW(ApplicationName, NULL, 0);
+
+    /* Allocate memory for the short application name */
+    ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                           HEAP_ZERO_MEMORY,
+                                           Length * sizeof(WCHAR));
+    if (!ShortAppName)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Get the short application name */
+    if (!GetShortPathNameW(ApplicationName, ShortAppName, Length))
+    {
+        /* Try to determine which error occurred */
+        switch (GetLastError())
+        {
+            case ERROR_NOT_ENOUGH_MEMORY:
+            {
+                Status = STATUS_NO_MEMORY;
+                break;
+            }
+
+            case ERROR_INVALID_PARAMETER:
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            default:
+            {
+                Status = STATUS_OBJECT_PATH_INVALID;
+            }
+        }
+
+        goto Cleanup;
+    }
+
+    /* Calculate the size of the short current directory path */
+    Length = GetShortPathNameW(CurrentDirectory, NULL, 0);
+
+    /* Allocate memory for the short current directory path */
+    ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                              HEAP_ZERO_MEMORY,
+                                              Length * sizeof(WCHAR));
+    if (!ShortCurrentDir)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Get the short current directory path */
+    if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length))
+    {
+        /* Try to determine which error occurred */
+        switch (GetLastError())
+        {
+            case ERROR_NOT_ENOUGH_MEMORY:
+            {
+                Status = STATUS_NO_MEMORY;
+                break;
+            }
+
+            case ERROR_INVALID_PARAMETER:
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                break;
+            }
+
+            default:
+            {
+                Status = STATUS_OBJECT_PATH_INVALID;
+            }
+        }
+        goto Cleanup;
+    }
+
+    /* Setup the input parameters */
+    CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+    CheckVdm->BinaryType = BinaryType;
+    CheckVdm->CodePage = CP_ACP;
+    CheckVdm->dwCreationFlags = CreationFlags;
+    CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
+    CheckVdm->CmdLen = wcslen(CommandLine) + 1;
+    CheckVdm->AppLen = wcslen(ShortAppName) + 1;
+    CheckVdm->PifLen = 0; // TODO: PIF file support!
+    CheckVdm->CurDirectoryLen = wcslen(ShortCurrentDir) + 1;
+    CheckVdm->EnvLen = AnsiEnvironment->Length;
+    CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
+    CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
+    CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
+
+    if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
+    {
+        /* Set the standard handles */
+        CheckVdm->StdIn = StartupInfo->hStdInput;
+        CheckVdm->StdOut = StartupInfo->hStdOutput;
+        CheckVdm->StdErr = StartupInfo->hStdError;
+    }
+
+    /* Allocate memory for the ANSI strings */
+    AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen);
+    AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
+    AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
+    if (StartupInfo->lpDesktop) AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                                                     HEAP_ZERO_MEMORY,
+                                                                     CheckVdm->DesktopLen);
+    if (StartupInfo->lpTitle) AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                                                 HEAP_ZERO_MEMORY,
+                                                                 CheckVdm->TitleLen);
+    if (StartupInfo->lpReserved) AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+                                                                       HEAP_ZERO_MEMORY,
+                                                                       CheckVdm->ReservedLen);
+
+    if (!AnsiCmdLine
+        || !AnsiAppName
+        || !AnsiCurDirectory
+        || (StartupInfo->lpDesktop && !AnsiDesktop)
+        || (StartupInfo->lpTitle && !AnsiTitle)
+        || (StartupInfo->lpReserved && !AnsiReserved))
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Convert the command line into an ANSI string */
+    WideCharToMultiByte(CP_ACP,
+                        0,
+                        CommandLine,
+                        CheckVdm->CmdLen,
+                        AnsiCmdLine,
+                        CheckVdm->CmdLen,
+                        NULL,
+                        NULL);
+
+    /* Convert the short application name into an ANSI string */
+    WideCharToMultiByte(CP_ACP,
+                        0,
+                        ShortAppName,
+                        CheckVdm->AppLen,
+                        AnsiAppName,
+                        CheckVdm->AppLen,
+                        NULL,
+                        NULL);
+
+    /* Convert the short current directory path into an ANSI string */
+    WideCharToMultiByte(CP_ACP,
+                        0,
+                        ShortCurrentDir,
+                        CheckVdm->CurDirectoryLen,
+                        AnsiCurDirectory,
+                        CheckVdm->CurDirectoryLen,
+                        NULL,
+                        NULL);
+
+    if (StartupInfo->lpDesktop)
+    {
+        /* Convert the desktop name into an ANSI string */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            StartupInfo->lpDesktop,
+                            CheckVdm->DesktopLen,
+                            AnsiDesktop,
+                            CheckVdm->DesktopLen,
+                            NULL,
+                            NULL);
+        NumStrings++;
+    }
+
+    if (StartupInfo->lpTitle)
+    {
+        /* Convert the title into an ANSI string */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            StartupInfo->lpTitle,
+                            CheckVdm->TitleLen,
+                            AnsiTitle,
+                            CheckVdm->TitleLen,
+                            NULL,
+                            NULL);
+        NumStrings++;
+    }
+
+    if (StartupInfo->lpReserved)
+    {
+        /* Convert the reserved value into an ANSI string */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            StartupInfo->lpReserved,
+                            CheckVdm->ReservedLen,
+                            AnsiReserved,
+                            CheckVdm->ReservedLen,
+                            NULL,
+                            NULL);
+        NumStrings++;
+    }
+
+    /* Fill the ANSI startup info structure */
+    RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(STARTUPINFO));
+    AnsiStartupInfo.lpReserved = AnsiReserved;
+    AnsiStartupInfo.lpDesktop = AnsiDesktop;
+    AnsiStartupInfo.lpTitle = AnsiTitle;
+
+    /* Allocate the capture buffer */
+    CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
+                                             CheckVdm->CmdLen
+                                             + CheckVdm->AppLen
+                                             + CheckVdm->PifLen
+                                             + CheckVdm->CurDirectoryLen
+                                             + CheckVdm->DesktopLen
+                                             + CheckVdm->TitleLen
+                                             + CheckVdm->ReservedLen
+                                             + CheckVdm->EnvLen
+                                             + sizeof(STARTUPINFOA));
+    if (CaptureBuffer == NULL)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Capture the command line */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            AnsiCmdLine,
+                            CheckVdm->CmdLen,
+                            (PVOID*)&CheckVdm->CmdLine);
+
+    /* Capture the application name */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            AnsiAppName,
+                            CheckVdm->AppLen,
+                            (PVOID*)&CheckVdm->AppName);
+
+    CheckVdm->PifFile = NULL; // TODO: PIF file support!
+
+    /* Capture the current directory */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            AnsiCurDirectory,
+                            CheckVdm->CurDirectoryLen,
+                            (PVOID*)&CheckVdm->CurDirectory);
+
+    /* Capture the environment */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            AnsiEnvironment->Buffer,
+                            CheckVdm->EnvLen,
+                            (PVOID*)&CheckVdm->Env);
+
+    /* Capture the startup info structure */
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            &AnsiStartupInfo,
+                            sizeof(STARTUPINFOA),
+                            (PVOID*)&CheckVdm->StartupInfo);
+
+    if (StartupInfo->lpDesktop)
+    {
+        /* Capture the desktop name */
+        CsrCaptureMessageBuffer(CaptureBuffer,
+                                AnsiDesktop,
+                                CheckVdm->DesktopLen,
+                                (PVOID*)&CheckVdm->Desktop);
+    }
+    else CheckVdm->Desktop = NULL;
+
+    if (StartupInfo->lpTitle)
+    {
+        /* Capture the title */
+        CsrCaptureMessageBuffer(CaptureBuffer,
+                                AnsiTitle,
+                                CheckVdm->TitleLen,
+                                (PVOID*)&CheckVdm->Title);
+    }
+    else CheckVdm->Title = NULL;
+
+    if (StartupInfo->lpReserved)
+    {
+        /* Capture the reserved parameter */
+        CsrCaptureMessageBuffer(CaptureBuffer,
+                                AnsiReserved,
+                                CheckVdm->ReservedLen,
+                                (PVOID*)&CheckVdm->Reserved);
+    }
+    else CheckVdm->Reserved = NULL;
+
+    /* Send the message to CSRSS */
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)ApiMessage,
+                                 CaptureBuffer,
+                                 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckVDM),
+                                 sizeof(BASE_CHECK_VDM));
+
+    /* Write back the task ID */
+    *iTask = CheckVdm->iTask;
+
+Cleanup:
+
+    /* Free the ANSI strings */
+    if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
+    if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
+    if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
+    if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
+    if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
+    if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
+
+    /* Free the capture buffer */
+    CsrFreeCaptureBuffer(CaptureBuffer);
+
+    /* Free the short paths */
+    if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
+    if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
+
+    /* Free the current directory, if it was allocated here */
+    if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
+
+    return Status;
 }
 
 BOOL
@@ -89,10 +434,9 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex,
                    IN ULONG IndexInfo,
                    IN ULONG BinaryType)
 {
-#if 0 // Unimplemented in BASESRV
     NTSTATUS Status;
     BASE_API_MESSAGE ApiMessage;
-    PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVdmEntry;
+    PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
 
     /* Check what update is being sent */
     switch (UpdateIndex)
@@ -155,7 +499,7 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex,
         /* Return it to the caller */
         *WaitHandle = UpdateVdmEntry->WaitObjectForParent;
     }
-#endif
+
     /* We made it */
     return TRUE;
 }
@@ -165,11 +509,10 @@ WINAPI
 BaseCheckForVDM(IN HANDLE ProcessHandle,
                 OUT LPDWORD ExitCode)
 {
-#if 0 // Unimplemented in BASESRV
     NTSTATUS Status;
     EVENT_BASIC_INFORMATION EventBasicInfo;
     BASE_API_MESSAGE ApiMessage;
-    PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVdmExitCode;
+    PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
 
     /* It's VDM if the process is actually a wait handle (an event) */
     Status = NtQueryEvent(ProcessHandle,
@@ -192,7 +535,6 @@ BaseCheckForVDM(IN HANDLE ProcessHandle,
 
     /* Get the exit code from the reply */
     *ExitCode = GetVdmExitCode->ExitCode;
-#endif
     return TRUE;
 }
 
@@ -335,7 +677,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
     if (!lpEnvironment)
     {
         /* Nope, create one */
-        Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
+        Status = RtlCreateEnvironment(TRUE, &Environment);
         if (!NT_SUCCESS(Status)) goto Quickie;
     }
     else
@@ -376,6 +718,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
     p = NewEnvironment;
 
     /* FIXME: Code here */
+    DPRINT1("BaseCreateVDMEnvironment is half-plemented!\n");
 
     /* Terminate it */
     *p++ = UNICODE_NULL;
@@ -574,7 +917,7 @@ InternalGetBinaryType(HANDLE hFile)
       return BINARY_PE_EXE32;
     }
 
-    if(!memcmp(magic, "NE", 1))
+    if(!memcmp(magic, "NE", 2))
     {
       /* This is a Windows executable (NE) header.  This can
        * mean either a 16-bit OS/2 or a 16-bit Windows or even a
@@ -755,46 +1098,399 @@ CmdBatNotification (
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
-DWORD
+VOID
 WINAPI
-ExitVDM (
-    DWORD   Unknown0,
-    DWORD   Unknown1
-    )
+ExitVDM(BOOL IsWow, ULONG iWowTask)
 {
-    STUB;
-    return 0;
-}
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
+
+    /* Setup the input parameters */
+    ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+    ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
+    ExitVdm->WaitObjectForVDM = NULL;
 
+    /* Call CSRSS */
+    CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                        NULL,
+                        CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepExitVDM),
+                        sizeof(BASE_EXIT_VDM));
+
+    /* Close the returned wait object handle, if any */
+    if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
+    {
+        CloseHandle(ExitVdm->WaitObjectForVDM);
+    }
+}
 
 /*
- * @unimplemented
+ * @implemented
  */
-DWORD
+BOOL
 WINAPI
-GetNextVDMCommand (
-    DWORD   Unknown0
-    )
+GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
 {
-    STUB;
-    return 0;
+    NTSTATUS Status;
+    BOOL Result = FALSE;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
+    PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
+    PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+    ULONG NumStrings = 0;
+
+    if (CommandData != NULL)
+    {
+        if (CommandData->VDMState & (VDM_NOT_LOADED | VDM_NOT_READY | VDM_READY))
+        {
+            /* Clear the structure */
+            ZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
+
+            /* Setup the input parameters */
+            GetNextVdmCommand->iTask = CommandData->TaskId;
+            GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+            GetNextVdmCommand->CmdLen = CommandData->CmdLen;
+            GetNextVdmCommand->AppLen = CommandData->AppLen;
+            GetNextVdmCommand->PifLen = CommandData->PifLen;
+            GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
+            GetNextVdmCommand->EnvLen = CommandData->EnvLen;
+            GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
+            GetNextVdmCommand->TitleLen = CommandData->TitleLen;
+            GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
+            GetNextVdmCommand->VDMState = CommandData->VDMState;
+
+            /* Count the number of strings */
+            if (CommandData->CmdLen) NumStrings++;
+            if (CommandData->AppLen) NumStrings++;
+            if (CommandData->PifLen) NumStrings++;
+            if (CommandData->CurDirectoryLen) NumStrings++;
+            if (CommandData->EnvLen) NumStrings++;
+            if (CommandData->DesktopLen) NumStrings++;
+            if (CommandData->TitleLen) NumStrings++;
+            if (CommandData->ReservedLen) NumStrings++;
+
+            /* Allocate the capture buffer */
+            CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
+                                                     GetNextVdmCommand->CmdLen
+                                                     + GetNextVdmCommand->AppLen
+                                                     + GetNextVdmCommand->PifLen
+                                                     + GetNextVdmCommand->CurDirectoryLen
+                                                     + GetNextVdmCommand->EnvLen
+                                                     + GetNextVdmCommand->DesktopLen
+                                                     + GetNextVdmCommand->TitleLen
+                                                     + GetNextVdmCommand->ReservedLen
+                                                     + sizeof(STARTUPINFOA));
+            if (CaptureBuffer == NULL)
+            {
+                BaseSetLastNTError(STATUS_NO_MEMORY);
+                goto Cleanup;
+            }
+
+            /* Allocate memory for the startup info */
+            CsrAllocateMessagePointer(CaptureBuffer,
+                                      sizeof(STARTUPINFOA),
+                                      (PVOID*)&GetNextVdmCommand->StartupInfo);
+
+            if (CommandData->CmdLen)
+            {
+                /* Allocate memory for the command line */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->CmdLen,
+                                          (PVOID*)&GetNextVdmCommand->CmdLine);
+            }
+
+            if (CommandData->AppLen)
+            {
+                /* Allocate memory for the application name */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->AppLen,
+                                          (PVOID*)&GetNextVdmCommand->AppName);
+            }
+
+            if (CommandData->PifLen)
+            {
+                /* Allocate memory for the PIF file name */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->PifLen,
+                                          (PVOID*)&GetNextVdmCommand->PifFile);
+            }
+
+            if (CommandData->CurDirectoryLen)
+            {
+                /* Allocate memory for the current directory */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->CurDirectoryLen,
+                                          (PVOID*)&GetNextVdmCommand->CurDirectory);
+            }
+
+            if (CommandData->EnvLen)
+            {
+                /* Allocate memory for the environment */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->EnvLen,
+                                          (PVOID*)&GetNextVdmCommand->Env);
+            }
+
+            if (CommandData->DesktopLen)
+            {
+                /* Allocate memory for the desktop name */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->DesktopLen,
+                                          (PVOID*)&GetNextVdmCommand->Desktop);
+            }
+
+            if (CommandData->TitleLen)
+            {
+                /* Allocate memory for the title */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->TitleLen,
+                                          (PVOID*)&GetNextVdmCommand->Title);
+            }
+
+            if (CommandData->ReservedLen)
+            {
+                /* Allocate memory for the reserved parameter */
+                CsrAllocateMessagePointer(CaptureBuffer,
+                                          CommandData->ReservedLen,
+                                          (PVOID*)&GetNextVdmCommand->Reserved);
+            }
+
+            do
+            {
+                /* Call CSRSS */
+                Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                             CaptureBuffer,
+                                             CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand),
+                                             sizeof(BASE_GET_NEXT_VDM_COMMAND));
+
+                if (!NT_SUCCESS(Status))
+                {
+                    BaseSetLastNTError(Status);
+                    goto Cleanup;
+                }
+
+                /* Did we receive an event handle? */
+                if (GetNextVdmCommand->WaitObjectForVDM != NULL)
+                {
+                    /* Wait for the event to become signaled and try again */
+                    Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
+                                                   FALSE,
+                                                   NULL);
+                    if (!NT_SUCCESS(Status))
+                    {
+                        BaseSetLastNTError(Status);
+                        goto Cleanup;
+                    }
+
+                    /* Set the retry flag and clear the exit code */
+                    GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
+                    GetNextVdmCommand->ExitCode = 0;
+                }
+            }
+            while (GetNextVdmCommand->WaitObjectForVDM != NULL);
+
+            /* Write back the standard handles */
+            CommandData->StdIn = GetNextVdmCommand->StdIn;
+            CommandData->StdOut = GetNextVdmCommand->StdOut;
+            CommandData->StdErr = GetNextVdmCommand->StdErr;
+
+            /* Write back the startup info */
+            RtlMoveMemory(&CommandData->StartupInfo,
+                          GetNextVdmCommand->StartupInfo,
+                          sizeof(STARTUPINFOA));
+
+            if (CommandData->CmdLen)
+            {
+                /* Write back the command line */
+                RtlMoveMemory(CommandData->CmdLine,
+                              GetNextVdmCommand->CmdLine,
+                              GetNextVdmCommand->CmdLen);
+
+                /* Set the actual length */
+                CommandData->CmdLen = GetNextVdmCommand->CmdLen;
+            }
+
+            if (CommandData->AppLen)
+            {
+                /* Write back the application name */
+                RtlMoveMemory(CommandData->AppName,
+                              GetNextVdmCommand->AppName,
+                              GetNextVdmCommand->AppLen);
+
+                /* Set the actual length */
+                CommandData->AppLen = GetNextVdmCommand->AppLen;
+            }
+
+            if (CommandData->PifLen)
+            {
+                /* Write back the PIF file name */
+                RtlMoveMemory(CommandData->PifFile,
+                              GetNextVdmCommand->PifFile,
+                              GetNextVdmCommand->PifLen);
+
+                /* Set the actual length */
+                CommandData->PifLen = GetNextVdmCommand->PifLen;
+            }
+
+            if (CommandData->CurDirectoryLen)
+            {
+                /* Write back the current directory */
+                RtlMoveMemory(CommandData->CurDirectory,
+                              GetNextVdmCommand->CurDirectory,
+                              GetNextVdmCommand->CurDirectoryLen);
+
+                /* Set the actual length */
+                CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
+            }
+
+            if (CommandData->EnvLen)
+            {
+                /* Write back the environment */
+                RtlMoveMemory(CommandData->Env,
+                              GetNextVdmCommand->Env,
+                              GetNextVdmCommand->EnvLen);
+
+                /* Set the actual length */
+                CommandData->EnvLen = GetNextVdmCommand->EnvLen;
+            }
+
+            if (CommandData->DesktopLen)
+            {
+                /* Write back the desktop name */
+                RtlMoveMemory(CommandData->Desktop,
+                              GetNextVdmCommand->Desktop,
+                              GetNextVdmCommand->DesktopLen);
+
+                /* Set the actual length */
+                CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
+            }
+
+            if (CommandData->TitleLen)
+            {
+                /* Write back the title */
+                RtlMoveMemory(CommandData->Title,
+                              GetNextVdmCommand->Title,
+                              GetNextVdmCommand->TitleLen);
+
+                /* Set the actual length */
+                CommandData->TitleLen = GetNextVdmCommand->TitleLen;
+            }
+
+            if (CommandData->ReservedLen)
+            {
+                /* Write back the reserved parameter */
+                RtlMoveMemory(CommandData->Reserved,
+                              GetNextVdmCommand->Reserved,
+                              GetNextVdmCommand->ReservedLen);
+
+                /* Set the actual length */
+                CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
+            }
+
+            /* Write the remaining output parameters */
+            CommandData->TaskId = GetNextVdmCommand->iTask;
+            CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
+            CommandData->CodePage = GetNextVdmCommand->CodePage;
+            CommandData->ExitCode = GetNextVdmCommand->ExitCode;
+            CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
+            CommandData->VDMState = GetNextVdmCommand->VDMState;
+            CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
+
+            /* It was successful */
+            Result = TRUE;
+        }
+        else if ((CommandData->VDMState == VDM_INC_REENTER_COUNT)
+                 || (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
+        {
+            /* Setup the input parameters */
+            SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+            SetReenterCount->fIncDec = CommandData->VDMState;
+
+            /* Call CSRSS */
+            Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                         NULL,
+                                         CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount),
+                                         sizeof(BASE_SET_REENTER_COUNT));
+            BaseSetLastNTError(Status);
+            Result = NT_SUCCESS(Status);
+        }
+        else
+        {
+            BaseSetLastNTError(STATUS_INVALID_PARAMETER);
+            Result = FALSE;
+        }
+    }
+    else
+    {
+        /* Call CSRSS */
+        Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                     NULL,
+                                     CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM),
+                                     sizeof(BASE_IS_FIRST_VDM));
+        if (!NT_SUCCESS(Status))
+        {
+            BaseSetLastNTError(Status);
+            goto Cleanup;
+        }
+
+        /* Return TRUE if this is the first VDM */
+        Result = IsFirstVdm->FirstVDM;
+    }
+
+Cleanup:
+    if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer); 
+    return Result;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 DWORD
 WINAPI
-GetVDMCurrentDirectories (
-    DWORD   Unknown0,
-    DWORD   Unknown1
-    )
+GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
 {
-    STUB;
-    return 0;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+
+    /* Allocate the capture buffer */
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
+    if (CaptureBuffer == NULL)
+    {
+        BaseSetLastNTError(STATUS_NO_MEMORY);
+        return 0;
+    }
+
+    /* Setup the input parameters */
+    VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
+    CsrAllocateMessagePointer(CaptureBuffer,
+                              cchCurDirs,
+                              (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
+
+    /* Call CSRSS */
+    CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                        CaptureBuffer,
+                        CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetVDMCurDirs),
+                        sizeof(BASE_GETSET_VDM_CURDIRS));
+
+    /* Set the last error */
+    BaseSetLastNTError(ApiMessage.Status);
+
+    if (NT_SUCCESS(ApiMessage.Status))
+    {
+        /* Copy the result */
+        RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
+    }
+
+    /* Free the capture buffer */
+    CsrFreeCaptureBuffer(CaptureBuffer);
+
+    /* Return the size if it was successful, or if the buffer was too small */
+    return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
+           ? VDMCurrentDirsRequest->cchCurDirs : 0;
 }
 
 
@@ -851,17 +1547,44 @@ RegisterWowExec (
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 WINAPI
-SetVDMCurrentDirectories (
-    DWORD   Unknown0,
-    DWORD   Unknown1
-    )
+SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
 {
-    STUB;
-    return FALSE;
+    BASE_API_MESSAGE ApiMessage;
+    PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+
+    /* Allocate the capture buffer */
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
+    if (CaptureBuffer == NULL)
+    {
+        BaseSetLastNTError(STATUS_NO_MEMORY);
+        return FALSE;
+    }
+
+    /* Setup the input parameters */
+    VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
+    CsrCaptureMessageBuffer(CaptureBuffer,
+                            lpszzCurDirs,
+                            cchCurDirs,
+                            (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
+
+    /* Call CSRSS */
+    CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                        CaptureBuffer,
+                        CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetVDMCurDirs),
+                        sizeof(BASE_GETSET_VDM_CURDIRS));
+
+    /* Free the capture buffer */
+    CsrFreeCaptureBuffer(CaptureBuffer);
+
+    /* Set the last error */
+    BaseSetLastNTError(ApiMessage.Status);
+
+    return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
 }
 
 /*
@@ -882,12 +1605,15 @@ VDMConsoleOperation (
 /*
  * @unimplemented
  */
-DWORD
+BOOL
 WINAPI
-VDMOperationStarted (
-    DWORD   Unknown0
-    )
+VDMOperationStarted(IN ULONG Unknown0)
 {
-    STUB;
-    return 0;
+    DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
+
+    return
+    BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
+                       NULL,
+                       0,
+                       Unknown0);
 }
index 696597d..56e8726 100644 (file)
@@ -8,42 +8,6 @@
 
 #pragma once
 
-/* CONSTANTS ******************************************************************/
-
-typedef enum _VDM_ENTRY_CODE
-{
-    VdmEntryUndo,
-    VdmEntryUpdateProcess,
-    VdmEntryUpdateControlCHandler
-} VDM_ENTRY_CODE;
-
-//
-// Undo States
-//
-#define VDM_UNDO_PARTIAL    0x01
-#define VDM_UNDO_FULL       0x02
-#define VDM_UNDO_REUSE      0x04
-#define VDM_UNDO_COMPLETED  0x08
-
-//
-// Binary Types to share with VDM
-//
-#define BINARY_TYPE_EXE     0x01
-#define BINARY_TYPE_COM     0x02
-#define BINARY_TYPE_PIF     0x03
-#define BINARY_TYPE_DOS     0x10
-#define BINARY_TYPE_SEPARATE_WOW 0x20
-#define BINARY_TYPE_WOW     0x40
-#define BINARY_TYPE_WOW_EX  0x80
-
-//
-// VDM States
-//
-#define VDM_NOT_LOADED      0x01
-#define VDM_NOT_READY       0x02
-#define VDM_READY           0x04
-
-
 /* FUNCTION PROTOTYPES ********************************************************/
 
 BOOL
@@ -87,7 +51,7 @@ BaseCheckForVDM(
     OUT LPDWORD ExitCode
 );
 
-BOOL
+NTSTATUS
 WINAPI
 BaseCheckVDM(
     IN ULONG BinaryType,
index e544b0c..7228f83 100644 (file)
@@ -46,6 +46,7 @@
 #include <win/basemsg.h>
 #include <win/console.h>
 #include <win/conmsg.h>
+#include <win/vdm.h>
 
 /* DDK Driver Headers */
 #include <mountmgr.h>
index 7eb91a9..c1a73d1 100644 (file)
@@ -10,7 +10,7 @@
  *                  Samuel Serapión 
  */
 
-/* synched with wine 1.1.26 */
+/* Partly synched with Wine 1.7.17 */
 
 #include <k32.h>
 
@@ -178,11 +178,15 @@ BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid,
                                   ULONG ulId, const GUID* lpSearchGuid,
                                   PACTCTX_SECTION_KEYED_DATA pInfo)
 {
-  FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid),
-       ulId, debugstr_guid(lpSearchGuid), pInfo);
-  SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
-}
+    NTSTATUS status;
 
+    if ((status = RtlFindActivationContextSectionGuid(dwFlags, lpExtGuid, ulId, lpSearchGuid, pInfo)))
+    {
+        SetLastError(RtlNtStatusToDosError(status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
 
 /* EOF */
index d0de62d..012cd04 100644 (file)
@@ -7,7 +7,7 @@ add_definitions(
     -DCOM_NO_WINDOWS_H)
 
 include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
-add_idl_Headers(mshtml_nsiface_header nsiface.idl)
+add_idl_headers(mshtml_nsiface_header nsiface.idl)
 spec2def(mshtml.dll mshtml.spec)
 
 list(APPEND SOURCE
index 9d210be..90b65d8 100644 (file)
@@ -4,13 +4,23 @@
 .code
 
 MACRO(DEFINE_WRAPPER_FUNC, n, off, x)
+#ifdef _M_IX86
 PUBLIC _wrapper_func_&n&
 _wrapper_func_&n&:
-mov eax, [esp+4]
-mov eax, [eax+4]
-mov [esp+4], eax
-mov eax, [eax]
-jmp dword ptr [eax+off]
+    mov eax, [esp+4]
+    mov eax, [eax+4]
+    mov [esp+4], eax
+    mov eax, [eax]
+    jmp dword ptr [eax+off]
+#elif defined(_M_AMD64)
+PUBLIC wrapper_func_&n&
+wrapper_func_&n&:
+    mov rcx, [rcx+4]
+    mov rax, [rcx]
+    jmp qword ptr [rax+off]
+#else
+#error Unimplemented
+#endif
 ENDM
 
 DEFINE_WRAPPER_FUNC 3, 12, 24
index 1e5e067..8587c0d 100644 (file)
@@ -73,7 +73,7 @@
 # @ cdecl ??_U@YAPAXIHPBDH@Z(long long str long) MSVCRT_operator_new_dbg
 @ cdecl -arch=win32 ??_V@YAXPAX@Z(ptr) MSVCRT_operator_delete
 @ cdecl -arch=win64 ??_V@YAXPEAX@Z(ptr) MSVCRT_operator_delete
-@ cdecl -arch=win64 -norelay __uncaught_exception(ptr)
+@ cdecl -norelay __uncaught_exception(ptr)
 @ cdecl -arch=win32 -norelay ?_query_new_handler@@YAP6AHI@ZXZ() MSVCRT__query_new_handler
 @ cdecl -arch=win64 -norelay ?_query_new_handler@@YAP6AH_K@ZXZ() MSVCRT__query_new_handler
 @ cdecl ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode
 @ cdecl __threadhandle() kernel32.GetCurrentThread
 @ cdecl __threadid() kernel32.GetCurrentThreadId
 @ cdecl __toascii(long)
-@ cdecl __uncaught_exception()
 @ cdecl __unDName(ptr str long ptr ptr long)
 @ cdecl __unDNameEx(ptr str long ptr ptr ptr long)
 @ extern __unguarded_readlc_active
index f60ea9f..6608d8a 100644 (file)
@@ -307,7 +307,10 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
 {
   RpcConnection_np *npc = (RpcConnection_np *) Connection;
   static const char prefix[] = "\\\\";
-  static const char local[] =".";
+  static const char local[] = ".";
+  BOOL bUseLocalName = TRUE;
+  CHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
+  DWORD bufLen = sizeof(ComputerName)/sizeof(ComputerName[0]);
   RPC_STATUS r;
   LPSTR pname;
   INT size;
@@ -318,15 +321,39 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
 
   /* protseq=ncacn_np: named pipes */
   size = strlen(prefix);
+
   if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0)
+  {
+    bUseLocalName = TRUE;
     size += strlen(local);
+  }
   else
-    size += strlen(Connection->NetworkAddr);
+  {
+    if (GetComputerNameA(ComputerName, &bufLen))
+    {
+      if (stricmp(ComputerName, Connection->NetworkAddr) == 0)
+      {
+        bUseLocalName = TRUE;
+        size += strlen(local);
+      }
+      else
+      {
+        bUseLocalName = FALSE;
+        size += strlen(Connection->NetworkAddr);
+      }
+    }
+    else
+    {
+      bUseLocalName = FALSE;
+      size += strlen(Connection->NetworkAddr);
+    }
+  }
+
   size += strlen(Connection->Endpoint) + 1;
 
   pname = I_RpcAllocate(size);
   strcpy(pname, prefix);
-  if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0)
+  if (bUseLocalName)
     strcat(pname, local);
   else
     strcat(pname, Connection->NetworkAddr);
index 36b824b..098606b 100644 (file)
@@ -1,40 +1,16 @@
-diff -prudN e:\Wine\dlls\rpcrt4/epm_towers.h e:\reactos\dll\win32\rpcrt4/epm_towers.h
---- e:\Wine\dlls\rpcrt4/epm_towers.h   2011-09-16 23:22:37.031828000 +0100
-+++ e:\reactos\dll\win32\rpcrt4/epm_towers.h   2013-01-25 14:13:03.257632500 +0100
-@@ -19,7 +19,7 @@
-  *
-  */
+diff -prudN .\wine\dlls\rpcrt4/rpc_epmap.c .\reactos\dll\win32\rpcrt4/rpc_epmap.c
+--- .\wine\dlls\rpcrt4/rpc_epmap.c     2014-05-09 03:43:55.965035900 +0200
++++ .\reactos\dll\win32\rpcrt4/rpc_epmap.c     2013-12-27 18:11:56.421567500 +0100
+@@ -92,7 +80,7 @@ static BOOL start_rpcss(void)
+     lstrcatW( cmd, rpcss );
  
--#include "epm.h"
-+#include <epm_c.h>
+     Wow64DisableWow64FsRedirection( &redir );
+-    rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi );
++    rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
+     Wow64RevertWow64FsRedirection( redir );
  
- #define EPM_PROTOCOL_DNET_NSP         0x04
- #define EPM_PROTOCOL_OSI_TP4                  0x05
-diff -prudN e:\Wine\dlls\rpcrt4/ndr_marshall.c e:\reactos\dll\win32\rpcrt4/ndr_marshall.c
---- e:\Wine\dlls\rpcrt4/ndr_marshall.c 2012-04-02 20:39:58.270363100 +0100
-+++ e:\reactos\dll\win32\rpcrt4/ndr_marshall.c 2013-12-06 20:04:02.897835300 +0100
-@@ -1211,7 +1211,7 @@ static unsigned char * EmbeddedPointerMa
-         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
-         unsigned char *saved_memory = pStubMsg->Memory;
--        pStubMsg->Memory = pMemory;
-+        pStubMsg->Memory = membase;
-         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
-         pStubMsg->Memory = saved_memory;
-       }
-@@ -1365,7 +1365,7 @@ static void EmbeddedPointerBufferSize(PM
-         unsigned char *memptr = membase + *(const SHORT*)&info[0];
-         unsigned char *saved_memory = pStubMsg->Memory;
--        pStubMsg->Memory = pMemory;
-+        pStubMsg->Memory = membase;
-         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
-         pStubMsg->Memory = saved_memory;
-       }
-diff -prudN e:\Wine\dlls\rpcrt4/rpc_epmap.c e:\reactos\dll\win32\rpcrt4/rpc_epmap.c
---- e:\Wine\dlls\rpcrt4/rpc_epmap.c    2013-03-02 14:18:00.736492500 +0100
-+++ e:\reactos\dll\win32\rpcrt4/rpc_epmap.c    2013-12-06 20:28:21.361553600 +0100
-@@ -162,7 +169,7 @@ static RPC_STATUS get_epm_handle_server(
+     if (rslt)
+@@ -162,7 +150,7 @@ static RPC_STATUS get_epm_handle_server(
  
  static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
  {
@@ -43,10 +19,10 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_epmap.c e:\reactos\dll\win32\rpcrt4/rpc_epma
      {
          case EXCEPTION_ACCESS_VIOLATION:
          case EXCEPTION_ILLEGAL_INSTRUCTION:
-diff -prudN e:\Wine\dlls\rpcrt4/rpc_server.c e:\reactos\dll\win32\rpcrt4/rpc_server.c
---- e:\Wine\dlls\rpcrt4/rpc_server.c   2012-12-09 09:57:02.680308600 +0100
-+++ e:\reactos\dll\win32\rpcrt4/rpc_server.c   2013-12-06 23:50:04.564226300 +0100
-@@ -1075,8 +1077,10 @@ void RPCRT4_destroy_all_protseqs(void)
+diff -prudN .\wine\dlls\rpcrt4/rpc_server.c .\reactos\dll\win32\rpcrt4/rpc_server.c
+--- .\wine\dlls\rpcrt4/rpc_server.c    2014-05-09 03:43:55.973036400 +0200
++++ .\reactos\dll\win32\rpcrt4/rpc_server.c    2013-12-27 18:11:56.780368100 +0100
+@@ -1075,8 +1053,10 @@ void RPCRT4_destroy_all_protseqs(void)
      EnterCriticalSection(&server_cs);
      LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry)
      {
@@ -57,10 +33,10 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_server.c e:\reactos\dll\win32\rpcrt4/rpc_ser
          destroy_serverprotoseq(cps);
      }
      LeaveCriticalSection(&server_cs);
-diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_transport.c
---- e:\Wine\dlls\rpcrt4/rpc_transport.c        2013-12-06 20:10:59.302378700 +0100
-+++ e:\reactos\dll\win32\rpcrt4/rpc_transport.c        2013-12-06 23:39:38.664465200 +0100
-@@ -111,31 +115,41 @@ typedef struct _RpcConnection_np
+diff -prudN .\wine\dlls\rpcrt4/rpc_transport.c .\reactos\dll\win32\rpcrt4/rpc_transport.c
+--- .\wine\dlls\rpcrt4/rpc_transport.c 2014-05-09 03:43:55.977036600 +0200
++++ .\reactos\dll\win32\rpcrt4/rpc_transport.c 2014-05-09 03:10:59.250551600 +0200
+@@ -113,31 +91,41 @@ typedef struct _RpcConnection_np
  {
    RpcConnection common;
    HANDLE pipe;
@@ -109,26 +85,20 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
        case ERROR_NO_DATA_DETECTED:
            /* client has disconnected, retry */
            DisconnectNamedPipe( npc->pipe );
-@@ -148,28 +162,12 @@ static DWORD CALLBACK listen_thread(void
+@@ -150,6 +138,7 @@ static DWORD CALLBACK listen_thread(void
+   }
+ }
++#ifndef __REACTOS__
+ static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
+ {
+   if (npc->listening)
+@@ -165,13 +154,14 @@ static RPC_STATUS rpcrt4_conn_listen_pip
    }
+   return RPC_S_OK;
  }
++#endif
  
--static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
--{
--  if (npc->listening)
--    return RPC_S_OK;
--
--  npc->listening = TRUE;
--  npc->listen_thread = CreateThread(NULL, 0, listen_thread, npc, 0, NULL);
--  if (!npc->listen_thread)
--  {
--      npc->listening = FALSE;
--      ERR("Couldn't create listen thread (error was %d)\n", GetLastError());
--      return RPC_S_OUT_OF_RESOURCES;
--  }
--  return RPC_S_OK;
--}
--
  static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
  {
    RpcConnection_np *npc = (RpcConnection_np *) Connection;
@@ -139,7 +109,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
                                 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
                                 PIPE_UNLIMITED_INSTANCES,
                                 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
-@@ -181,6 +179,9 @@ static RPC_STATUS rpcrt4_conn_create_pip
+@@ -183,6 +173,9 @@ static RPC_STATUS rpcrt4_conn_create_pip
        return RPC_S_CANT_CREATE_ENDPOINT;
    }
  
@@ -149,7 +119,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    /* Note: we don't call ConnectNamedPipe here because it must be done in the
     * server thread as the thread must be alertable */
    return RPC_S_OK;
-@@ -227,6 +228,9 @@ static RPC_STATUS rpcrt4_conn_open_pipe(
+@@ -229,6 +222,9 @@ static RPC_STATUS rpcrt4_conn_open_pipe(
      if (err == ERROR_PIPE_BUSY) {
        TRACE("connection failed, error=%x\n", err);
        return RPC_S_SERVER_TOO_BUSY;
@@ -159,7 +129,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
      }
      if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
        err = GetLastError();
-@@ -236,9 +240,11 @@ static RPC_STATUS rpcrt4_conn_open_pipe(
+@@ -238,9 +234,11 @@ static RPC_STATUS rpcrt4_conn_open_pipe(
    }
  
    /* success */
@@ -171,13 +141,16 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    npc->pipe = pipe;
  
    return RPC_S_OK;
-@@ -306,18 +312,32 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc
+@@ -308,18 +306,59 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc
  static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
  {
    RpcConnection_np *npc = (RpcConnection_np *) Connection;
 -  static const char prefix[] = "\\\\.";
 +  static const char prefix[] = "\\\\";
-+  static const char local[] =".";
++  static const char local[] = ".";
++  BOOL bUseLocalName = TRUE;
++  CHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
++  DWORD bufLen = sizeof(ComputerName)/sizeof(ComputerName[0]);
    RPC_STATUS r;
    LPSTR pname;
 +  INT size;
@@ -191,15 +164,39 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
 -  strcat(strcpy(pname, prefix), Connection->Endpoint);
 -  r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
 +  size = strlen(prefix);
++
 +  if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0)
++  {
++    bUseLocalName = TRUE;
 +    size += strlen(local);
++  }
 +  else
-+    size += strlen(Connection->NetworkAddr);
++  {
++    if (GetComputerNameA(ComputerName, &bufLen))
++    {
++      if (stricmp(ComputerName, Connection->NetworkAddr) == 0)
++      {
++        bUseLocalName = TRUE;
++        size += strlen(local);
++      }
++      else
++      {
++        bUseLocalName = FALSE;
++        size += strlen(Connection->NetworkAddr);
++      }
++    }
++    else
++    {
++      bUseLocalName = FALSE;
++      size += strlen(Connection->NetworkAddr);
++    }
++  }
++
 +  size += strlen(Connection->Endpoint) + 1;
 +
 +  pname = I_RpcAllocate(size);
 +  strcpy(pname, prefix);
-+  if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0)
++  if (bUseLocalName)
 +    strcat(pname, local);
 +  else
 +    strcat(pname, Connection->NetworkAddr);
@@ -208,7 +205,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    I_RpcFree(pname);
  
    return r;
-@@ -366,9 +386,9 @@ static void rpcrt4_conn_np_handoff(RpcCo
+@@ -368,9 +407,9 @@ static void rpcrt4_conn_np_handoff(RpcCo
     * to the child, then reopen the server binding to continue listening */
  
    new_npc->pipe = old_npc->pipe;
@@ -220,7 +217,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    old_npc->listening = FALSE;
  }
  
-@@ -413,11 +433,17 @@ static int rpcrt4_conn_np_read(RpcConnec
+@@ -415,11 +454,17 @@ static int rpcrt4_conn_np_read(RpcConnec
    char *buf = buffer;
    BOOL ret = TRUE;
    unsigned int bytes_left = count;
@@ -239,7 +236,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
      if (!ret && GetLastError() == ERROR_MORE_DATA)
          ret = TRUE;
      if (!ret || !bytes_read)
-@@ -425,6 +451,7 @@ static int rpcrt4_conn_np_read(RpcConnec
+@@ -427,6 +472,7 @@ static int rpcrt4_conn_np_read(RpcConnec
      bytes_left -= bytes_read;
      buf += bytes_read;
    }
@@ -247,7 +244,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    return ret ? count : -1;
  }
  
-@@ -435,16 +462,23 @@ static int rpcrt4_conn_np_write(RpcConne
+@@ -437,16 +483,23 @@ static int rpcrt4_conn_np_write(RpcConne
    const char *buf = buffer;
    BOOL ret = TRUE;
    unsigned int bytes_left = count;
@@ -272,7 +269,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    return ret ? count : -1;
  }
  
-@@ -456,9 +490,9 @@ static int rpcrt4_conn_np_close(RpcConne
+@@ -458,9 +511,9 @@ static int rpcrt4_conn_np_close(RpcConne
      CloseHandle(npc->pipe);
      npc->pipe = 0;
    }
@@ -285,7 +282,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
    }
    return 0;
  }
-@@ -662,7 +696,7 @@ static void *rpcrt4_protseq_np_get_wait_
+@@ -664,7 +717,7 @@ static void *rpcrt4_protseq_np_get_wait_
      conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
      while (conn) {
          rpcrt4_conn_listen_pipe(conn);
@@ -294,7 +291,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
              (*count)++;
          conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
      }
-@@ -683,7 +717,7 @@ static void *rpcrt4_protseq_np_get_wait_
+@@ -685,7 +738,7 @@ static void *rpcrt4_protseq_np_get_wait_
      *count = 1;
      conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
      while (conn) {
@@ -303,7 +300,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
              (*count)++;
          conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
      }
-@@ -730,18 +764,12 @@ static int rpcrt4_protseq_np_wait_for_ne
+@@ -732,18 +785,12 @@ static int rpcrt4_protseq_np_wait_for_ne
          EnterCriticalSection(&protseq->cs);
          conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
          while (conn) {
@@ -324,9 +321,9 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_
          else
              ERR("failed to locate connection for handle %p\n", b_handle);
          LeaveCriticalSection(&protseq->cs);
-diff -prudN e:\Wine\dlls\rpcrt4/rpcrt4.spec e:\reactos\dll\win32\rpcrt4/rpcrt4.spec
---- e:\Wine\dlls\rpcrt4/rpcrt4.spec    2012-09-09 19:47:53.677232900 +0100
-+++ e:\reactos\dll\win32\rpcrt4/rpcrt4.spec    2013-12-06 20:29:09.804227500 +0100
+diff -prudN .\wine\dlls\rpcrt4/rpcrt4.spec .\reactos\dll\win32\rpcrt4/rpcrt4.spec
+--- .\wine\dlls\rpcrt4/rpcrt4.spec     2014-05-09 03:43:55.911032800 +0200
++++ .\reactos\dll\win32\rpcrt4/rpcrt4.spec     2013-12-07 15:35:15.331527800 +0100
 @@ -266,7 +266,7 @@
  @ stdcall NdrRangeUnmarshall(ptr ptr ptr long)
  @ stub NdrRpcSmClientAllocate
index 3d1af9f..5f0c736 100644 (file)
@@ -40,7 +40,7 @@ add_library(setupapi SHARED
 
 set_module_type(setupapi win32dll UNICODE)
 target_link_libraries(setupapi uuid wine ${PSEH_LIB})
-add_delay_importlibs(setupapi shell32)
+add_delay_importlibs(setupapi shell32 wintrust)
 
 add_importlibs(setupapi
     msvcrt
index 533820b..6bc03be 100644 (file)
@@ -2173,6 +2173,7 @@ BOOL WINAPI SetupCopyOEMInfA(
     PWSTR DestinationInfFileNameW = NULL;
     PWSTR DestinationInfFileNameComponentW = NULL;
     BOOL ret = FALSE;
+    DWORD size;
 
     TRACE("%s %s 0x%lx 0x%lx %p 0%lu %p %p\n",
         SourceInfFileName, OEMSourceMediaLocation, OEMSourceMediaType,
@@ -2204,11 +2205,14 @@ BOOL WINAPI SetupCopyOEMInfA(
             CopyStyle,
             DestinationInfFileNameW,
             DestinationInfFileNameSize,
-            RequiredSize,
+            &size,
             DestinationInfFileNameComponent ? &DestinationInfFileNameComponentW : NULL);
         if (!ret)
+        {
+            if (RequiredSize) *RequiredSize = size;
             goto cleanup;
-
+        }
+            
         if (DestinationInfFileNameSize != 0)
         {
             if (WideCharToMultiByte(CP_ACP, 0, DestinationInfFileNameW, -1,
index cca5891..138dcae 100644 (file)
@@ -1217,6 +1217,34 @@ DWORD WINAPI InstallCatalog( LPCSTR catalog, LPCSTR basename, LPSTR fullname )
     return 0;
 }
 
+/***********************************************************************
+ *      pSetupInstallCatalog  (SETUPAPI.@)
+ */
+DWORD WINAPI pSetupInstallCatalog( LPCWSTR catalog, LPCWSTR basename, LPWSTR fullname )
+{
+    HCATADMIN admin;
+    HCATINFO cat;
+
+    TRACE ("%s, %s, %p\n", debugstr_w(catalog), debugstr_w(basename), fullname);
+
+    if (!CryptCATAdminAcquireContext(&admin,NULL,0))
+        return GetLastError();
+
+    if (!(cat = CryptCATAdminAddCatalog( admin, (PWSTR)catalog, (PWSTR)basename, 0 )))
+    {
+        DWORD rc = GetLastError();
+        CryptCATAdminReleaseContext(admin, 0);
+        return rc;
+    }
+    CryptCATAdminReleaseCatalogContext(admin, cat, 0);
+    CryptCATAdminReleaseContext(admin,0);
+
+    if (fullname)
+        FIXME("not returning full installed catalog path\n");
+
+    return NO_ERROR;
+}
+
 static UINT detect_compression_type( LPCWSTR file )
 {
     DWORD size;
@@ -1536,26 +1564,29 @@ static DWORD decompress_file_lz( LPCWSTR source, LPCWSTR target )
     return ret;
 }
 
+struct callback_context
+{
+    BOOL has_extracted;
+    LPCWSTR target;
+};
+
 static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 )
 {
+    struct callback_context *context_info = context;
     FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1;
 
     switch (notification)
     {
     case SPFILENOTIFY_FILEINCABINET:
     {
-        LPCWSTR filename, targetname = context;
-        WCHAR *p;
-
-        if ((p = strrchrW( targetname, '\\' ))) filename = p + 1;
-        else filename = targetname;
+        if (context_info->has_extracted)
+            return FILEOP_ABORT;
 
-        if (!lstrcmpiW( filename, info->NameInCabinet ))
-        {
-            strcpyW( info->FullTargetName, targetname );
-            return FILEOP_DOIT;
-        }
-        return FILEOP_SKIP;
+        TRACE("Requesting extraction of cabinet file %s\n",
+              wine_dbgstr_w(info->NameInCabinet));
+        strcpyW( info->FullTargetName, context_info->target );
+        context_info->has_extracted = TRUE;
+        return FILEOP_DOIT;
     }
     default: return NO_ERROR;
     }
@@ -1563,9 +1594,10 @@ static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notificati
 
 static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target )
 {
+    struct callback_context context = {0, target};
     BOOL ret;
 
-    ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, (PVOID)target );
+    ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, &context );
 
     if (ret) return ERROR_SUCCESS;
     else return GetLastError();
@@ -1578,7 +1610,7 @@ static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target )
  */
 DWORD WINAPI SetupDecompressOrCopyFileA( PCSTR source, PCSTR target, PUINT type )
 {
-    DWORD ret = FALSE;
+    DWORD ret = 0;
     WCHAR *sourceW = NULL, *targetW = NULL;
 
     if (source && !(sourceW = pSetupMultiByteToUnicode( source, CP_ACP ))) return FALSE;
index 81f2125..2a6ad8d 100644 (file)
 @ stub pSetupHandleFailedVerification
 @ stub pSetupInfCacheBuild
 @ stub pSetupInfIsFromOemLocation
-@ stub pSetupInstallCatalog
+@ stdcall pSetupInstallCatalog(wstr wstr ptr)
 @ stub pSetupInstallStopEx
 @ stdcall pSetupIsGuidNull(ptr)
 @ stub pSetupIsLocalSystem
index 53db948..80a818a 100644 (file)
@@ -37,6 +37,8 @@
 #include <regstr.h>
 #include <sddl.h>
 #include <setupapi.h>
+#include <softpub.h>
+#include <mscat.h>
 #include <shlobj.h>
 #include <wine/unicode.h>
 #define NTOS_MODE_USER
index 47ec5b6..cf0c9cf 100644 (file)
@@ -852,9 +852,14 @@ HRESULT WINAPI CControlPanelFolder::ExecuteFromIdList(LPCITEMIDLIST pidl)
     }
 
     /* Build control panel applet cmd
-       Note: we passes applet name to Control_RunDLL to distinguish between applets in one .cpl file */
+       Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */
     WCHAR wszCmd[2*MAX_PATH];
-    StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%hs\"", pCPanel->szName, pCPanel->szName + pCPanel->offsDispName);
+    WCHAR wszAppletName[MAX_PATH];
+
+    if(!MultiByteToWideChar(CP_ACP, 0, pCPanel->szName + pCPanel->offsDispName, -1, wszAppletName, MAX_PATH))
+        return E_FAIL;
+
+    StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%ls\"", pCPanel->szName, wszAppletName);
 
     /* Start the applet */
     TRACE("Run cpl %ls\n", wszCmd);
index d653e61..b3f7b93 100644 (file)
@@ -1,6 +1,6 @@
 /* FILE:       dll/win32/shell32/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2013-06-01
+ * UPDATED:    2014-04-25
  * THANKS TO:  navaraf, who translated major part of this file
  */
 
@@ -764,7 +764,7 @@ BEGIN
     IDS_SYS_FILE "Systémový soubor"
 
     IDS_OPEN_VERB "Otevřít"
-    IDS_EXPLORE_VERB "Explore"
+    IDS_EXPLORE_VERB "Prozkoumat"
     IDS_RUNAS_VERB "Spustit jako "
     IDS_EDIT_VERB "Upravit"
     IDS_FIND_VERB "Najít"
index 8e022a1..b1614e3 100644 (file)
@@ -450,16 +450,14 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
     startup.cb = sizeof(STARTUPINFOW);
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = psei->nShow;
+    dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
+   if (psei->fMask & SEE_MASK_NO_CONSOLE)
+        dwCreationFlags |= CREATE_NEW_CONSOLE;    
     startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) ? psei->lpClass : NULL);
 
     if (psei->fMask & SEE_MASK_HASLINKNAME)
         startup.dwFlags |= STARTF_TITLEISLINKNAME;
 
-    dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
-
-    if (psei->fMask & SEE_MASK_NO_CONSOLE)
-        dwCreationFlags |= CREATE_NEW_CONSOLE;
-
     if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
                        lpDirectory, &startup, &info))
     {
@@ -703,7 +701,13 @@ static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOpera
         lpFile = xlpFile;
         /* Hey, isn't this value ignored?  Why make this call?  Shouldn't we return here?  --dank*/
     }
-
+    else if (lpPath && SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
+    {
+        TRACE("SearchPathW returned non-zero\n");
+        lpFile = xlpFile;
+        /* The file was found in one of the directories in the system-wide search path */
+    }
+    
     attribs = GetFileAttributesW(lpFile);
     if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY))
     {
index 46eb8d9..c0589ac 100644 (file)
@@ -3515,7 +3515,7 @@ BOOL WINAPI PathRelativePathToW(LPWSTR lpszPath, LPCWSTR lpszFrom, DWORD dwAttrF
 
   if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY))
     PathRemoveFileSpecW(szFrom);
-  if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY))
+  if(!(dwAttrTo & FILE_ATTRIBUTE_DIRECTORY))
     PathRemoveFileSpecW(szTo);
 
   /* Paths can only be relative if they have a common root */
index f94b970..f9eb3a7 100644 (file)
@@ -1,6 +1,6 @@
 /* FILE:       dll/win32/syssetup/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2009-08-02
+ * UPDATED:    2014-04-21
  * THANKS TO:  Filip Navara and Kamil Hornicek, who translated major part of this file
  */
 
@@ -12,7 +12,7 @@ CAPTION "ReactOS Instalátor"
 FONT 8, "MS Shell Dlg"
 BEGIN
     LTEXT "Vítejte v průvodci instalace systému ReactOS.", IDC_WELCOMETITLE, 115, 9, 189, 31
-    LTEXT "Tento průvodce nainstaluje systém ReactOS na Váš počítač. Průvodce potřebuje získat některé informace o Vás a Vašem počítači aby mohl systém správně nastavit.", IDC_STATIC, 115, 50, 189, 100
+    LTEXT "Tento průvodce nainstaluje systém ReactOS na Váš počítač. Průvodce potřebuje získat některé informace o Vás a Vašem počítači, aby mohl systém správně nastavit.", IDC_STATIC, 115, 50, 189, 100
     LTEXT "Kliknutím na Další pokračujte v instalaci.", IDC_STATIC, 115, 160, 189, 31
 END
 
@@ -155,7 +155,7 @@ BEGIN
     IDS_TIMEOUT "Vypršel časový limit registrace"
     IDS_REASON_UNKNOWN ""
     /*
-     * ATTENTION: 
+     * ATTENTION:
      *   If you translate the administator account name, keep IDS_ADMINISTRATOR_NAME and
      *   samsrv.dll:IDS_USER_ADMINISTRATOR_NAME synchronized.
      *   Also check the IDD_COMPUTERPAGE dialog.
index 2837900..bb37a3d 100644 (file)
@@ -38,7 +38,7 @@ KdpSendBuffer(
  * \brief Receives data from the KD port and fills a buffer.
  * \param Buffer Pointer to a buffer that receives the data.
  * \param Size Size of data to receive in bytes.
- * \return KDP_PACKET_RECEIVED if successful. 
+ * \return KDP_PACKET_RECEIVED if successful.
  *         KDP_PACKET_TIMEOUT if the receice timed out.
  */
 KDP_STATUS
@@ -69,7 +69,7 @@ KdpReceiveBuffer(
  * \name KdpReceivePacketLeader
  * \brief Receives a packet leadr from the KD port.
  * \param PacketLeader Pointer to an ULONG that receives the packet leader.
- * \return KDP_PACKET_RECEIVED if successful. 
+ * \return KDP_PACKET_RECEIVED if successful.
  *         KDP_PACKET_TIMEOUT if the receive timed out.
  *         KDP_PACKET_RESEND if a breakin byte was detected.
  */
@@ -141,7 +141,7 @@ KdpReceivePacketLeader(
     while (Index < 4);
 
     /* Enable the debugger */
-    KdDebuggerNotPresent = FALSE;
+    KD_DEBUGGER_NOT_PRESENT = FALSE;
     SharedUserData->KdDebuggerEnabled |= 0x00000002;
 
     /* Return the received packet leader */
index f34aa9a..337c521 100644 (file)
@@ -14,7 +14,7 @@
 
 NTSTATUS
 NTAPI
-BatteryIoctl(IN ULONG IoControlCode, 
+BatteryIoctl(IN ULONG IoControlCode,
              IN PDEVICE_OBJECT DeviceObject,
              IN PVOID InputBuffer,
              IN ULONG InputBufferLength,
@@ -50,11 +50,11 @@ BatteryIoctl(IN ULONG IoControlCode,
             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
             Status = IoStatusBlock.Status;
         }
-        
+
         /* Print failure */
         if (!(NT_SUCCESS(Status)) && (CompBattDebug & 8))
             DbgPrint("BatteryIoctl: Irp failed - %x\n", Status);
-        
+
         /* Done */
         if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING BatteryIoctl\n");
     }
@@ -64,7 +64,7 @@ BatteryIoctl(IN ULONG IoControlCode,
         if (CompBattDebug & 8) DbgPrint("BatteryIoctl: couldn't create Irp\n");
         Status = STATUS_INSUFFICIENT_RESOURCES;
     }
-    
+
     /* Return status */
     return Status;
 }
@@ -82,7 +82,7 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName,
     PFILE_OBJECT LocalFileObject;
     HANDLE DeviceHandle;
     PAGED_CODE();
-    
+
     /* Open a file object handle to the device */
     InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
     Status = ZwCreateFile(&DeviceHandle,
@@ -101,7 +101,7 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName,
         /* Reference the file object */
         Status = ObReferenceObjectByHandle(DeviceHandle,
                                            0,
-                                           IoFileObjectType,
+                                           *IoFileObjectType,
                                            KernelMode,
                                            (PVOID)&LocalFileObject,
                                            NULL);
@@ -111,11 +111,11 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName,
             *FileObject = LocalFileObject;
             *DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
         }
-      
+
         /* Close the handle */
         ZwClose(DeviceHandle);
     }
-    
+
     /* Return status */
     return Status;
 }
index 392ad0f..1d1168a 100644 (file)
@@ -31,11 +31,13 @@ KsecGenRandom(
     PVOID Buffer,
     SIZE_T Length)
 {
+    LARGE_INTEGER TickCount;
     ULONG i, RandomValue;
     PULONG P;
 
     /* Try to generate a more random seed */
-    KsecRandomSeed ^= _rotl(KeTickCount.LowPart, (KsecRandomSeed % 23));
+    KeQueryTickCount(&TickCount);
+    KsecRandomSeed ^= _rotl(TickCount.LowPart, (KsecRandomSeed % 23));
 
     P = Buffer;
     for (i = 0; i < Length / sizeof(ULONG); i++)
@@ -94,7 +96,7 @@ KsecGatherEntropyData(
     PTEB Teb;
     PPEB Peb;
     PWSTR String;
-    ULONG ReturnLength;
+    SIZE_T ReturnLength;
     NTSTATUS Status;
 
     /* Query some generic values */
@@ -125,7 +127,7 @@ KsecGatherEntropyData(
             /* Update the MD4 context from the environment data */
             MD4Update(&Md4Context,
                       (PUCHAR)Peb->ProcessParameters->Environment,
-                      (PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment);
+                      (ULONG)((PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment));
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
index c86df7a..4ee8096 100644 (file)
@@ -1552,7 +1552,7 @@ MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension,
     }
 
     /* Reference it */
-    Status = ObReferenceObjectByHandle(Handle, 0, IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(Handle, 0, *IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         goto Cleanup;
index 26aa2cf..575a5a4 100644 (file)
@@ -1140,7 +1140,7 @@ KsSynchronousIoControlDevice(
         if (Status)
         {
             /* store bytes returned */
-            *BytesReturned = IoStatusBlock.Information;
+            *BytesReturned = (ULONG)IoStatusBlock.Information;
             /* return status */
             return IoStatusBlock.Status;
         }
@@ -1181,7 +1181,7 @@ KsSynchronousIoControlDevice(
         Status = IoStatusBlock.Status;
     }
 
-    *BytesReturned = IoStatusBlock.Information;
+    *BytesReturned = (ULONG)IoStatusBlock.Information;
     return Status;
 }
 
@@ -1716,8 +1716,8 @@ KsCompletePendingRequest(
         return;
     }
 
-    /* FIXME 
-     * delete object / device header 
+    /* FIXME
+     * delete object / device header
      * remove dead pin / filter instance
      */
     UNIMPLEMENTED
@@ -1782,7 +1782,7 @@ KspDeviceSetGetBusData(
     Status = IoCallDriver(DeviceObject, Irp);
 
     /* is the request still pending */
-    if (Status == STATUS_PENDING) 
+    if (Status == STATUS_PENDING)
     {
         /* have a nap */
         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
@@ -1887,7 +1887,7 @@ KsGetNextSibling(
     /* get the basic header */
     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
 
-    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 
+    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
            BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
 
     return (PVOID)BasicHeader->Next.Pin;
@@ -2128,7 +2128,7 @@ KspMergePropertySet(
     PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem;
     NTSTATUS Status;
 
-    // max properties 
+    // max properties
     PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount;
 
     // allocate items
@@ -2518,7 +2518,7 @@ KsRegisterAggregatedClientUnknown(
     PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
 
     /* sanity check */
-    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 
+    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
            BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
 
     if (BasicHeader->ClientAggregate)
index f851957..96f0146 100644 (file)
@@ -87,7 +87,7 @@ NTSTATUS
 KspEnableEvent(
     IN  PIRP Irp,
     IN  ULONG EventSetsCount,
-    IN  PKSEVENT_SET EventSet,
+    IN  const KSEVENT_SET* EventSet,
     IN  OUT PLIST_ENTRY EventsList OPTIONAL,
     IN  KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
     IN  PVOID EventsLock OPTIONAL,
@@ -99,7 +99,7 @@ KspEnableEvent(
     KSEVENT Event;
     PKSEVENT_ITEM EventItem, FoundEventItem;
     PKSEVENTDATA EventData;
-    PKSEVENT_SET FoundEventSet;
+    const KSEVENT_SET *FoundEventSet;
     PKSEVENT_ENTRY EventEntry;
     ULONG Index, SubIndex, Size;
     PVOID Object;
@@ -234,7 +234,7 @@ KspEnableEvent(
         if (EventData->NotificationType == KSEVENTF_SEMAPHORE_HANDLE)
         {
             /* get semaphore object handle */
-            Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL);
+            Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, *ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL);
 
             if (!NT_SUCCESS(Status))
             {
@@ -245,7 +245,7 @@ KspEnableEvent(
         else if (EventData->NotificationType == KSEVENTF_EVENT_HANDLE)
         {
             /* get event object handle */
-            Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, ExEventObjectType, Irp->RequestorMode, &Object, NULL);
+            Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode, &Object, NULL);
 
             if (!NT_SUCCESS(Status))
             {
@@ -270,7 +270,7 @@ KspEnableEvent(
             /* invalid type requested */
             return STATUS_INVALID_PARAMETER;
         }
-    } 
+    }
 
 
     /* calculate request size */
@@ -398,18 +398,19 @@ KsEnableEvent(
 /*
     @implemented
 */
+_IRQL_requires_max_(PASSIVE_LEVEL)
 KSDDKAPI
 NTSTATUS
 NTAPI
 KsEnableEventWithAllocator(
-    IN  PIRP Irp,
-    IN  ULONG EventSetsCount,
-    IN  PKSEVENT_SET EventSet,
-    IN  OUT PLIST_ENTRY EventsList OPTIONAL,
-    IN  KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
-    IN  PVOID EventsLock OPTIONAL,
-    IN  PFNKSALLOCATOR Allocator OPTIONAL,
-    IN  ULONG EventItemSize OPTIONAL)
+    _In_ PIRP Irp,
+    _In_ ULONG EventSetsCount,
+    _In_reads_(EventSetsCount) const KSEVENT_SET* EventSet,
+    _Inout_opt_ PLIST_ENTRY EventsList,
+    _In_opt_ KSEVENTS_LOCKTYPE EventsFlags,
+    _In_opt_ PVOID EventsLock,
+    _In_opt_ PFNKSALLOCATOR Allocator,
+    _In_opt_ ULONG EventItemSize)
 {
     return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, Allocator, EventItemSize);
 }
index 83d57b2..8a930dd 100644 (file)
@@ -175,7 +175,7 @@ NTSTATUS
 KspEnableEvent(
     IN  PIRP Irp,
     IN  ULONG EventSetsCount,
-    IN  PKSEVENT_SET EventSet,
+    IN  const KSEVENT_SET* EventSet,
     IN  OUT PLIST_ENTRY EventsList OPTIONAL,
     IN  KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
     IN  PVOID EventsLock OPTIONAL,
index 65b49c6..e58a6ff 100644 (file)
@@ -147,7 +147,7 @@ KspMethodHandlerWithAllocator(
             if (Allocator)
             {
                 /* allocate the requested amount */
-                Status = Allocator(Irp, Irp->IoStatus.Information, FALSE);
+                Status = Allocator(Irp, (ULONG)Irp->IoStatus.Information, FALSE);
 
                 /* check if the block was allocated */
                 if (!NT_SUCCESS(Status))
@@ -189,13 +189,14 @@ KspMethodHandlerWithAllocator(
 /*
     @implemented
 */
+_IRQL_requires_max_(PASSIVE_LEVEL)
 KSDDKAPI
 NTSTATUS
 NTAPI
 KsMethodHandler(
-    IN  PIRP Irp,
-    IN  ULONG MethodSetsCount,
-    IN  PKSMETHOD_SET MethodSet)
+    _In_ PIRP Irp,
+    _In_ ULONG MethodSetsCount,
+    _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet)
 {
     return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, NULL, 0);
 }
@@ -203,15 +204,16 @@ KsMethodHandler(
 /*
     @implemented
 */
+_IRQL_requires_max_(PASSIVE_LEVEL)
 KSDDKAPI
 NTSTATUS
 NTAPI
 KsMethodHandlerWithAllocator(
-    IN  PIRP Irp,
-    IN  ULONG MethodSetsCount,
-    IN  PKSMETHOD_SET MethodSet,
-    IN  PFNKSALLOCATOR Allocator OPTIONAL,
-    IN  ULONG MethodItemSize OPTIONAL)
+    _In_ PIRP Irp,
+    _In_ ULONG MethodSetsCount,
+    _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet,
+    _In_opt_ PFNKSALLOCATOR Allocator,
+    _In_opt_ ULONG MethodItemSize)
 {
     return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, Allocator, MethodItemSize);
 }
index 1aa2b7d..9ad2cc5 100644 (file)
@@ -103,7 +103,7 @@ KspCopyCreateRequest(
     OUT PVOID * Result)
 {
     PIO_STACK_LOCATION IoStack;
-    ULONG ObjectLength, ParametersLength;
+    SIZE_T ObjectLength, ParametersLength;
     PVOID Buffer;
 
     /* get current irp stack */
@@ -129,7 +129,7 @@ KspCopyCreateRequest(
 
     /* store result */
     *Result = Buffer;
-    *Size = ParametersLength;
+    *Size = (ULONG)ParametersLength;
 
     return STATUS_SUCCESS;
 }
@@ -199,7 +199,7 @@ KsGetOuterUnknown(
     PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
 
     /* sanity check */
-    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 
+    ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
            BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
 
     /* return objects outer unknown */
index 0865b3b..2226223 100644 (file)
@@ -193,7 +193,7 @@ IKsPin_PinMasterClock(
             {
                 Mode = ExGetPreviousMode();
 
-                Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
+                Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, *IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
 
                 DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
                 if (NT_SUCCESS(Status))
@@ -2221,7 +2221,7 @@ IKsPin_DispatchCreateClock(
                    pResolution = &Resolution;
                 }
 
-                Status = KsAllocateDefaultClockEx(&This->DefaultClock, 
+                Status = KsAllocateDefaultClockEx(&This->DefaultClock,
                                                   (PVOID)&This->Pin,
                                                   (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
                                                   (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
@@ -2265,7 +2265,7 @@ IKsPin_DispatchCreateNode(
     return STATUS_NOT_IMPLEMENTED;
 }
 
-static KSDISPATCH_TABLE PinDispatchTable = 
+static KSDISPATCH_TABLE PinDispatchTable =
 {
     IKsPin_DispatchDeviceIoControl,
     KsDispatchInvalidDeviceRequest,
@@ -2329,10 +2329,10 @@ KspCreatePin(
             DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment);
             DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight);
             DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize,
-                   Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize, 
+                   Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize,
                    Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping);
 
-            DPRINT("KspCreatePin Index %lu FramingRange  MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n", 
+            DPRINT("KspCreatePin Index %lu FramingRange  MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n",
                    Index,
                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize,
                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize,
index 7d6a29b..0290435 100644 (file)
@@ -300,7 +300,7 @@ KspPropertyHandler(
             if (Allocator)
             {
                 /* allocate the requested amount */
-                Status = Allocator(Irp, Irp->IoStatus.Information, FALSE);
+                Status = Allocator(Irp, (ULONG)Irp->IoStatus.Information, FALSE);
 
                 /* check if the block was allocated */
                 if (!NT_SUCCESS(Status))
@@ -364,15 +364,16 @@ KsPropertyHandler(
 /*
     @implemented
 */
+_IRQL_requires_max_(PASSIVE_LEVEL)
 KSDDKAPI
 NTSTATUS
 NTAPI
 KsPropertyHandlerWithAllocator(
-    IN  PIRP Irp,
-    IN  ULONG PropertySetsCount,
-    IN  PKSPROPERTY_SET PropertySet,
-    IN  PFNKSALLOCATOR Allocator OPTIONAL,
-    IN  ULONG PropertyItemSize OPTIONAL)
+    _In_ PIRP Irp,
+    _In_ ULONG PropertySetsCount,
+    _In_reads_(PropertySetsCount) const KSPROPERTY_SET* PropertySet,
+    _In_opt_ PFNKSALLOCATOR Allocator,
+    _In_opt_ ULONG PropertyItemSize)
 {
     return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize);
 }
index 0b76c85..93dbb41 100644 (file)
@@ -329,7 +329,7 @@ KspCreateDeviceReference(
     IN LPWSTR ReferenceString)
 {
     LPWSTR DeviceName;
-    ULONG Length;
+    SIZE_T Length;
     PLIST_ENTRY Entry;
     PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */
     BOOLEAN ItemExists = FALSE;
@@ -523,7 +523,7 @@ KspBusQueryReferenceString(
     IN OUT PWCHAR *String)
 {
     LPWSTR Name;
-    ULONG Length;
+    SIZE_T Length;
     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context;
 
     /* sanity checks */
@@ -665,7 +665,7 @@ KspDoReparseForIrp(
     PIRP Irp,
     PBUS_DEVICE_ENTRY DeviceEntry)
 {
-    ULONG Length;
+    SIZE_T Length;
     LPWSTR Buffer;
     PIO_STACK_LOCATION IoStack;
 
@@ -885,7 +885,7 @@ KspQueryId(
     PBUS_DEVICE_ENTRY DeviceEntry;
     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
     LPWSTR Name;
-    ULONG Length;
+    SIZE_T Length;
 
     /* get current irp stack location */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -972,7 +972,7 @@ KspInstallInterface(
     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
     IN PSWENUM_INSTALL_INTERFACE InstallInterface)
 {
-    ULONG Length, Index;
+    SIZE_T Length, Index;
     UNICODE_STRING DeviceString, InterfaceString, ReferenceString;
     HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey;
     NTSTATUS Status;
@@ -1369,7 +1369,7 @@ KsGetBusEnumIdentifier(
     PDEV_EXTENSION DeviceExtension;
     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
     PIO_STACK_LOCATION IoStack;
-    ULONG Length;
+    SIZE_T Length;
     NTSTATUS Status;
     LPWSTR Buffer;
 
@@ -1489,7 +1489,7 @@ KsCreateBusEnumObject(
     IN REFGUID InterfaceGuid OPTIONAL,
     IN PWCHAR ServiceRelativePath OPTIONAL)
 {
-    ULONG Length;
+    SIZE_T Length;
     NTSTATUS Status = STATUS_SUCCESS;
     UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
index c6dc1b7..2785a9b 100644 (file)
@@ -28,7 +28,7 @@ KspCreateObjectType(
 
     /* calculate request length */
     Name.Length = 0;
-    Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize +  1 * sizeof(WCHAR);
+    Name.MaximumLength = (USHORT)(wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize +  1 * sizeof(WCHAR));
     Name.MaximumLength += sizeof(WCHAR);
     /* acquire request buffer */
     Name.Buffer = AllocateItem(NonPagedPool, Name.MaximumLength);
@@ -39,7 +39,7 @@ KspCreateObjectType(
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    /* build a request which looks like {ObjectClass}\CreateParameters 
+    /* build a request which looks like {ObjectClass}\CreateParameters
      * For pins the parent is the reference string used in registration
      * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
      */
index 5bc13bf..21a64fe 100644 (file)
@@ -105,7 +105,7 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                        0,
                                        NULL,
                                        MAXIMUM_ALLOWED,
-                                       IoFileObjectType,
+                                       *IoFileObjectType,
                                        Irp->RequestorMode,
                                        &UserHandle);
         if (NT_SUCCESS(Status))
index 66b8ac8..2e30ca3 100644 (file)
@@ -289,7 +289,7 @@ AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
         Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo->
                                             EventObject,
                                             EVENT_ALL_ACCESS,
-                                            ExEventObjectType,
+                                            *ExEventObjectType,
                                             UserMode,
                                             (PVOID *)&FCB->EventSelect,
                                             NULL );
@@ -346,7 +346,7 @@ AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     Status = ObReferenceObjectByHandle(EnumReq->Event,
                                        EVENT_ALL_ACCESS,
-                                       ExEventObjectType,
+                                       *ExEventObjectType,
                                        UserMode,
                                        (PVOID *)&UserEvent,
                                        NULL);
index 60040e1..a36a09d 100644 (file)
@@ -144,7 +144,7 @@ static NTSTATUS TdiOpenDevice(
     if (NT_SUCCESS(Status)) {
         Status = ObReferenceObjectByHandle(*Handle,                       /* Handle to open file */
                                            GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,  /* Access mode */
-                                           IoFileObjectType,              /* Object type */
+                                           *IoFileObjectType,              /* Object type */
                                            KernelMode,                    /* Access mode */
                                            (PVOID*)Object,                /* Pointer to object */
                                            NULL);                         /* Handle information */
index 94d127d..69ed6bf 100644 (file)
@@ -173,7 +173,7 @@ VOID NTAPI DispCancelRequest(
     case TDI_CONNECT:
         DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
         break;
-            
+
     case TDI_DISCONNECT:
         Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
 
@@ -303,7 +303,7 @@ NTSTATUS DispTdiAssociateAddress(
   Status = ObReferenceObjectByHandle(
     Parameters->AddressHandle,
     0,
-    IoFileObjectType,
+    *IoFileObjectType,
     KernelMode,
     (PVOID*)&FileObject,
     NULL);
@@ -511,7 +511,7 @@ NTSTATUS DispTdiDisconnect(
     Status = STATUS_INVALID_PARAMETER;
     goto done;
   }
-    
+
   Status = DispPrepareIrpForCancel
     (TranContext->Handle.ConnectionContext,
      Irp,
@@ -716,7 +716,7 @@ NTSTATUS DispTdiQueryInformation(
           case TDI_CONNECTION_FILE:
             Endpoint =
                                (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
-                
+
             Address->TAAddressCount = 1;
             Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
             Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
@@ -761,12 +761,12 @@ NTSTATUS DispTdiQueryInformation(
       case TDI_QUERY_MAX_DATAGRAM_INFO:
       {
           PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo;
-          
+
           if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) {
               TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
               return STATUS_BUFFER_TOO_SMALL;
           }
-          
+
           MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO)
             MmGetSystemAddressForMdl(Irp->MdlAddress);
 
@@ -1560,7 +1560,7 @@ NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
 
             IF->Netmask.Type = IP_ADDRESS_V4;
             IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
-            
+
             IF->Broadcast.Type = IP_ADDRESS_V4;
            IF->Broadcast.Address.IPv4Address =
                IF->Unicast.Address.IPv4Address |
index 740fd9e..ea4a2be 100644 (file)
@@ -761,9 +761,9 @@ InitController(PCONTROLLER_INFO ControllerInfo)
     HeadLoadTime = SPECIFY_HLT_500K;
     HeadUnloadTime = SPECIFY_HUT_500K;
     StepRateTime = SPECIFY_SRT_500K;
-    
+
     INFO_(FLOPPY, "InitController: setting data rate\n");
-    
+
     /* Set data rate */
     if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS)
     {
@@ -1176,7 +1176,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
+    if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, *PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
     {
         WARN_(FLOPPY, "Unable to reference returned thread handle; failing init\n");
         return STATUS_UNSUCCESSFUL;
index 1b6a90d..89d85fd 100644 (file)
@@ -97,7 +97,7 @@ WdmAudControlDeviceState(
 
     DPRINT("WdmAudControlDeviceState\n");
 
-    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
@@ -197,7 +197,7 @@ WdmAudFrameSize(
     NTSTATUS Status;
 
     /* Get sysaudio pin file object */
-    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
@@ -290,7 +290,7 @@ WdmAudResetStream(
 
     DPRINT("WdmAudResetStream\n");
 
-    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
@@ -528,7 +528,7 @@ WdmAudReadWrite(
     ASSERT(DeviceInfo);
 
     /* now get sysaudio file object */
-    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
index 4363a03..477ac30 100644 (file)
@@ -165,7 +165,7 @@ WdmAudOpenSysAudioDevices(
             }
 
             /* get the file object */
-            Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+            Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
             if (!NT_SUCCESS(Status))
             {
                 DPRINT1("Failed to reference FileObject %x\n", Status);
@@ -200,7 +200,7 @@ WdmAudRegisterDeviceInterface(
     }
 
     /* failed to register device interface
-     * create a symbolic link instead 
+     * create a symbolic link instead
      */
     DeviceExtension->DeviceInterfaceSupport = FALSE;
 
index 6642447..deafa02 100644 (file)
@@ -202,7 +202,7 @@ Control(
     PFILE_OBJECT FileObject;
 
     /* get file object */
-    Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT("failed to reference %p with %lx\n", hMixer, Status);
@@ -420,7 +420,7 @@ WdmAudControlOpenMixer(
 
     if (DeviceInfo->u.hNotifyEvent)
     {
-        Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
+        Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
 
         if (!NT_SUCCESS(Status))
         {
index c7c33a5..f191789 100644 (file)
@@ -420,7 +420,7 @@ OpenDevice(
 
     if (FileObject)
     {
-        Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL);
+        Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL);
 
         if (!NT_SUCCESS(Status))
         {
index 8db2977..5e5bb09 100644 (file)
@@ -50,7 +50,7 @@ OpenDevice(
         return Status;
     }
 
-    Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         ZwClose(NodeHandle);
index f0c7f44..1b688aa 100644 (file)
@@ -35,7 +35,7 @@ Pin_fnDeviceIoControl(
     ASSERT(Context);
 
     /* acquire real pin file object */
-    Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         Irp->IoStatus.Information = 0;
@@ -94,7 +94,7 @@ Pin_fnWrite(
     }
 
     /* acquire real pin file object */
-    Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("failed\n");
@@ -235,8 +235,8 @@ CreateMixerPinAndSetFormat(
     }
 
     Status = ObReferenceObjectByHandle(PinHandle,
-                                       GENERIC_READ | GENERIC_WRITE, 
-                                       IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+                                       GENERIC_READ | GENERIC_WRITE,
+                                       *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
 
     if (!NT_SUCCESS(Status))
     {
index 2fb593b..35f1984 100644 (file)
@@ -12,4 +12,4 @@ set_module_type(wmilib kernelmodedriver ENTRYPOINT 0)
 
 add_importlibs(wmilib ntoskrnl)
 
-add_cd_file(TARGET wmilib DESTINATION reactos/system32/drivers FOR all)
+add_cd_file(TARGET wmilib DESTINATION reactos/system32/drivers NO_CAB FOR all)
diff --git a/include/ddk/isvbop.h b/include/ddk/isvbop.h
new file mode 100644 (file)
index 0000000..088e9e6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * isvbop.h
+ *
+ * Windows NT Device Driver Kit
+ *
+ * This file is part of the ReactOS DDK package.
+ *
+ * Contributors:
+ *   Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * 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
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ * The corresponding ASM header of this file is isvbop.inc.
+ */
+
+#pragma once
+
+/* BOP Identifiers */
+#define BOP_3RDPARTY    0x58    // 3rd-party VDD BOP
+#define BOP_UNSIMULATE  0xFE    // Stop execution
+
+#if defined(__GNUC__)
+
+#define RegisterModule()    __asm__(".byte 0xC4, 0xC4, %c0, 0" : : "i"(BOP_3RDPARTY))
+#define UnRegisterModule()  __asm__(".byte 0xC4, 0xC4, %c0, 1" : : "i"(BOP_3RDPARTY))
+#define DispatchCall()      __asm__(".byte 0xC4, 0xC4, %c0, 2" : : "i"(BOP_3RDPARTY))
+#define VDDUnSimulate16()   __asm__(".byte 0xC4, 0xC4, %c0"    : : "i"(BOP_UNSIMULATE))
+
+#elif defined(_MSC_VER)
+
+#define RegisterModule()    _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 0
+#define UnRegisterModule()  _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 1
+#define DispatchCall()      _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 2
+#define VDDUnSimulate16()   _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_UNSIMULATE
+
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+/* EOF */
diff --git a/include/ddk/isvbop.inc b/include/ddk/isvbop.inc
new file mode 100644 (file)
index 0000000..7a13b4b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * isvbop.inc
+ *
+ * Windows NT Device Driver Kit
+ *
+ * This file is part of the ReactOS DDK package.
+ *
+ * Contributors:
+ *   Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * 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
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ * This is the corresponding ASM header for isvbop.h.
+ * Please refer to isvbop.h for information about these interfaces.
+ */
+
+#include <asm.inc>
+
+BOP_3RDPARTY    = HEX(58)
+BOP_UNSIMULATE  = HEX(FE)
+
+MACRO(RegisterModule)
+    .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 0
+ENDM
+
+MACRO(UnRegisterModule)
+    .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 1
+ENDM
+
+MACRO(DispatchCall)
+    .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 2
+ENDM
+
+MACRO(VDDUnSimulate16)
+    .byte HEX(C4), HEX(C4), BOP_UNSIMULATE
+ENDM
+
+/* EOF */
diff --git a/include/ddk/nt_vdd.h b/include/ddk/nt_vdd.h
new file mode 100644 (file)
index 0000000..b4b6c7d
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * nt_vdd.h
+ *
+ * Windows NT Device Driver Kit
+ *
+ * This file is part of the ReactOS DDK package.
+ *
+ * Contributors:
+ *   Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * 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
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#pragma once
+
+#define _NT_VDD
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * VDM Control
+ */
+
+VOID
+WINAPI
+VDDSimulate16(VOID);
+
+VOID
+WINAPI
+VDDTerminateVDM(VOID);
+
+
+/*
+ * I/O Port services
+ */
+
+typedef VOID (*PFNVDD_INB)   (WORD iport, PBYTE data);
+typedef VOID (*PFNVDD_INW)   (WORD iport, PWORD data);
+typedef VOID (*PFNVDD_INSB)  (WORD iport, PBYTE data, WORD count);
+typedef VOID (*PFNVDD_INSW)  (WORD iport, PWORD data, WORD count);
+typedef VOID (*PFNVDD_OUTB)  (WORD iport, BYTE  data);
+typedef VOID (*PFNVDD_OUTW)  (WORD iport, WORD  data);
+typedef VOID (*PFNVDD_OUTSB) (WORD iport, PBYTE data, WORD count);
+typedef VOID (*PFNVDD_OUTSW) (WORD iport, PWORD data, WORD count);
+
+typedef struct _VDD_IO_HANDLERS
+{
+    PFNVDD_INB   inb_handler;
+    PFNVDD_INW   inw_handler;
+    PFNVDD_INSB  insb_handler;
+    PFNVDD_INSW  insw_handler;
+    PFNVDD_OUTB  outb_handler;
+    PFNVDD_OUTW  outw_handler;
+    PFNVDD_OUTSB outsb_handler;
+    PFNVDD_OUTSW outsw_handler;
+} VDD_IO_HANDLERS, *PVDD_IO_HANDLERS;
+
+typedef struct _VDD_IO_PORTRANGE
+{
+    WORD First;
+    WORD Last;
+} VDD_IO_PORTRANGE, *PVDD_IO_PORTRANGE;
+
+BOOL
+WINAPI
+VDDInstallIOHook
+(
+    HANDLE            hVdd,
+    WORD              cPortRange,
+    PVDD_IO_PORTRANGE pPortRange,
+    PVDD_IO_HANDLERS  IOhandler
+);
+
+VOID
+WINAPI
+VDDDeInstallIOHook
+(
+    HANDLE            hVdd,
+    WORD              cPortRange,
+    PVDD_IO_PORTRANGE pPortRange
+);
+
+
+/*
+ * Memory services
+ */
+
+typedef enum
+{
+    VDM_V86,
+    VDM_PM
+} VDM_MODE;
+
+#ifndef MSW_PE
+#define MSW_PE  0x0001
+#endif
+
+#define getMODE() ((getMSW() & MSW_PE) ? VDM_PM : VDM_V86)
+
+PBYTE
+WINAPI
+Sim32pGetVDMPointer
+(
+    IN ULONG   Address,
+    IN BOOLEAN ProtectedMode
+);
+
+PBYTE
+WINAPI
+MGetVdmPointer
+(
+    IN ULONG   Address,
+    IN ULONG   Size,
+    IN BOOLEAN ProtectedMode
+);
+
+PVOID
+WINAPI
+VdmMapFlat
+(
+    IN USHORT   Segment,
+    IN ULONG    Offset,
+    IN VDM_MODE Mode
+);
+
+BOOL
+WINAPI
+VdmFlushCache
+(
+    IN USHORT   Segment,
+    IN ULONG    Offset,
+    IN ULONG    Size,
+    IN VDM_MODE Mode
+);
+
+BOOL
+WINAPI
+VdmUnmapFlat
+(
+    IN USHORT   Segment,
+    IN ULONG    Offset,
+    IN PVOID    Buffer,
+    IN VDM_MODE Mode
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* EOF */
index b8e4e03..8cf5a48 100644 (file)
@@ -1666,14 +1666,12 @@ typedef struct {
 #endif
 } HAL_DISPATCH, *PHAL_DISPATCH;
 
-/* GCC/MSVC and WDK compatible declaration */
-extern NTKERNELAPI HAL_DISPATCH HalDispatchTable;
-
-#if defined(_NTOSKRNL_) || defined(_BLDR_)
+#ifdef _NTSYSTEM_
+extern HAL_DISPATCH HalDispatchTable;
 #define HALDISPATCH (&HalDispatchTable)
 #else
-/* This is a WDK compatibility definition */
-#define HalDispatchTable (&HalDispatchTable)
+extern PHAL_DISPATCH HalDispatchTable;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(HalDispatchTable)
 #define HALDISPATCH HalDispatchTable
 #endif
 
index df190c1..53b2d13 100644 (file)
@@ -4937,35 +4937,13 @@ FsRtlNotifyStreamFileObject(
   _In_ BOOLEAN SafeToRecurse);
 #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
 
-#define DO_VERIFY_VOLUME                    0x00000002
-#define DO_BUFFERED_IO                      0x00000004
-#define DO_EXCLUSIVE                        0x00000008
-#define DO_DIRECT_IO                        0x00000010
-#define DO_MAP_IO_BUFFER                    0x00000020
-#define DO_DEVICE_HAS_NAME                  0x00000040
-#define DO_DEVICE_INITIALIZING              0x00000080
-#define DO_SYSTEM_BOOT_PARTITION            0x00000100
-#define DO_LONG_TERM_REQUESTS               0x00000200
-#define DO_NEVER_LAST_DEVICE                0x00000400
-#define DO_SHUTDOWN_REGISTERED              0x00000800
-#define DO_BUS_ENUMERATED_DEVICE            0x00001000
-#define DO_POWER_PAGABLE                    0x00002000
-#define DO_POWER_INRUSH                     0x00004000
-#define DO_LOW_PRIORITY_FILESYSTEM          0x00010000
-#define DO_SUPPORTS_TRANSACTIONS            0x00040000
-#define DO_FORCE_NEITHER_IO                 0x00080000
-#define DO_VOLUME_DEVICE_OBJECT             0x00100000
-#define DO_SYSTEM_SYSTEM_PARTITION          0x00200000
-#define DO_SYSTEM_CRITICAL_PARTITION        0x00400000
-#define DO_DISALLOW_EXECUTE                 0x00800000
-
-extern KSPIN_LOCK                   IoStatisticsLock;
-extern ULONG                        IoReadOperationCount;
-extern ULONG                        IoWriteOperationCount;
-extern ULONG                        IoOtherOperationCount;
-extern LARGE_INTEGER                IoReadTransferCount;
-extern LARGE_INTEGER                IoWriteTransferCount;
-extern LARGE_INTEGER                IoOtherTransferCount;
+extern NTKERNELAPI KSPIN_LOCK    IoStatisticsLock;
+extern NTKERNELAPI ULONG         IoReadOperationCount;
+extern NTKERNELAPI ULONG         IoWriteOperationCount;
+extern NTKERNELAPI ULONG         IoOtherOperationCount;
+extern NTKERNELAPI LARGE_INTEGER IoReadTransferCount;
+extern NTKERNELAPI LARGE_INTEGER IoWriteTransferCount;
+extern NTKERNELAPI LARGE_INTEGER IoOtherTransferCount;
 
 #define IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE    64
 #define IO_FILE_OBJECT_PAGED_POOL_CHARGE        1024
@@ -5731,6 +5709,7 @@ SeLocateProcessImageName(
     ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken )
 
 extern NTKERNELAPI PSE_EXPORTS SeExports;
+
 /******************************************************************************
  *                          Process Manager Functions                         *
  ******************************************************************************/
@@ -8413,26 +8392,31 @@ FsRtlRemovePerFileObjectContext(
     (InterlockedDecrement((LONG volatile *)&((FL)->LockRequestsInProgress)));\
 }
 
-/* GCC compatible definition, MS one is retarded */
-extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray;
-#define LEGAL_ANSI_CHARACTER_ARRAY        FsRtlLegalAnsiCharacterArray
+#ifdef _NTSYSTEM_
+extern const UCHAR * const FsRtlLegalAnsiCharacterArray;
+#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray
+#else
+extern const UCHAR * const *FsRtlLegalAnsiCharacterArray;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(FsRtlLegalAnsiCharacterArray)
+#define LEGAL_ANSI_CHARACTER_ARRAY (*FsRtlLegalAnsiCharacterArray)
+#endif
 
 #define FsRtlIsAnsiCharacterWild(C) (                                       \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \
 )
 
 #define FsRtlIsAnsiCharacterLegalFat(C, WILD) (                                \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_FAT_LEGAL) |       \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_FAT_LEGAL) |       \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
 #define FsRtlIsAnsiCharacterLegalHpfs(C, WILD) (                               \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) |      \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) |      \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
 #define FsRtlIsAnsiCharacterLegalNtfs(C, WILD) (                               \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) |      \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) |      \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
@@ -8460,7 +8444,7 @@ extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray;
 #define FsRtlIsUnicodeCharacterWild(C) (                                    \
     (((C) >= 0x40) ?                                                        \
     FALSE :                                                                 \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(C)], FSRTL_WILD_CHARACTER ))       \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(C)], FSRTL_WILD_CHARACTER ))       \
 )
 
 #define FsRtlInitPerFileContext( _fc, _owner, _inst, _cb)   \
@@ -8623,7 +8607,7 @@ typedef VOID
     (((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \
 )
 
-extern ULONG CcFastMdlReadWait;
+extern NTKERNELAPI ULONG CcFastMdlReadWait;
 
 #if (NTDDI_VERSION >= NTDDI_WIN2K)
 
@@ -11005,13 +10989,14 @@ HalGetDmaAlignmentRequirement(
 #define HalGetDmaAlignmentRequirement() 1L
 #endif
 
-extern NTKERNELAPI PUSHORT NlsOemLeadByteInfo;
-#define NLS_OEM_LEAD_BYTE_INFO            NlsOemLeadByteInfo
-
-#ifdef NLS_MB_CODE_PAGE_TAG
-#undef NLS_MB_CODE_PAGE_TAG
+#ifdef _NTSYSTEM_
+extern PUSHORT NlsOemLeadByteInfo;
+#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo
+#else
+extern PUSHORT *NlsOemLeadByteInfo;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsOemLeadByteInfo)
+#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo)
 #endif
-#define NLS_MB_CODE_PAGE_TAG              NlsMbOemCodePageTag
 
 #if (NTDDI_VERSION >= NTDDI_VISTA)
 
diff --git a/include/ddk/vddsvc.h b/include/ddk/vddsvc.h
new file mode 100644 (file)
index 0000000..451a2c4
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * vddsvc.h
+ *
+ * Windows NT Device Driver Kit
+ *
+ * This file is part of the ReactOS DDK package.
+ *
+ * Contributors:
+ *   Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * 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
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#pragma once
+
+#ifndef _NT_VDD
+#include <nt_vdd.h>
+#endif
+
+/*
+ * Interrupts services
+ */
+#define ICA_MASTER  0
+#define ICA_SLAVE   1
+
+VOID
+WINAPI
+call_ica_hw_interrupt
+(
+    INT  ms,
+    BYTE line,
+    INT  count
+);
+
+#define VDDSimulateInterrupt(ms, line, count)   \
+    call_ica_hw_interrupt((ms), (line), (count)) // Windows specifies a count of 1 ...
+
+
+/*
+ * Registers manipulation
+ */
+PVOID  WINAPI getIntelRegistersPointer(VOID);
+
+#ifndef _M_MIPS
+
+ULONG  WINAPI getEAX(VOID);
+VOID   WINAPI setEAX(ULONG);
+USHORT WINAPI getAX(VOID);
+VOID   WINAPI setAX(USHORT);
+UCHAR  WINAPI getAH(VOID);
+VOID   WINAPI setAH(UCHAR);
+UCHAR  WINAPI getAL(VOID);
+VOID   WINAPI setAL(UCHAR);
+
+ULONG  WINAPI getEBX(VOID);
+VOID   WINAPI setEBX(ULONG);
+USHORT WINAPI getBX(VOID);
+VOID   WINAPI setBX(USHORT);
+UCHAR  WINAPI getBH(VOID);
+VOID   WINAPI setBH(UCHAR);
+UCHAR  WINAPI getBL(VOID);
+VOID   WINAPI setBL(UCHAR);
+
+ULONG  WINAPI getECX(VOID);
+VOID   WINAPI setECX(ULONG);
+USHORT WINAPI getCX(VOID);
+VOID   WINAPI setCX(USHORT);
+UCHAR  WINAPI getCH(VOID);
+VOID   WINAPI setCH(UCHAR);
+UCHAR  WINAPI getCL(VOID);
+VOID   WINAPI setCL(UCHAR);
+
+ULONG  WINAPI getEDX(VOID);
+VOID   WINAPI setEDX(ULONG);
+USHORT WINAPI getDX(VOID);
+VOID   WINAPI setDX(USHORT);
+UCHAR  WINAPI getDH(VOID);
+VOID   WINAPI setDH(UCHAR);
+UCHAR  WINAPI getDL(VOID);
+VOID   WINAPI setDL(UCHAR);
+
+
+
+ULONG  WINAPI getESP(VOID);
+VOID   WINAPI setESP(ULONG);
+USHORT WINAPI getSP(VOID);
+VOID   WINAPI setSP(USHORT);
+
+ULONG  WINAPI getEBP(VOID);
+VOID   WINAPI setEBP(ULONG);
+USHORT WINAPI getBP(VOID);
+VOID   WINAPI setBP(USHORT);
+
+ULONG  WINAPI getESI(VOID);
+VOID   WINAPI setESI(ULONG);
+USHORT WINAPI getSI(VOID);
+VOID   WINAPI setSI(USHORT);
+
+ULONG  WINAPI getEDI(VOID);
+VOID   WINAPI setEDI(ULONG);
+USHORT WINAPI getDI(VOID);
+VOID   WINAPI setDI(USHORT);
+
+ULONG  WINAPI getEIP(VOID);
+VOID   WINAPI setEIP(ULONG);
+USHORT WINAPI getIP(VOID);
+VOID   WINAPI setIP(USHORT);
+
+USHORT WINAPI getCS(VOID);
+VOID   WINAPI setCS(USHORT);
+USHORT WINAPI getSS(VOID);
+VOID   WINAPI setSS(USHORT);
+USHORT WINAPI getDS(VOID);
+VOID   WINAPI setDS(USHORT);
+USHORT WINAPI getES(VOID);
+VOID   WINAPI setES(USHORT);
+USHORT WINAPI getFS(VOID);
+VOID   WINAPI setFS(USHORT);
+USHORT WINAPI getGS(VOID);
+VOID   WINAPI setGS(USHORT);
+
+ULONG  WINAPI getCF(VOID);
+VOID   WINAPI setCF(ULONG);
+ULONG  WINAPI getPF(VOID);
+VOID   WINAPI setPF(ULONG);
+ULONG  WINAPI getAF(VOID);
+VOID   WINAPI setAF(ULONG);
+ULONG  WINAPI getZF(VOID);
+VOID   WINAPI setZF(ULONG);
+ULONG  WINAPI getSF(VOID);
+VOID   WINAPI setSF(ULONG);
+ULONG  WINAPI getIF(VOID);
+VOID   WINAPI setIF(ULONG);
+ULONG  WINAPI getDF(VOID);
+VOID   WINAPI setDF(ULONG);
+ULONG  WINAPI getOF(VOID);
+VOID   WINAPI setOF(ULONG);
+
+ULONG  WINAPI getEFLAGS(VOID);
+VOID   WINAPI setEFLAGS(ULONG);
+
+USHORT WINAPI getMSW(VOID);
+VOID   WINAPI setMSW(USHORT);
+
+#else
+
+ULONG  WINAPI c_getEAX(VOID);
+VOID   WINAPI c_setEAX(ULONG);
+USHORT WINAPI c_getAX(VOID);
+VOID   WINAPI c_setAX(USHORT);
+UCHAR  WINAPI c_getAH(VOID);
+VOID   WINAPI c_setAH(UCHAR);
+UCHAR  WINAPI c_getAL(VOID);
+VOID   WINAPI c_setAL(UCHAR);
+
+ULONG  WINAPI c_getEBX(VOID);
+VOID   WINAPI c_setEBX(ULONG);
+USHORT WINAPI c_getBX(VOID);
+VOID   WINAPI c_setBX(USHORT);
+UCHAR  WINAPI c_getBH(VOID);
+VOID   WINAPI c_setBH(UCHAR);
+UCHAR  WINAPI c_getBL(VOID);
+VOID   WINAPI c_setBL(UCHAR);
+
+ULONG  WINAPI c_getECX(VOID);
+VOID   WINAPI c_setECX(ULONG);
+USHORT WINAPI c_getCX(VOID);
+VOID   WINAPI c_setCX(USHORT);
+UCHAR  WINAPI c_getCH(VOID);
+VOID   WINAPI c_setCH(UCHAR);
+UCHAR  WINAPI c_getCL(VOID);
+VOID   WINAPI c_setCL(UCHAR);
+
+ULONG  WINAPI c_getEDX(VOID);
+VOID   WINAPI c_setEDX(ULONG);
+USHORT WINAPI c_getDX(VOID);
+VOID   WINAPI c_setDX(USHORT);
+UCHAR  WINAPI c_getDH(VOID);
+VOID   WINAPI c_setDH(UCHAR);
+UCHAR  WINAPI c_getDL(VOID);
+VOID   WINAPI c_setDL(UCHAR);
+
+
+
+ULONG  WINAPI c_getESP(VOID);
+VOID   WINAPI c_setESP(ULONG);
+USHORT WINAPI c_getSP(VOID);
+VOID   WINAPI c_setSP(USHORT);
+
+ULONG  WINAPI c_getEBP(VOID);
+VOID   WINAPI c_setEBP(ULONG);
+USHORT WINAPI c_getBP(VOID);
+VOID   WINAPI c_setBP(USHORT);
+
+ULONG  WINAPI c_getESI(VOID);
+VOID   WINAPI c_setESI(ULONG);
+USHORT WINAPI c_getSI(VOID);
+VOID   WINAPI c_setSI(USHORT);
+
+ULONG  WINAPI c_getEDI(VOID);
+VOID   WINAPI c_setEDI(ULONG);
+USHORT WINAPI c_getDI(VOID);
+VOID   WINAPI c_setDI(USHORT);
+
+ULONG  WINAPI c_getEIP(VOID);
+VOID   WINAPI c_setEIP(ULONG);
+USHORT WINAPI c_getIP(VOID);
+VOID   WINAPI c_setIP(USHORT);
+
+USHORT WINAPI c_getCS(VOID);
+VOID   WINAPI c_setCS(USHORT);
+USHORT WINAPI c_getSS(VOID);
+VOID   WINAPI c_setSS(USHORT);
+USHORT WINAPI c_getDS(VOID);
+VOID   WINAPI c_setDS(USHORT);
+USHORT WINAPI c_getES(VOID);
+VOID   WINAPI c_setES(USHORT);
+USHORT WINAPI c_getFS(VOID);
+VOID   WINAPI c_setFS(USHORT);
+USHORT WINAPI c_getGS(VOID);
+VOID   WINAPI c_setGS(USHORT);
+
+ULONG  WINAPI c_getCF(VOID);
+VOID   WINAPI c_setCF(ULONG);
+ULONG  WINAPI c_getPF(VOID);
+VOID   WINAPI c_setPF(ULONG);
+ULONG  WINAPI c_getAF(VOID);
+VOID   WINAPI c_setAF(ULONG);
+ULONG  WINAPI c_getZF(VOID);
+VOID   WINAPI c_setZF(ULONG);
+ULONG  WINAPI c_getSF(VOID);
+VOID   WINAPI c_setSF(ULONG);
+ULONG  WINAPI c_getIF(VOID);
+VOID   WINAPI c_setIF(ULONG);
+ULONG  WINAPI c_getDF(VOID);
+VOID   WINAPI c_setDF(ULONG);
+ULONG  WINAPI c_getOF(VOID);
+VOID   WINAPI c_setOF(ULONG);
+
+USHORT WINAPI c_getMSW(VOID);
+VOID   WINAPI c_setMSW(USHORT);
+
+#endif
+
+/* EOF */
index 124e45b..8d04060 100644 (file)
@@ -82,10 +82,13 @@ extern "C" {
 #endif
 
 /* For ReactOS */
-#if !defined(_NTOSKRNL_) && !defined(_BLDR_)
+#if !defined(_NTOSKRNL_) && !defined(_BLDR_) && !defined(_NTSYSTEM_)
 #define NTKERNELAPI DECLSPEC_IMPORT
 #else
 #define NTKERNELAPI
+#ifndef _NTSYSTEM_
+#define _NTSYSTEM_
+#endif
 #endif
 
 #if defined(_X86_) && !defined(_NTHAL_)
@@ -129,6 +132,29 @@ extern "C" {
 #define ALLOC_DATA_PRAGMA 1
 #endif
 
+#endif /* _MSC_VER */
+
+/* These macros are used to create aliases for imported data. We need to do
+   this to have declarations that are compatible with MS DDK */
+#ifdef _M_IX86
+#define __SYMBOL(_Name) "_"#_Name
+#define __IMPORTSYMBOL(_Name) "__imp__"#_Name
+#define __IMPORTNAME(_Name) _imp__##_Name
+#else
+#define __SYMBOL(_Name) #_Name
+#define __IMPORTSYMBOL(_Name) "__imp_"#_Name
+#define __IMPORTNAME(_Name) __imp_##_Name
+#endif
+#ifdef _MSC_VER
+#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \
+    __pragma(comment(linker, "/alternatename:"__SYMBOL(_Name) "=" __IMPORTSYMBOL(_Name)))
+#else /* !_MSC_VER */
+#ifndef __STRINGIFY
+#define __STRINGIFY(_exp) #_exp
+#endif
+#define _Pragma_redefine_extname(_Name, _Target) _Pragma(__STRINGIFY(redefine_extname _Name _Target))
+#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \
+    _Pragma_redefine_extname(_Name,__IMPORTNAME(_Name))
 #endif
 
 #if defined(_WIN64)
@@ -599,11 +625,19 @@ typedef struct _EXCEPTION_POINTERS {
   PCONTEXT ContextRecord;
 } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
 
-/* MS definition is broken! */
-extern BOOLEAN NTSYSAPI NlsMbCodePageTag;
-extern BOOLEAN NTSYSAPI NlsMbOemCodePageTag;
+#ifdef _NTSYSTEM_
+extern BOOLEAN NlsMbCodePageTag;
 #define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag
+extern BOOLEAN NlsMbOemCodePageTag;
 #define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
+#else
+extern BOOLEAN *NlsMbCodePageTag;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbCodePageTag)
+#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag)
+extern BOOLEAN *NlsMbOemCodePageTag;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbOemCodePageTag)
+#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag)
+#endif
 
 #define SHORT_LEAST_SIGNIFICANT_BIT       0
 #define SHORT_MOST_SIGNIFICANT_BIT        1
@@ -1673,6 +1707,7 @@ extern NTSYSAPI volatile CCHAR KeNumberProcessors;
 extern NTSYSAPI CCHAR KeNumberProcessors;
 #else
 extern PCCHAR KeNumberProcessors;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors)
 #endif
 
 
@@ -1824,8 +1859,11 @@ typedef enum _MM_SYSTEM_SIZE {
   MmLargeSystem
 } MM_SYSTEMSIZE;
 
-extern NTKERNELAPI BOOLEAN Mm64BitPhysicalAddress;
-extern PVOID MmBadPointer;
+#ifndef _NTSYSTEM_
+extern PBOOLEAN Mm64BitPhysicalAddress;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(Mm64BitPhysicalAddress)
+#endif
+extern NTKERNELAPI PVOID MmBadPointer;
 
 
 /******************************************************************************
@@ -2098,7 +2136,7 @@ typedef struct _RESOURCE_PERFORMANCE_DATA {
 
 /* Global debug flag */
 #if DEVL
-extern ULONG NtGlobalFlag;
+extern NTKERNELAPI ULONG NtGlobalFlag;
 #define IF_NTOS_DEBUG(FlagName) if (NtGlobalFlag & (FLG_##FlagName))
 #else
 #define IF_NTOS_DEBUG(FlagName) if(FALSE)
@@ -7857,6 +7895,7 @@ typedef struct _OBJECT_NAME_INFORMATION {
 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
 
 /* Exported object types */
+#ifdef _NTSYSTEM_
 extern POBJECT_TYPE NTSYSAPI CmKeyObjectType;
 extern POBJECT_TYPE NTSYSAPI ExEventObjectType;
 extern POBJECT_TYPE NTSYSAPI ExSemaphoreObjectType;
@@ -7864,6 +7903,30 @@ extern POBJECT_TYPE NTSYSAPI IoFileObjectType;
 extern POBJECT_TYPE NTSYSAPI PsThreadType;
 extern POBJECT_TYPE NTSYSAPI SeTokenObjectType;
 extern POBJECT_TYPE NTSYSAPI PsProcessType;
+#else
+extern POBJECT_TYPE *CmKeyObjectType;
+extern POBJECT_TYPE *IoFileObjectType;
+extern POBJECT_TYPE *ExEventObjectType;
+extern POBJECT_TYPE *ExSemaphoreObjectType;
+extern POBJECT_TYPE *TmTransactionManagerObjectType;
+extern POBJECT_TYPE *TmResourceManagerObjectType;
+extern POBJECT_TYPE *TmEnlistmentObjectType;
+extern POBJECT_TYPE *TmTransactionObjectType;
+extern POBJECT_TYPE *PsProcessType;
+extern POBJECT_TYPE *PsThreadType;
+extern POBJECT_TYPE *SeTokenObjectType;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(CmKeyObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(IoFileObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(ExEventObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(ExSemaphoreObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionManagerObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmResourceManagerObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmEnlistmentObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(PsProcessType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(PsThreadType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(SeTokenObjectType)
+#endif
 
 
 /******************************************************************************
@@ -8339,7 +8402,7 @@ KeRestoreFloatingPointState(PVOID FloatingState)
 #define HIGH_LEVEL              15
 
 #define KI_USER_SHARED_DATA ((ULONG_PTR)(KADDRESS_BASE + 0xFFFE0000))
-extern volatile LARGE_INTEGER KeTickCount;
+extern NTKERNELAPI volatile LARGE_INTEGER KeTickCount;
 
 #define PAUSE_PROCESSOR __yield();
 
@@ -15770,27 +15833,18 @@ DbgSetDebugPrintCallback(
 
 #endif /* !DBG */
 
-#if defined(__GNUC__)
-
-extern NTKERNELAPI BOOLEAN KdDebuggerNotPresent;
-extern NTKERNELAPI BOOLEAN KdDebuggerEnabled;
-#define KD_DEBUGGER_ENABLED KdDebuggerEnabled
-#define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent
-
-#elif defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_WDMDDK_) || defined(_NTOSP_)
-
-extern NTKERNELAPI PBOOLEAN KdDebuggerNotPresent;
-extern NTKERNELAPI PBOOLEAN KdDebuggerEnabled;
-#define KD_DEBUGGER_ENABLED *KdDebuggerEnabled
-#define KD_DEBUGGER_NOT_PRESENT *KdDebuggerNotPresent
-
-#else
-
-extern BOOLEAN KdDebuggerNotPresent;
+#ifdef _NTSYSTEM_
 extern BOOLEAN KdDebuggerEnabled;
 #define KD_DEBUGGER_ENABLED KdDebuggerEnabled
+extern BOOLEAN KdDebuggerNotPresent;
 #define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent
-
+#else
+extern BOOLEAN *KdDebuggerEnabled;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerEnabled)
+#define KD_DEBUGGER_ENABLED (*KdDebuggerEnabled)
+extern BOOLEAN *KdDebuggerNotPresent;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerNotPresent)
+#define KD_DEBUGGER_NOT_PRESENT (*KdDebuggerNotPresent)
 #endif
 
 #if (NTDDI_VERSION >= NTDDI_WIN2K)
index c0a205c..b38a982 100644 (file)
@@ -3654,7 +3654,7 @@ RtlFindActivationContextSectionString(
     _In_ ULONG dwFlags,
     _In_ const GUID *ExtensionGuid,
     _In_ ULONG SectionType,
-    _In_ PUNICODE_STRING SectionName,
+    _In_ const UNICODE_STRING *SectionName,
     _Inout_ PVOID ReturnedData
 );
 
@@ -4419,6 +4419,17 @@ RtlCloneMemoryStream(
 
 #endif // NTOS_MODE_USER
 
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlFindActivationContextSectionGuid(
+    ULONG flags,
+    const GUID *extguid,
+    ULONG section_kind,
+    const GUID *guid,
+    void *ptr
+);
+
 #ifdef __cplusplus
 }
 #endif
index eb5d2f5..3ae6e9a 100644 (file)
@@ -3525,7 +3525,7 @@ NTAPI
 KsMethodHandler(
   _In_ PIRP Irp,
   _In_ ULONG MethodSetsCount,
-  _In_reads_(MethodSetsCount) const PKSMETHOD_SET MethodSet);
+  _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet);
 
 _IRQL_requires_max_(PASSIVE_LEVEL)
 KSDDKAPI
@@ -3534,7 +3534,7 @@ NTAPI
 KsMethodHandlerWithAllocator(
   _In_ PIRP Irp,
   _In_ ULONG MethodSetsCount,
-  _In_reads_(MethodSetsCount) const PKSMETHOD_SET MethodSet,
+  _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet,
   _In_opt_ PFNKSALLOCATOR Allocator,
   _In_opt_ ULONG MethodItemSize);
 
@@ -3576,7 +3576,7 @@ NTAPI
 KsPropertyHandlerWithAllocator(
   _In_ PIRP Irp,
   _In_ ULONG PropertySetsCount,
-  _In_reads_(PropertySetsCount) const PKSPROPERTY_SET PropertySet,
+  _In_reads_(PropertySetsCount) const KSPROPERTY_SET* PropertySet,
   _In_opt_ PFNKSALLOCATOR Allocator,
   _In_opt_ ULONG PropertyItemSize);
 
@@ -3659,7 +3659,7 @@ NTAPI
 KsEnableEventWithAllocator(
   _In_ PIRP Irp,
   _In_ ULONG EventSetsCount,
-  _In_reads_(EventSetsCount) const PKSEVENT_SET EventSet,
+  _In_reads_(EventSetsCount) const KSEVENT_SET* EventSet,
   _Inout_opt_ PLIST_ENTRY EventsList,
   _In_opt_ KSEVENTS_LOCKTYPE EventsFlags,
   _In_opt_ PVOID EventsLock,
@@ -4819,7 +4819,7 @@ DEFINE_GUID(IID_IKsControl, 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0,
 
 DECLARE_INTERFACE_(IKsControl,IUnknown)
 {
-    STDMETHOD_(NTSTATUS, QueryInterface)( THIS_ 
+    STDMETHOD_(NTSTATUS, QueryInterface)( THIS_
         REFIID InterfaceId,
         PVOID* Interface)PURE;
 
diff --git a/include/reactos/libs/fast486/fast486.h b/include/reactos/libs/fast486/fast486.h
new file mode 100644 (file)
index 0000000..339ecb6
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fast486.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _FAST486_H_
+#define _FAST486_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+#ifndef FASTCALL
+#define FASTCALL __fastcall
+#endif
+
+#define FAST486_NUM_GEN_REGS    8
+#define FAST486_NUM_SEG_REGS    6
+#define FAST486_NUM_CTRL_REGS   3
+#define FAST486_NUM_DBG_REGS    6
+#define FAST486_NUM_FPU_REGS    8
+
+#define FAST486_CR0_PE  (1 << 0)
+#define FAST486_CR0_MP  (1 << 1)
+#define FAST486_CR0_EM  (1 << 2)
+#define FAST486_CR0_TS  (1 << 3)
+#define FAST486_CR0_ET  (1 << 4)
+#define FAST486_CR0_NE  (1 << 5)
+#define FAST486_CR0_WP  (1 << 16)
+#define FAST486_CR0_AM  (1 << 18)
+#define FAST486_CR0_NW  (1 << 29)
+#define FAST486_CR0_CD  (1 << 30)
+#define FAST486_CR0_PG  (1 << 31)
+
+#define FAST486_DR4_B0 (1 << 0)
+#define FAST486_DR4_B1 (1 << 1)
+#define FAST486_DR4_B2 (1 << 2)
+#define FAST486_DR4_B3 (1 << 3)
+#define FAST486_DR4_BD (1 << 13)
+#define FAST486_DR4_BS (1 << 14)
+#define FAST486_DR4_BT (1 << 15)
+
+#define FAST486_DR5_L0 (1 << 0)
+#define FAST486_DR5_G0 (1 << 1)
+#define FAST486_DR5_L1 (1 << 2)
+#define FAST486_DR5_G1 (1 << 3)
+#define FAST486_DR5_L2 (1 << 4)
+#define FAST486_DR5_G2 (1 << 5)
+#define FAST486_DR5_L3 (1 << 6)
+#define FAST486_DR5_G3 (1 << 7)
+#define FAST486_DR5_LE (1 << 8)
+#define FAST486_DR5_GE (1 << 9)
+#define FAST486_DR5_GD (1 << 13)
+
+#define FAST486_DBG_BREAK_EXEC 0
+#define FAST486_DBG_BREAK_WRITE 1
+#define FAST486_DBG_BREAK_READWRITE 3
+
+#define FAST486_DR4_RESERVED 0xFFFF1FF0
+#define FAST486_DR5_RESERVED 0x0000DC00
+
+#define FAST486_IDT_TASK_GATE       0x5
+#define FAST486_IDT_INT_GATE        0x6
+#define FAST486_IDT_TRAP_GATE       0x7
+#define FAST486_IDT_INT_GATE_32     0xE
+#define FAST486_IDT_TRAP_GATE_32    0xF
+
+#define FAST486_LDT_SIGNATURE 0x02
+#define FAST486_TSS_SIGNATURE 0x09
+
+#define FAST486_PREFIX_SEG      (1 << 0)
+#define FAST486_PREFIX_OPSIZE   (1 << 1)
+#define FAST486_PREFIX_ADSIZE   (1 << 2)
+#define FAST486_PREFIX_LOCK     (1 << 3)
+#define FAST486_PREFIX_REPNZ    (1 << 4)
+#define FAST486_PREFIX_REP      (1 << 5)
+
+struct _FAST486_STATE;
+typedef struct _FAST486_STATE FAST486_STATE, *PFAST486_STATE;
+
+typedef enum _FAST486_GEN_REGS
+{
+    FAST486_REG_EAX,
+    FAST486_REG_ECX,
+    FAST486_REG_EDX,
+    FAST486_REG_EBX,
+    FAST486_REG_ESP,
+    FAST486_REG_EBP,
+    FAST486_REG_ESI,
+    FAST486_REG_EDI
+} FAST486_GEN_REGS, *PFAST486_GEN_REGS;
+
+typedef enum _FAST486_SEG_REGS
+{
+    FAST486_REG_ES,
+    FAST486_REG_CS,
+    FAST486_REG_SS,
+    FAST486_REG_DS,
+    FAST486_REG_FS,
+    FAST486_REG_GS
+} FAST486_SEG_REGS, *PFAST486_SEG_REGS;
+
+typedef enum _FAST486_CTRL_REGS
+{
+    FAST486_REG_CR0 = 0,
+    FAST486_REG_CR2 = 1,
+    FAST486_REG_CR3 = 2,
+} FAST486_CTRL_REGS, *PFAST486_CTRL_REGS;
+
+typedef enum _FAST486_DBG_REGS
+{
+    FAST486_REG_DR0 = 0,
+    FAST486_REG_DR1 = 1,
+    FAST486_REG_DR2 = 2,
+    FAST486_REG_DR3 = 3,
+    FAST486_REG_DR4 = 4,
+    FAST486_REG_DR5 = 5,
+    FAST486_REG_DR6 = 4, // alias to DR4
+    FAST486_REG_DR7 = 5  // alias to DR5
+} FAST486_DBG_REGS, *PFAST486_DBG_REGS;
+
+typedef enum _FAST486_EXCEPTIONS
+{
+    FAST486_EXCEPTION_DE = 0x00,
+    FAST486_EXCEPTION_DB = 0x01,
+    FAST486_EXCEPTION_BP = 0x03,
+    FAST486_EXCEPTION_OF = 0x04,
+    FAST486_EXCEPTION_BR = 0x05,
+    FAST486_EXCEPTION_UD = 0x06,
+    FAST486_EXCEPTION_NM = 0x07,
+    FAST486_EXCEPTION_DF = 0x08,
+    FAST486_EXCEPTION_TS = 0x0A,
+    FAST486_EXCEPTION_NP = 0x0B,
+    FAST486_EXCEPTION_SS = 0x0C,
+    FAST486_EXCEPTION_GP = 0x0D,
+    FAST486_EXCEPTION_PF = 0x0E,
+    FAST486_EXCEPTION_MF = 0x10,
+    FAST486_EXCEPTION_AC = 0x11,
+    FAST486_EXCEPTION_MC = 0x12
+} FAST486_EXCEPTIONS, *PFAST486_EXCEPTIONS;
+
+typedef enum _FAST486_INT_STATUS
+{
+    FAST486_INT_NONE = 0,
+    FAST486_INT_EXECUTE = 1,
+    FAST486_INT_SIGNAL = 2
+} FAST486_INT_STATUS, *PFAST486_INT_STATUS;
+
+typedef
+VOID
+(NTAPI *FAST486_MEM_READ_PROC)
+(
+    PFAST486_STATE State,
+    ULONG Address,
+    PVOID Buffer,
+    ULONG Size
+);
+
+typedef
+VOID
+(NTAPI *FAST486_MEM_WRITE_PROC)
+(
+    PFAST486_STATE State,
+    ULONG Address,
+    PVOID Buffer,
+    ULONG Size
+);
+
+typedef
+VOID
+(NTAPI *FAST486_IO_READ_PROC)
+(
+    PFAST486_STATE State,
+    ULONG Port,
+    PVOID Buffer,
+    ULONG DataCount,
+    UCHAR DataSize
+);
+
+typedef
+VOID
+(NTAPI *FAST486_IO_WRITE_PROC)
+(
+    PFAST486_STATE State,
+    ULONG Port,
+    PVOID Buffer,
+    ULONG DataCount,
+    UCHAR DataSize
+);
+
+typedef
+VOID
+(NTAPI *FAST486_IDLE_PROC)
+(
+    PFAST486_STATE State
+);
+
+typedef
+VOID
+(NTAPI *FAST486_BOP_PROC)
+(
+    PFAST486_STATE State,
+    UCHAR BopCode
+);
+
+typedef
+UCHAR
+(NTAPI *FAST486_INT_ACK_PROC)
+(
+    PFAST486_STATE State
+);
+
+typedef union _FAST486_REG
+{
+    union
+    {
+        struct
+        {
+            UCHAR LowByte;
+            UCHAR HighByte;
+        };
+        USHORT LowWord;
+    };
+    ULONG Long;
+} FAST486_REG, *PFAST486_REG;
+
+typedef struct _FAST486_SEG_REG
+{
+    USHORT Selector;
+
+    /* Descriptor cache */
+    ULONG Accessed      : 1;
+    ULONG ReadWrite     : 1;
+    ULONG DirConf       : 1;
+    ULONG Executable    : 1;
+    ULONG SystemType    : 1;
+    ULONG Dpl           : 2;
+    ULONG Present       : 1;
+    ULONG Size          : 1;
+    ULONG Limit;
+    ULONG Base;
+} FAST486_SEG_REG, *PFAST486_SEG_REG;
+
+typedef struct
+{
+    USHORT Selector;
+    ULONG Base;
+    ULONG Limit;
+} FAST486_LDT_REG;
+
+typedef struct
+{
+    USHORT Selector;
+    ULONG Base;
+    ULONG Limit;
+    BOOLEAN Busy;
+} FAST486_TASK_REG, *PFAST486_TASK_REG;
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+    ULONG Limit         : 16;
+    ULONG Base          : 16;
+    ULONG BaseMid       : 8;
+    ULONG Accessed      : 1;
+    ULONG ReadWrite     : 1;
+    ULONG DirConf       : 1;
+    ULONG Executable    : 1;
+    ULONG SystemType    : 1;
+    ULONG Dpl           : 2;
+    ULONG Present       : 1;
+    ULONG LimitHigh     : 4;
+    ULONG Avl           : 1;
+    ULONG Reserved      : 1;
+    ULONG Size          : 1;
+    ULONG Granularity   : 1;
+    ULONG BaseHigh      : 8;
+} FAST486_GDT_ENTRY, *PFAST486_GDT_ENTRY;
+
+/* Verify the structure size */
+C_ASSERT(sizeof(FAST486_GDT_ENTRY) == sizeof(ULONGLONG));
+
+typedef struct
+{
+    ULONG Limit         : 16;
+    ULONG Base          : 16;
+    ULONG BaseMid       : 8;
+    ULONG Signature     : 5;
+    ULONG Dpl           : 2;
+    ULONG Present       : 1;
+    ULONG LimitHigh     : 4;
+    ULONG Avl           : 1;
+    ULONG Reserved      : 2;
+    ULONG Granularity   : 1;
+    ULONG BaseHigh      : 8;
+} FAST486_SYSTEM_DESCRIPTOR, *PFAST486_SYSTEM_DESCRIPTOR;
+
+/* Verify the structure size */
+C_ASSERT(sizeof(FAST486_SYSTEM_DESCRIPTOR) == sizeof(ULONGLONG));
+
+typedef struct
+{
+    ULONG Offset : 16;
+    ULONG Selector : 16;
+    ULONG ParamCount : 5;
+    ULONG Reserved : 3;
+    ULONG Type : 4;
+    ULONG SystemType : 1;
+    ULONG Dpl : 2;
+    ULONG Present : 1;
+    ULONG OffsetHigh : 16;
+} FAST486_CALL_GATE, *PFAST486_CALL_GATE;
+
+/* Verify the structure size */
+C_ASSERT(sizeof(FAST486_CALL_GATE) == sizeof(ULONGLONG));
+
+typedef struct
+{
+    ULONG Offset        : 16;
+    ULONG Selector      : 16;
+    ULONG Zero          : 8;
+    ULONG Type          : 4;
+    ULONG Storage       : 1;
+    ULONG Dpl           : 2;
+    ULONG Present       : 1;
+    ULONG OffsetHigh    : 16;
+} FAST486_IDT_ENTRY, *PFAST486_IDT_ENTRY;
+
+/* Verify the structure size */
+C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG));
+
+#pragma pack(pop)
+
+typedef struct _FAST486_TABLE_REG
+{
+    USHORT Size;
+    ULONG Address;
+} FAST486_TABLE_REG, *PFAST486_TABLE_REG;
+
+typedef union _FAST486_FLAGS_REG
+{
+    USHORT LowWord;
+    ULONG Long;
+
+    struct
+    {
+        ULONG Cf        : 1;
+        ULONG AlwaysSet : 1;
+        ULONG Pf        : 1;
+        ULONG Reserved0 : 1;
+        ULONG Af        : 1;
+        ULONG Reserved1 : 1;
+        ULONG Zf        : 1;
+        ULONG Sf        : 1;
+        ULONG Tf        : 1;
+        ULONG If        : 1;
+        ULONG Df        : 1;
+        ULONG Of        : 1;
+        ULONG Iopl      : 2;
+        ULONG Nt        : 1;
+        ULONG Reserved2 : 1;
+        ULONG Rf        : 1;
+        ULONG Vm        : 1;
+        ULONG Ac        : 1;
+
+        // ULONG Reserved : 13;
+    };
+} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG;
+
+typedef struct _FAST486_TSS
+{
+    ULONG Link;
+    ULONG Esp0;
+    ULONG Ss0;
+    ULONG Esp1;
+    ULONG Ss1;
+    ULONG Esp2;
+    ULONG Ss2;
+    ULONG Cr3;
+    ULONG Eip;
+    ULONG Eflags;
+    ULONG Eax;
+    ULONG Ecx;
+    ULONG Edx;
+    ULONG Ebx;
+    ULONG Esp;
+    ULONG Ebp;
+    ULONG Esi;
+    ULONG Edi;
+    ULONG Es;
+    ULONG Cs;
+    ULONG Ss;
+    ULONG Ds;
+    ULONG Fs;
+    ULONG Gs;
+    ULONG Ldtr;
+    ULONG IopbOffset;
+} FAST486_TSS, *PFAST486_TSS;
+
+typedef struct _FAST486_FPU_DATA_REG
+{
+    ULONGLONG Mantissa;
+    USHORT Exponent;
+} FAST486_FPU_DATA_REG, *PFAST486_FPU_DATA_REG;
+
+typedef union _FAST486_FPU_STATUS_REG
+{
+    USHORT Value;
+
+    struct
+    {
+        ULONG Ie : 1;
+        ULONG De : 1;
+        ULONG Ze : 1;
+        ULONG Oe : 1;
+        ULONG Ue : 1;
+        ULONG Pe : 1;
+        ULONG Sf : 1;
+        ULONG Es : 1;
+        ULONG Code0 : 1;
+        ULONG Code1 : 1;
+        ULONG Code2 : 1;
+        ULONG Top : 3;
+        ULONG Code3 : 1;
+        ULONG Busy : 1;
+    };
+} FAST486_FPU_STATUS_REG, *PFAST486_FPU_STATUS_REG;
+
+typedef union _FAST486_FPU_CONTROL_REG
+{
+    USHORT Value;
+
+    struct
+    {
+        ULONG Im : 1;
+        ULONG Dm : 1;
+        ULONG Zm : 1;
+        ULONG Om : 1;
+        ULONG Um : 1;
+        ULONG Pm : 1;
+        ULONG Reserved : 2;
+        ULONG Pc : 2;
+        ULONG Rc : 2;
+        ULONG Inf : 1;
+        // ULONG Reserved1 : 3;
+    };
+} FAST486_FPU_CONTROL_REG, *PFAST486_FPU_CONTROL_REG;
+
+struct _FAST486_STATE
+{
+    FAST486_MEM_READ_PROC MemReadCallback;
+    FAST486_MEM_WRITE_PROC MemWriteCallback;
+    FAST486_IO_READ_PROC IoReadCallback;
+    FAST486_IO_WRITE_PROC IoWriteCallback;
+    FAST486_IDLE_PROC IdleCallback;
+    FAST486_BOP_PROC BopCallback;
+    FAST486_INT_ACK_PROC IntAckCallback;
+    FAST486_REG GeneralRegs[FAST486_NUM_GEN_REGS];
+    FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS];
+    FAST486_REG InstPtr, SavedInstPtr;
+    FAST486_FLAGS_REG Flags;
+    FAST486_TABLE_REG Gdtr, Idtr;
+    FAST486_LDT_REG Ldtr;
+    FAST486_TASK_REG TaskReg;
+    UCHAR Cpl;
+    ULONG ControlRegisters[FAST486_NUM_CTRL_REGS];
+    ULONG DebugRegisters[FAST486_NUM_DBG_REGS];
+    ULONG ExceptionCount;
+    ULONG PrefixFlags;
+    FAST486_SEG_REGS SegmentOverride;
+    FAST486_INT_STATUS IntStatus;
+    UCHAR PendingIntNum;
+    PULONG Tlb;
+    FAST486_FPU_DATA_REG FpuRegisters[FAST486_NUM_FPU_REGS];
+    FAST486_FPU_STATUS_REG FpuStatus;
+    FAST486_FPU_CONTROL_REG FpuControl;
+    USHORT FpuTag;
+};
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+NTAPI
+Fast486Initialize(PFAST486_STATE         State,
+                  FAST486_MEM_READ_PROC  MemReadCallback,
+                  FAST486_MEM_WRITE_PROC MemWriteCallback,
+                  FAST486_IO_READ_PROC   IoReadCallback,
+                  FAST486_IO_WRITE_PROC  IoWriteCallback,
+                  FAST486_IDLE_PROC      IdleCallback,
+                  FAST486_BOP_PROC       BopCallback,
+                  FAST486_INT_ACK_PROC   IntAckCallback,
+                  PULONG                 Tlb);
+
+VOID
+NTAPI
+Fast486Reset(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486Continue(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486StepInto(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486StepOver(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486StepOut(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486DumpState(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486Interrupt(PFAST486_STATE State, UCHAR Number);
+
+VOID
+NTAPI
+Fast486InterruptSignal(PFAST486_STATE State);
+
+VOID
+NTAPI
+Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset);
+
+VOID
+NTAPI
+Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset);
+
+VOID
+NTAPI
+Fast486SetSegment
+(
+    PFAST486_STATE State,
+    FAST486_SEG_REGS Segment,
+    USHORT Selector
+);
+
+#endif // _FAST486_H_
+
+/* EOF */
index 6aa15dd..8337b41 100644 (file)
@@ -120,7 +120,7 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
 #define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(4)) : "%esp", "memory")
 
 /* CLANG doesn't have asm goto! */
-#define _SEH3$_ASM_GOTO(_Label, ...)
+#define _SEH3$_ASM_GOTO(...)
 
 int
 __attribute__((regparm(3)))
@@ -167,7 +167,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
 /* This will make GCC use ebp, even if it was disabled by -fomit-frame-pointer */
 #define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(0)) : "%esp", "memory")
 
-#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
+#define _SEH3$_ASM_GOTO(...) asm goto ("#\n" : : : "memory" : __VA_ARGS__)
 
 #ifdef __cplusplus
 #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
@@ -177,7 +177,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
               : \
               : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c"(__builtin_alloca(0)) \
               : "eax", "edx", "memory" \
-              : _SEH3$_l_HandlerTarget, _SEH3$_l_FilterOrFinally)
+              : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
 
 #else
 #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
@@ -187,7 +187,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
               : \
               : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \
               : "eax", "edx", "ecx", "memory" \
-              : _SEH3$_l_HandlerTarget)
+              : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
 #endif
 
 /* This is an asm wrapper around _SEH3$_RegisterFrame */
@@ -202,10 +202,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
    around into places that are never executed. */
 #define _SEH3$_SCARE_GCC() \
         void *plabel; \
-        _SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry); \
-        _SEH3$_ASM_GOTO(_SEH3$_l_HandlerTarget); \
-        _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
-        asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException) \
+        _SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally); \
+        asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException), "p"(&&_SEH3$_l_FilterOrFinally) \
                       : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory" ); \
         goto _SEH3$_l_OnException;
 
diff --git a/include/reactos/subsys/win/vdm.h b/include/reactos/subsys/win/vdm.h
new file mode 100644 (file)
index 0000000..e493dcd
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Base API Server DLL
+ * FILE:            include/reactos/subsys/win/vdm.h
+ * PURPOSE:         Public definitions for the Virtual Dos Machine
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+#ifndef _VDM_H
+#define _VDM_H
+
+#pragma once
+
+/* CONSTANTS & TYPES **********************************************************/
+
+typedef enum _VDM_ENTRY_CODE
+{
+    VdmEntryUndo,
+    VdmEntryUpdateProcess,
+    VdmEntryUpdateControlCHandler
+} VDM_ENTRY_CODE;
+
+//
+// Undo States
+//
+#define VDM_UNDO_PARTIAL    0x01
+#define VDM_UNDO_FULL       0x02
+#define VDM_UNDO_REUSE      0x04
+#define VDM_UNDO_COMPLETED  0x08
+
+//
+// Binary Types to share with VDM
+//
+#define BINARY_TYPE_EXE     0x01
+#define BINARY_TYPE_COM     0x02
+#define BINARY_TYPE_PIF     0x03
+#define BINARY_TYPE_DOS     0x10
+#define BINARY_TYPE_SEPARATE_WOW 0x20
+#define BINARY_TYPE_WOW     0x40
+#define BINARY_TYPE_WOW_EX  0x80
+
+//
+// VDM States
+//
+#define VDM_NOT_LOADED      0x01
+#define VDM_NOT_READY       0x02
+#define VDM_READY           0x04
+
+//
+// VDM Flags
+//
+#define VDM_FLAG_FIRST_TASK     0x01
+#define VDM_FLAG_WOW            0x02
+#define VDM_FLAG_DOS            0x04
+#define VDM_FLAG_RETRY          0x08
+#define VDM_INC_REENTER_COUNT   0x10
+#define VDM_DEC_REENTER_COUNT   0x20
+#define VDM_FLAG_NESTED_TASK    0x40
+#define VDM_FLAG_DONT_WAIT      0x80
+#define VDM_GET_FIRST_COMMAND   0x100
+#define VDM_GET_ENVIRONMENT     0x400
+#define VDM_FLAG_SEPARATE_WOW   0x800
+#define VDM_LIST_WOW_PROCESSES  0x1000
+#define VDM_LIST_WOW_TASKS      0x4000
+#define VDM_ADD_WOW_TASK        0x8000
+
+typedef struct
+{
+    ULONG TaskId;
+    ULONG CreationFlags;
+    ULONG ExitCode;
+    ULONG CodePage;
+    HANDLE StdIn;
+    HANDLE StdOut;
+    HANDLE StdErr;
+    LPSTR CmdLine;
+    LPSTR AppName;
+    LPSTR PifFile;
+    LPSTR CurDirectory;
+    LPSTR Env;
+    ULONG EnvLen;
+    STARTUPINFOA StartupInfo;
+    LPSTR Desktop;
+    ULONG DesktopLen;
+    LPSTR Title;
+    ULONG TitleLen;
+    LPVOID Reserved;
+    ULONG ReservedLen;
+    USHORT CmdLen;
+    USHORT AppLen;
+    USHORT PifLen;
+    USHORT CurDirectoryLen;
+    USHORT VDMState;
+    USHORT CurrentDrive;
+    BOOLEAN ComingFromBat;
+} VDM_COMMAND_INFO, *PVDM_COMMAND_INFO;
+
+
+/* FUNCTION PROTOTYPES ********************************************************/
+
+BOOL
+WINAPI
+GetNextVDMCommand(
+    IN OUT PVDM_COMMAND_INFO CommandData OPTIONAL
+);
+
+VOID
+WINAPI
+ExitVDM(
+    IN BOOL IsWow,
+    IN ULONG iWowTask
+);
+
+#endif // _VDM_H
+
+/* EOF */
index 7b42643..30d8e9e 100644 (file)
@@ -278,7 +278,7 @@ ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset );
 #endif /* HAVE_PWRITE */
 #endif /* __REACTOS__ */
 
-#ifdef WIN32
+#ifdef _WIN32
 #ifndef HAVE_SIGSETJMP
 # include <setjmp.h>
 typedef jmp_buf sigjmp_buf;
@@ -343,9 +343,9 @@ extern int spawnvp(int mode, const char *cmdname, const char * const argv[]);
 #if defined(_MSC_VER) || (defined(__i386__) && defined(__GNUC__) && !defined(WINE_PORT_NO_INTERLOCKED))
 
 #define interlocked_cmpxchg InterlockedCompareExchange
-#define interlocked_cmpxchg_ptr InterlockedCompareExchangePtr
+#define interlocked_cmpxchg_ptr InterlockedCompareExchangePointer
 #define interlocked_xchg InterlockedExchange
-#define interlocked_xchg_ptr InterlockedExchangePtr
+#define interlocked_xchg_ptr InterlockedExchangePointer
 #define interlocked_xchg_add InterlockedExchangeAdd
 
 
index 9192381..5e998d8 100644 (file)
@@ -6,7 +6,7 @@ $if (_NTIFS_)
     (((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \
 )
 
-extern ULONG CcFastMdlReadWait;
+extern NTKERNELAPI ULONG CcFastMdlReadWait;
 
 #if (NTDDI_VERSION >= NTDDI_WIN2K)
 
index ae252d3..548dcee 100644 (file)
@@ -271,7 +271,7 @@ typedef struct _RESOURCE_PERFORMANCE_DATA {
 
 /* Global debug flag */
 #if DEVL
-extern ULONG NtGlobalFlag;
+extern NTKERNELAPI ULONG NtGlobalFlag;
 #define IF_NTOS_DEBUG(FlagName) if (NtGlobalFlag & (FLG_##FlagName))
 #else
 #define IF_NTOS_DEBUG(FlagName) if(FALSE)
index b98897c..24465b8 100644 (file)
@@ -1580,26 +1580,31 @@ FsRtlRemovePerFileObjectContext(
     (InterlockedDecrement((LONG volatile *)&((FL)->LockRequestsInProgress)));\
 }
 
-/* GCC compatible definition, MS one is retarded */
-extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray;
-#define LEGAL_ANSI_CHARACTER_ARRAY        FsRtlLegalAnsiCharacterArray
+#ifdef _NTSYSTEM_
+extern const UCHAR * const FsRtlLegalAnsiCharacterArray;
+#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray
+#else
+extern const UCHAR * const *FsRtlLegalAnsiCharacterArray;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(FsRtlLegalAnsiCharacterArray)
+#define LEGAL_ANSI_CHARACTER_ARRAY (*FsRtlLegalAnsiCharacterArray)
+#endif
 
 #define FsRtlIsAnsiCharacterWild(C) (                                       \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \
 )
 
 #define FsRtlIsAnsiCharacterLegalFat(C, WILD) (                                \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_FAT_LEGAL) |       \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_FAT_LEGAL) |       \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
 #define FsRtlIsAnsiCharacterLegalHpfs(C, WILD) (                               \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) |      \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) |      \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
 #define FsRtlIsAnsiCharacterLegalNtfs(C, WILD) (                               \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) |      \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) |      \
                                         ((WILD) ? FSRTL_WILD_CHARACTER : 0 ))  \
 )
 
@@ -1627,7 +1632,7 @@ extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray;
 #define FsRtlIsUnicodeCharacterWild(C) (                                    \
     (((C) >= 0x40) ?                                                        \
     FALSE :                                                                 \
-    FlagOn(FsRtlLegalAnsiCharacterArray[(C)], FSRTL_WILD_CHARACTER ))       \
+    FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(C)], FSRTL_WILD_CHARACTER ))       \
 )
 
 #define FsRtlInitPerFileContext( _fc, _owner, _inst, _cb)   \
index 941daef..db30806 100644 (file)
@@ -269,14 +269,12 @@ typedef struct {
 #endif
 } HAL_DISPATCH, *PHAL_DISPATCH;
 
-/* GCC/MSVC and WDK compatible declaration */
-extern NTKERNELAPI HAL_DISPATCH HalDispatchTable;
-
-#if defined(_NTOSKRNL_) || defined(_BLDR_)
+#ifdef _NTSYSTEM_
+extern HAL_DISPATCH HalDispatchTable;
 #define HALDISPATCH (&HalDispatchTable)
 #else
-/* This is a WDK compatibility definition */
-#define HalDispatchTable (&HalDispatchTable)
+extern PHAL_DISPATCH HalDispatchTable;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(HalDispatchTable)
 #define HALDISPATCH HalDispatchTable
 #endif
 
index 2920636..27ff06a 100644 (file)
@@ -17,7 +17,7 @@ $if (_WDMDDK_)
 #define HIGH_LEVEL              15
 
 #define KI_USER_SHARED_DATA ((ULONG_PTR)(KADDRESS_BASE + 0xFFFE0000))
-extern volatile LARGE_INTEGER KeTickCount;
+extern NTKERNELAPI volatile LARGE_INTEGER KeTickCount;
 
 #define PAUSE_PROCESSOR __yield();
 
index 4b37515..41954a5 100644 (file)
@@ -7037,35 +7037,13 @@ FsRtlNotifyStreamFileObject(
   _In_ BOOLEAN SafeToRecurse);
 #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
 
-#define DO_VERIFY_VOLUME                    0x00000002
-#define DO_BUFFERED_IO                      0x00000004
-#define DO_EXCLUSIVE                        0x00000008
-#define DO_DIRECT_IO                        0x00000010
-#define DO_MAP_IO_BUFFER                    0x00000020
-#define DO_DEVICE_HAS_NAME                  0x00000040
-#define DO_DEVICE_INITIALIZING              0x00000080
-#define DO_SYSTEM_BOOT_PARTITION            0x00000100
-#define DO_LONG_TERM_REQUESTS               0x00000200
-#define DO_NEVER_LAST_DEVICE                0x00000400
-#define DO_SHUTDOWN_REGISTERED              0x00000800
-#define DO_BUS_ENUMERATED_DEVICE            0x00001000
-#define DO_POWER_PAGABLE                    0x00002000
-#define DO_POWER_INRUSH                     0x00004000
-#define DO_LOW_PRIORITY_FILESYSTEM          0x00010000
-#define DO_SUPPORTS_TRANSACTIONS            0x00040000
-#define DO_FORCE_NEITHER_IO                 0x00080000
-#define DO_VOLUME_DEVICE_OBJECT             0x00100000
-#define DO_SYSTEM_SYSTEM_PARTITION          0x00200000
-#define DO_SYSTEM_CRITICAL_PARTITION        0x00400000
-#define DO_DISALLOW_EXECUTE                 0x00800000
-
-extern KSPIN_LOCK                   IoStatisticsLock;
-extern ULONG                        IoReadOperationCount;
-extern ULONG                        IoWriteOperationCount;
-extern ULONG                        IoOtherOperationCount;
-extern LARGE_INTEGER                IoReadTransferCount;
-extern LARGE_INTEGER                IoWriteTransferCount;
-extern LARGE_INTEGER                IoOtherTransferCount;
+extern NTKERNELAPI KSPIN_LOCK    IoStatisticsLock;
+extern NTKERNELAPI ULONG         IoReadOperationCount;
+extern NTKERNELAPI ULONG         IoWriteOperationCount;
+extern NTKERNELAPI ULONG         IoOtherOperationCount;
+extern NTKERNELAPI LARGE_INTEGER IoReadTransferCount;
+extern NTKERNELAPI LARGE_INTEGER IoWriteTransferCount;
+extern NTKERNELAPI LARGE_INTEGER IoOtherTransferCount;
 
 #define IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE    64
 #define IO_FILE_OBJECT_PAGED_POOL_CHARGE        1024
index e05c865..b5e908b 100644 (file)
@@ -119,27 +119,18 @@ DbgSetDebugPrintCallback(
 
 #endif /* !DBG */
 
-#if defined(__GNUC__)
-
-extern NTKERNELAPI BOOLEAN KdDebuggerNotPresent;
-extern NTKERNELAPI BOOLEAN KdDebuggerEnabled;
-#define KD_DEBUGGER_ENABLED KdDebuggerEnabled
-#define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent
-
-#elif defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_WDMDDK_) || defined(_NTOSP_)
-
-extern NTKERNELAPI PBOOLEAN KdDebuggerNotPresent;
-extern NTKERNELAPI PBOOLEAN KdDebuggerEnabled;
-#define KD_DEBUGGER_ENABLED *KdDebuggerEnabled
-#define KD_DEBUGGER_NOT_PRESENT *KdDebuggerNotPresent
-
-#else
-
-extern BOOLEAN KdDebuggerNotPresent;
+#ifdef _NTSYSTEM_
 extern BOOLEAN KdDebuggerEnabled;
 #define KD_DEBUGGER_ENABLED KdDebuggerEnabled
+extern BOOLEAN KdDebuggerNotPresent;
 #define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent
-
+#else
+extern BOOLEAN *KdDebuggerEnabled;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerEnabled)
+#define KD_DEBUGGER_ENABLED (*KdDebuggerEnabled)
+extern BOOLEAN *KdDebuggerNotPresent;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerNotPresent)
+#define KD_DEBUGGER_NOT_PRESENT (*KdDebuggerNotPresent)
 #endif
 
 #if (NTDDI_VERSION >= NTDDI_WIN2K)
index 1ef6473..7b14d0a 100644 (file)
@@ -987,6 +987,7 @@ extern NTSYSAPI volatile CCHAR KeNumberProcessors;
 extern NTSYSAPI CCHAR KeNumberProcessors;
 #else
 extern PCCHAR KeNumberProcessors;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors)
 #endif
 
 $endif (_WDMDDK_)
index 2b98aee..ae665cc 100644 (file)
@@ -147,8 +147,11 @@ typedef enum _MM_SYSTEM_SIZE {
   MmLargeSystem
 } MM_SYSTEMSIZE;
 
-extern NTKERNELAPI BOOLEAN Mm64BitPhysicalAddress;
-extern PVOID MmBadPointer;
+#ifndef _NTSYSTEM_
+extern PBOOLEAN Mm64BitPhysicalAddress;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(Mm64BitPhysicalAddress)
+#endif
+extern NTKERNELAPI PVOID MmBadPointer;
 
 $endif (_WDMDDK_)
 $if (_NTDDK_)
index dfff253..6895789 100644 (file)
@@ -1124,13 +1124,14 @@ HalGetDmaAlignmentRequirement(
 #define HalGetDmaAlignmentRequirement() 1L
 #endif
 
-extern NTKERNELAPI PUSHORT NlsOemLeadByteInfo;
-#define NLS_OEM_LEAD_BYTE_INFO            NlsOemLeadByteInfo
-
-#ifdef NLS_MB_CODE_PAGE_TAG
-#undef NLS_MB_CODE_PAGE_TAG
+#ifdef _NTSYSTEM_
+extern PUSHORT NlsOemLeadByteInfo;
+#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo
+#else
+extern PUSHORT *NlsOemLeadByteInfo;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsOemLeadByteInfo)
+#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo)
 #endif
-#define NLS_MB_CODE_PAGE_TAG              NlsMbOemCodePageTag
 
 #if (NTDDI_VERSION >= NTDDI_VISTA)
 
index 7063ab1..482ab19 100644 (file)
@@ -125,6 +125,7 @@ typedef struct _OBJECT_NAME_INFORMATION {
 } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
 
 /* Exported object types */
+#ifdef _NTSYSTEM_
 extern POBJECT_TYPE NTSYSAPI CmKeyObjectType;
 extern POBJECT_TYPE NTSYSAPI ExEventObjectType;
 extern POBJECT_TYPE NTSYSAPI ExSemaphoreObjectType;
@@ -132,6 +133,30 @@ extern POBJECT_TYPE NTSYSAPI IoFileObjectType;
 extern POBJECT_TYPE NTSYSAPI PsThreadType;
 extern POBJECT_TYPE NTSYSAPI SeTokenObjectType;
 extern POBJECT_TYPE NTSYSAPI PsProcessType;
+#else
+extern POBJECT_TYPE *CmKeyObjectType;
+extern POBJECT_TYPE *IoFileObjectType;
+extern POBJECT_TYPE *ExEventObjectType;
+extern POBJECT_TYPE *ExSemaphoreObjectType;
+extern POBJECT_TYPE *TmTransactionManagerObjectType;
+extern POBJECT_TYPE *TmResourceManagerObjectType;
+extern POBJECT_TYPE *TmEnlistmentObjectType;
+extern POBJECT_TYPE *TmTransactionObjectType;
+extern POBJECT_TYPE *PsProcessType;
+extern POBJECT_TYPE *PsThreadType;
+extern POBJECT_TYPE *SeTokenObjectType;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(CmKeyObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(IoFileObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(ExEventObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(ExSemaphoreObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionManagerObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmResourceManagerObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmEnlistmentObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionObjectType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(PsProcessType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(PsThreadType)
+__CREATE_NTOS_DATA_IMPORT_ALIAS(SeTokenObjectType)
+#endif
 
 $endif (_WDMDDK_)
 $if (_NTIFS_)
index 0b61c72..fef0604 100644 (file)
@@ -197,11 +197,19 @@ typedef struct _EXCEPTION_POINTERS {
   PCONTEXT ContextRecord;
 } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
 
-/* MS definition is broken! */
-extern BOOLEAN NTSYSAPI NlsMbCodePageTag;
-extern BOOLEAN NTSYSAPI NlsMbOemCodePageTag;
+#ifdef _NTSYSTEM_
+extern BOOLEAN NlsMbCodePageTag;
 #define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag
+extern BOOLEAN NlsMbOemCodePageTag;
 #define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
+#else
+extern BOOLEAN *NlsMbCodePageTag;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbCodePageTag)
+#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag)
+extern BOOLEAN *NlsMbOemCodePageTag;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbOemCodePageTag)
+#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag)
+#endif
 
 #define SHORT_LEAST_SIGNIFICANT_BIT       0
 #define SHORT_MOST_SIGNIFICANT_BIT        1
index 44e5fed..c7e2766 100644 (file)
@@ -588,4 +588,5 @@ SeLocateProcessImageName(
     ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken )
 
 extern NTKERNELAPI PSE_EXPORTS SeExports;
+
 $endif (_NTIFS_)
index fa47215..e525303 100644 (file)
@@ -82,10 +82,13 @@ extern "C" {
 #endif
 
 /* For ReactOS */
-#if !defined(_NTOSKRNL_) && !defined(_BLDR_)
+#if !defined(_NTOSKRNL_) && !defined(_BLDR_) && !defined(_NTSYSTEM_)
 #define NTKERNELAPI DECLSPEC_IMPORT
 #else
 #define NTKERNELAPI
+#ifndef _NTSYSTEM_
+#define _NTSYSTEM_
+#endif
 #endif
 
 #if defined(_X86_) && !defined(_NTHAL_)
@@ -129,6 +132,29 @@ extern "C" {
 #define ALLOC_DATA_PRAGMA 1
 #endif
 
+#endif /* _MSC_VER */
+
+/* These macros are used to create aliases for imported data. We need to do
+   this to have declarations that are compatible with MS DDK */
+#ifdef _M_IX86
+#define __SYMBOL(_Name) "_"#_Name
+#define __IMPORTSYMBOL(_Name) "__imp__"#_Name
+#define __IMPORTNAME(_Name) _imp__##_Name
+#else
+#define __SYMBOL(_Name) #_Name
+#define __IMPORTSYMBOL(_Name) "__imp_"#_Name
+#define __IMPORTNAME(_Name) __imp_##_Name
+#endif
+#ifdef _MSC_VER
+#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \
+    __pragma(comment(linker, "/alternatename:"__SYMBOL(_Name) "=" __IMPORTSYMBOL(_Name)))
+#else /* !_MSC_VER */
+#ifndef __STRINGIFY
+#define __STRINGIFY(_exp) #_exp
+#endif
+#define _Pragma_redefine_extname(_Name, _Target) _Pragma(__STRINGIFY(redefine_extname _Name _Target))
+#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \
+    _Pragma_redefine_extname(_Name,__IMPORTNAME(_Name))
 #endif
 
 #if defined(_WIN64)
index 8918d67..a030ad1 100644 (file)
@@ -11,6 +11,7 @@ add_subdirectory(cryptlib)
 #add_subdirectory(dnslib) Nothing links to this lib.
 add_subdirectory(drivers)
 add_subdirectory(epsapi)
+add_subdirectory(fast486)
 add_subdirectory(fslib)
 add_subdirectory(lsalib)
 add_subdirectory(ppcmmu)
diff --git a/lib/fast486/CMakeLists.txt b/lib/fast486/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2fbdb31
--- /dev/null
@@ -0,0 +1,12 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486)
+
+list(APPEND SOURCE
+    fast486.c
+    opcodes.c
+    opgroups.c
+    extraops.c
+    common.c
+    fpu.c)
+
+add_library(fast486 ${SOURCE})
diff --git a/lib/fast486/COPYING b/lib/fast486/COPYING
new file mode 100644 (file)
index 0000000..d159169
--- /dev/null
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/lib/fast486/common.c b/lib/fast486/common.c
new file mode 100644 (file)
index 0000000..36f026e
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "common.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN
+Fast486ReadMemory(PFAST486_STATE State,
+                  FAST486_SEG_REGS SegmentReg,
+                  ULONG Offset,
+                  BOOLEAN InstFetch,
+                  PVOID Buffer,
+                  ULONG Size)
+{
+    ULONG LinearAddress;
+    PFAST486_SEG_REG CachedDescriptor;
+
+    ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
+
+    /* Get the cached descriptor */
+    CachedDescriptor = &State->SegmentRegs[SegmentReg];
+
+    if ((Offset + Size - 1) > CachedDescriptor->Limit)
+    {
+        /* Read beyond limit */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[0] & FAST486_CR0_PE)
+    {
+        /* Privilege checks */
+
+        if (!CachedDescriptor->Present)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_NP);
+            return FALSE;
+        }
+
+        if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
+            || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+
+        if (InstFetch)
+        {
+            if (!CachedDescriptor->Executable)
+            {
+                /* Data segment not executable */
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+        }
+        else
+        {
+            if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
+            {
+                /* Code segment not readable */
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+        }
+    }
+
+    /* Find the linear address */
+    LinearAddress = CachedDescriptor->Base + Offset;
+
+    /* Read from the linear address */
+    return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
+}
+
+BOOLEAN
+Fast486WriteMemory(PFAST486_STATE State,
+                   FAST486_SEG_REGS SegmentReg,
+                   ULONG Offset,
+                   PVOID Buffer,
+                   ULONG Size)
+{
+    ULONG LinearAddress;
+    PFAST486_SEG_REG CachedDescriptor;
+
+    ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
+
+    /* Get the cached descriptor */
+    CachedDescriptor = &State->SegmentRegs[SegmentReg];
+
+    if ((Offset + Size - 1) > CachedDescriptor->Limit)
+    {
+        /* Write beyond limit */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[0] & FAST486_CR0_PE)
+    {
+        /* Privilege checks */
+
+        if (!CachedDescriptor->Present)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_NP);
+            return FALSE;
+        }
+
+        if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+            || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+
+        if (CachedDescriptor->Executable)
+        {
+            /* Code segment not writable */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+        else if (!CachedDescriptor->ReadWrite)
+        {
+            /* Data segment not writeable */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+    }
+
+    /* Find the linear address */
+    LinearAddress = CachedDescriptor->Base + Offset;
+
+    /* Write to the linear address */
+    return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size);
+}
+
+BOOLEAN
+Fast486InterruptInternal(PFAST486_STATE State,
+                         USHORT SegmentSelector,
+                         ULONG Offset,
+                         BOOLEAN InterruptGate)
+{
+    /* Check for protected mode */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    {
+        FAST486_TSS Tss;
+        USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
+        ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
+
+        /* Check if the interrupt handler is more privileged */
+        if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
+        {
+            /* Read the TSS */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->TaskReg.Base,
+                                         &Tss,
+                                         sizeof(Tss)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Check the new (higher) privilege level */
+            switch (GET_SEGMENT_RPL(SegmentSelector))
+            {
+                case 0:
+                {
+                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0))
+                    {
+                        /* Exception occurred */
+                        return FALSE;
+                    }
+                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0;
+
+                    break;
+                }
+
+                case 1:
+                {
+                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1))
+                    {
+                        /* Exception occurred */
+                        return FALSE;
+                    }
+                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1;
+
+                    break;
+                }
+
+                case 2:
+                {
+                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2))
+                    {
+                        /* Exception occurred */
+                        return FALSE;
+                    }
+                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2;
+
+                    break;
+                }
+
+                default:
+                {
+                    /* Should never reach here! */
+                    ASSERT(FALSE);
+                }
+            }
+
+            /* Push SS selector */
+            if (!Fast486StackPush(State, OldSs)) return FALSE;
+
+            /* Push stack pointer */
+            if (!Fast486StackPush(State, OldEsp)) return FALSE;
+        }
+    }
+    else
+    {
+        if (State->SegmentRegs[FAST486_REG_CS].Size)
+        {
+            /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
+            State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
+        }
+    }
+
+    /* Push EFLAGS */
+    if (!Fast486StackPush(State, State->Flags.Long)) return FALSE;
+
+    /* Push CS selector */
+    if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) return FALSE;
+
+    /* Push the instruction pointer */
+    if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;
+
+    if (InterruptGate)
+    {
+        /* Disable interrupts after a jump to an interrupt gate handler */
+        State->Flags.If = FALSE;
+    }
+
+    /* Load new CS */
+    if (!Fast486LoadSegment(State, FAST486_REG_CS, SegmentSelector))
+    {
+        /* An exception occurred during the jump */
+        return FALSE;
+    }
+
+    if (State->SegmentRegs[FAST486_REG_CS].Size)
+    {
+        /* 32-bit code segment, use EIP */
+        State->InstPtr.Long = Offset;
+    }
+    else
+    {
+        /* 16-bit code segment, use IP */
+        State->InstPtr.LowWord = LOWORD(Offset);
+    }
+
+    return TRUE;
+}
+
+VOID
+FASTCALL
+Fast486ExceptionWithErrorCode(PFAST486_STATE State,
+                              FAST486_EXCEPTIONS ExceptionCode,
+                              ULONG ErrorCode)
+{
+    FAST486_IDT_ENTRY IdtEntry;
+
+    /* Increment the exception count */
+    State->ExceptionCount++;
+
+    /* Check if the exception occurred more than once */
+    if (State->ExceptionCount > 1)
+    {
+        /* Then this is a double fault */
+        ExceptionCode = FAST486_EXCEPTION_DF;
+    }
+
+    /* Check if this is a triple fault */
+    if (State->ExceptionCount == 3)
+    {
+        /* Reset the CPU */
+        Fast486Reset(State);
+        return;
+    }
+
+    /* Restore the IP to the saved IP */
+    State->InstPtr = State->SavedInstPtr;
+
+    if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry))
+    {
+        /*
+         * If this function failed, that means Fast486Exception
+         * was called again, so just return in this case.
+         */
+        return;
+    }
+
+    /* Perform the interrupt */
+    if (!Fast486InterruptInternal(State,
+                                  IdtEntry.Selector,
+                                  MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
+                                  IdtEntry.Type))
+    {
+        /*
+         * If this function failed, that means Fast486Exception
+         * was called again, so just return in this case.
+         */
+        return;
+    }
+
+    if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode)
+        && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
+    {
+        /* Push the error code */
+        if (!Fast486StackPush(State, ErrorCode))
+        {
+            /*
+             * If this function failed, that means Fast486Exception
+             * was called again, so just return in this case.
+             */
+            return;
+        }
+    }
+
+    /* Reset the exception count */
+    State->ExceptionCount = 0;
+}
+
+/* EOF */
diff --git a/lib/fast486/common.h b/lib/fast486/common.h
new file mode 100644 (file)
index 0000000..1bfdb31
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+#define SIGN_FLAG_BYTE  0x80
+#define SIGN_FLAG_WORD  0x8000
+#define SIGN_FLAG_LONG  0x80000000
+#define REAL_MODE_FLAGS_MASK 0x57FD5
+#define PROT_MODE_FLAGS_MASK 0x50DD5
+
+/* Block size for string operations */
+#define STRING_BLOCK_SIZE 4096
+
+#define GET_SEGMENT_RPL(s)          ((s) & 3)
+#define GET_SEGMENT_INDEX(s)        ((s) & 0xFFF8)
+#define SEGMENT_TABLE_INDICATOR     (1 << 2)
+#define EXCEPTION_HAS_ERROR_CODE(x) (((x) == 8) || ((x) >= 10 && (x) <= 14))
+
+#define NO_LOCK_PREFIX()\
+if (State->PrefixFlags & FAST486_PREFIX_LOCK)\
+{\
+    Fast486Exception(State, FAST486_EXCEPTION_UD);\
+    return FALSE;\
+}
+
+#define TOGGLE_OPSIZE(x)\
+    if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) x = !x;
+
+#define TOGGLE_ADSIZE(x)\
+    if (State->PrefixFlags & FAST486_PREFIX_ADSIZE) x = !x;
+
+#define SWAP(x, y) { (x) ^= (y); (y) ^= (x); (x) ^= (y); }
+
+#define ALIGNMENT_CHECK(x, a) if (State->Flags.Ac \
+                                  && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_AM)\
+                                  && (State->Cpl == 3)\
+                                  && (((x) % (a)) != 0))\
+{\
+    Fast486Exception(State, FAST486_EXCEPTION_AC);\
+    return FALSE;\
+}
+
+#define PAGE_ALIGN(x)   ((x) & 0xFFFFF000)
+#define PAGE_OFFSET(x)  ((x) & 0x00000FFF)
+#define GET_ADDR_PDE(x) ((x) >> 22)
+#define GET_ADDR_PTE(x) (((x) >> 12) & 0x3FF)
+#define INVALID_TLB_FIELD 0xFFFFFFFF
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE   4096
+#endif
+
+typedef struct _FAST486_MOD_REG_RM
+{
+    FAST486_GEN_REGS Register;
+    BOOLEAN Memory;
+    union
+    {
+        FAST486_GEN_REGS SecondRegister;
+        ULONG MemoryAddress;
+    };
+} FAST486_MOD_REG_RM, *PFAST486_MOD_REG_RM;
+
+#pragma pack(push, 1)
+
+typedef union _FAST486_PAGE_DIR
+{
+    struct
+    {
+        ULONG Present       : 1;
+        ULONG Writeable     : 1;
+        ULONG Usermode      : 1;
+        ULONG WriteThrough  : 1;
+        ULONG NoCache       : 1;
+        ULONG Accessed      : 1;
+        ULONG AlwaysZero    : 1;
+        ULONG Size          : 1;
+        ULONG Unused        : 4;
+        ULONG TableAddress  : 20;
+    };
+    ULONG Value;
+} FAST486_PAGE_DIR, *PFAST486_PAGE_DIR;
+
+C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
+
+typedef union _FAST486_PAGE_TABLE
+{
+    struct
+    {
+        ULONG Present       : 1;
+        ULONG Writeable     : 1;
+        ULONG Usermode      : 1;
+        ULONG WriteThrough  : 1;
+        ULONG NoCache       : 1;
+        ULONG Accessed      : 1;
+        ULONG Dirty         : 1;
+        ULONG AlwaysZero    : 1;
+        ULONG Global        : 1;
+        ULONG Unused        : 3;
+        ULONG Address       : 20;
+    };
+    ULONG Value;
+} FAST486_PAGE_TABLE, *PFAST486_PAGE_TABLE;
+
+C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
+
+#pragma pack(pop)
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+Fast486ReadMemory
+(
+    PFAST486_STATE State,
+    FAST486_SEG_REGS SegmentReg,
+    ULONG Offset,
+    BOOLEAN InstFetch,
+    PVOID Buffer,
+    ULONG Size
+);
+
+BOOLEAN
+Fast486WriteMemory
+(
+    PFAST486_STATE State,
+    FAST486_SEG_REGS SegmentReg,
+    ULONG Offset,
+    PVOID Buffer,
+    ULONG Size
+);
+
+BOOLEAN
+Fast486InterruptInternal
+(
+    PFAST486_STATE State,
+    USHORT SegmentSelector,
+    ULONG Offset,
+    BOOLEAN InterruptGate
+);
+
+VOID
+FASTCALL
+Fast486ExceptionWithErrorCode
+(
+    PFAST486_STATE State,
+    FAST486_EXCEPTIONS ExceptionCode,
+    ULONG ErrorCode
+);
+
+/* INLINED FUNCTIONS **********************************************************/
+
+#include "common.inl"
+
+#endif // _COMMON_H_
+
+/* EOF */
diff --git a/lib/fast486/common.inl b/lib/fast486/common.inl
new file mode 100644 (file)
index 0000000..fff8fc0
--- /dev/null
@@ -0,0 +1,1324 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.inl
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "common.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+FORCEINLINE
+INT
+Fast486GetCurrentPrivLevel(PFAST486_STATE State)
+{
+    /* Return the CPL, or 3 if we're in virtual 8086 mode */
+    return (!State->Flags.Vm) ? State->Cpl : 3;
+}
+
+FORCEINLINE
+ULONG
+Fast486GetPageTableEntry(PFAST486_STATE State,
+                         ULONG VirtualAddress,
+                         BOOLEAN MarkAsDirty)
+{
+    ULONG PdeIndex = GET_ADDR_PDE(VirtualAddress);
+    ULONG PteIndex = GET_ADDR_PTE(VirtualAddress);
+    FAST486_PAGE_DIR DirectoryEntry;
+    FAST486_PAGE_TABLE TableEntry;
+    ULONG PageDirectory = State->ControlRegisters[FAST486_REG_CR3];
+
+    if ((State->Tlb != NULL)
+        && (State->Tlb[VirtualAddress >> 12] != INVALID_TLB_FIELD))
+    {
+        /* Return the cached entry */
+        return State->Tlb[VirtualAddress >> 12];
+    }
+
+    /* Read the directory entry */
+    State->MemReadCallback(State,
+                           PageDirectory + PdeIndex * sizeof(ULONG),
+                           &DirectoryEntry.Value,
+                           sizeof(DirectoryEntry));
+
+    /* Make sure it is present */
+    if (!DirectoryEntry.Present) return 0;
+
+    /* Was the directory entry accessed before? */
+    if (!DirectoryEntry.Accessed)
+    {
+        /* Well, it is now */
+        DirectoryEntry.Accessed = TRUE;
+
+        /* Write back the directory entry */
+        State->MemWriteCallback(State,
+                                PageDirectory + PdeIndex * sizeof(ULONG),
+                                &DirectoryEntry.Value,
+                                sizeof(DirectoryEntry));
+    }
+
+    /* Read the table entry */
+    State->MemReadCallback(State,
+                           (DirectoryEntry.TableAddress << 12)
+                           + PteIndex * sizeof(ULONG),
+                           &TableEntry.Value,
+                           sizeof(TableEntry));
+
+    /* Make sure it is present */
+    if (!TableEntry.Present) return 0;
+
+    if (MarkAsDirty) TableEntry.Dirty = TRUE;
+
+    /* Was the table entry accessed before? */
+    if (!TableEntry.Accessed)
+    {
+        /* Well, it is now */
+        TableEntry.Accessed = TRUE;
+
+        /* Write back the table entry */
+        State->MemWriteCallback(State,
+                                (DirectoryEntry.TableAddress << 12)
+                                + PteIndex * sizeof(ULONG),
+                                &TableEntry.Value,
+                                sizeof(TableEntry));
+    }
+
+    /*
+     * The resulting permissions depend on the permissions
+     * in the page directory table too
+     */
+    TableEntry.Writeable &= DirectoryEntry.Writeable;
+    TableEntry.Usermode &= DirectoryEntry.Usermode;
+
+    if (State->Tlb != NULL)
+    {
+        /* Set the TLB entry */
+        State->Tlb[VirtualAddress >> 12] = TableEntry.Value;
+    }
+
+    /* Return the table entry */
+    return TableEntry.Value;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadLinearMemory(PFAST486_STATE State,
+                        ULONG LinearAddress,
+                        PVOID Buffer,
+                        ULONG Size)
+{
+    /* Check if paging is enabled */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
+    {
+        ULONG Page;
+        FAST486_PAGE_TABLE TableEntry;
+        INT Cpl = Fast486GetCurrentPrivLevel(State);
+        ULONG BufferOffset = 0;
+
+        for (Page = PAGE_ALIGN(LinearAddress);
+             Page <= PAGE_ALIGN(LinearAddress + Size - 1);
+             Page += PAGE_SIZE)
+        {
+            ULONG PageOffset = 0, PageLength = PAGE_SIZE;
+
+            /* Get the table entry */
+            TableEntry.Value = Fast486GetPageTableEntry(State, Page, FALSE);
+
+            if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+            {
+                /* Exception */
+                Fast486ExceptionWithErrorCode(State,
+                                              FAST486_EXCEPTION_PF,
+                                              TableEntry.Value & 0x07);
+                return FALSE;
+            }
+
+            /* Check if this is the first page */
+            if (Page == PAGE_ALIGN(LinearAddress))
+            {
+                /* Start reading from the offset from the beginning of the page */
+                PageOffset = PAGE_OFFSET(LinearAddress);
+                PageLength -= PageOffset;
+            }
+
+            /* Check if this is the last page */
+            if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
+            {
+                /* Read only a part of the page */
+                PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1;
+            }
+
+            /* Read the memory */
+            State->MemReadCallback(State,
+                                   (TableEntry.Address << 12) | PageOffset,
+                                   (PVOID)((ULONG_PTR)Buffer + BufferOffset),
+                                   PageLength);
+
+            BufferOffset += PageLength;
+        }
+    }
+    else
+    {
+        /* Read the memory */
+        State->MemReadCallback(State, LinearAddress, Buffer, Size);
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteLinearMemory(PFAST486_STATE State,
+                         ULONG LinearAddress,
+                         PVOID Buffer,
+                         ULONG Size)
+{
+    /* Check if paging is enabled */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
+    {
+        ULONG Page;
+        FAST486_PAGE_TABLE TableEntry;
+        INT Cpl = Fast486GetCurrentPrivLevel(State);
+        ULONG BufferOffset = 0;
+
+        for (Page = PAGE_ALIGN(LinearAddress);
+             Page <= PAGE_ALIGN(LinearAddress + Size - 1);
+             Page += PAGE_SIZE)
+        {
+            ULONG PageOffset = 0, PageLength = PAGE_SIZE;
+
+            /* Get the table entry */
+            TableEntry.Value = Fast486GetPageTableEntry(State, Page, TRUE);
+
+            if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+                || ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_WP)
+                && !TableEntry.Writeable))
+            {
+                /* Exception */
+                Fast486ExceptionWithErrorCode(State,
+                                              FAST486_EXCEPTION_PF,
+                                              TableEntry.Value & 0x07);
+                return FALSE;
+            }
+
+            /* Check if this is the first page */
+            if (Page == PAGE_ALIGN(LinearAddress))
+            {
+                /* Start writing from the offset from the beginning of the page */
+                PageOffset = PAGE_OFFSET(LinearAddress);
+                PageLength -= PageOffset;
+            }
+
+            /* Check if this is the last page */
+            if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
+            {
+                /* Write only a part of the page */
+                PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1;
+            }
+
+            /* Write the memory */
+            State->MemWriteCallback(State,
+                                    (TableEntry.Address << 12) | PageOffset,
+                                    (PVOID)((ULONG_PTR)Buffer + BufferOffset),
+                                    PageLength);
+
+            BufferOffset += PageLength;
+        }
+    }
+    else
+    {
+        /* Write the memory */
+        State->MemWriteCallback(State, LinearAddress, Buffer, Size);
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+VOID
+Fast486Exception(PFAST486_STATE State,
+                 FAST486_EXCEPTIONS ExceptionCode)
+{
+    /* Call the internal function */
+    Fast486ExceptionWithErrorCode(State, ExceptionCode, 0);
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486StackPush(PFAST486_STATE State,
+                 ULONG Value)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* The OPSIZE prefix toggles the size */
+    if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) Size = !Size;
+
+    if (Size)
+    {
+        /* 32-bit size */
+
+        /* Check if ESP is between 1 and 3 */
+        if (State->GeneralRegs[FAST486_REG_ESP].Long >= 1
+            && State->GeneralRegs[FAST486_REG_ESP].Long <= 3)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_SS);
+            return FALSE;
+        }
+
+        /* Subtract ESP by 4 */
+        State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG);
+
+        /* Store the value in SS:ESP */
+        return Fast486WriteMemory(State,
+                                  FAST486_REG_SS,
+                                  State->GeneralRegs[FAST486_REG_ESP].Long,
+                                  &Value,
+                                  sizeof(ULONG));
+    }
+    else
+    {
+        /* 16-bit size */
+        USHORT ShortValue = LOWORD(Value);
+
+        /* Check if SP is 1 */
+        if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 1)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_SS);
+            return FALSE;
+        }
+
+        /* Subtract SP by 2 */
+        State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT);
+
+        /* Store the value in SS:SP */
+        return Fast486WriteMemory(State,
+                                  FAST486_REG_SS,
+                                  State->GeneralRegs[FAST486_REG_ESP].LowWord,
+                                  &ShortValue,
+                                  sizeof(USHORT));
+    }
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486StackPop(PFAST486_STATE State,
+                PULONG Value)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* The OPSIZE prefix toggles the size */
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        /* 32-bit size */
+        ULONG LongValue;
+
+        /* Check if ESP is 0xFFFFFFFF */
+        if (State->GeneralRegs[FAST486_REG_ESP].Long == 0xFFFFFFFF)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_SS);
+            return FALSE;
+        }
+
+        /* Read the value from SS:ESP */
+        if (!Fast486ReadMemory(State,
+                               FAST486_REG_SS,
+                               State->GeneralRegs[FAST486_REG_ESP].Long,
+                               FALSE,
+                               &LongValue,
+                               sizeof(LongValue)))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Increment ESP by 4 */
+        State->GeneralRegs[FAST486_REG_ESP].Long += sizeof(ULONG);
+
+        /* Store the value in the result */
+        *Value = LongValue;
+    }
+    else
+    {
+        /* 16-bit size */
+        USHORT ShortValue;
+
+        /* Check if SP is 0xFFFF */
+        if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 0xFFFF)
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_SS);
+            return FALSE;
+        }
+
+        /* Read the value from SS:SP */
+        if (!Fast486ReadMemory(State,
+                               FAST486_REG_SS,
+                               State->GeneralRegs[FAST486_REG_ESP].LowWord,
+                               FALSE,
+                               &ShortValue,
+                               sizeof(ShortValue)))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Increment SP by 2 */
+        State->GeneralRegs[FAST486_REG_ESP].LowWord += sizeof(USHORT);
+
+        /* Store the value in the result */
+        *Value = ShortValue;
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486LoadSegment(PFAST486_STATE State,
+                   FAST486_SEG_REGS Segment,
+                   USHORT Selector)
+{
+    PFAST486_SEG_REG CachedDescriptor;
+    FAST486_GDT_ENTRY GdtEntry;
+
+    ASSERT(Segment < FAST486_NUM_SEG_REGS);
+
+    /* Get the cached descriptor */
+    CachedDescriptor = &State->SegmentRegs[Segment];
+
+    /* Check for protected mode */
+    if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
+    {
+        if (!(Selector & SEGMENT_TABLE_INDICATOR))
+        {
+            /* Make sure the GDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the GDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Gdtr.Address
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+        else
+        {
+            /* Make sure the LDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the LDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Ldtr.Base
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+
+        if (Segment == FAST486_REG_SS)
+        {
+            /* Loading the stack segment */
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!GdtEntry.SystemType)
+            {
+                /* This is a special descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            if (GdtEntry.Executable || !GdtEntry.ReadWrite)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            if ((GET_SEGMENT_RPL(Selector) != Fast486GetCurrentPrivLevel(State))
+                || (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_SS, Selector);
+                return FALSE;
+            }
+        }
+        else if (Segment == FAST486_REG_CS)
+        {
+            /* Loading the code segment */
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!GdtEntry.SystemType)
+            {
+                // TODO: Call/interrupt/task gates NOT IMPLEMENTED!
+                UNIMPLEMENTED;
+            }
+            else
+            {
+                if (!GdtEntry.Present)
+                {
+                    Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                    return FALSE;
+                }
+
+                if (!GdtEntry.Executable)
+                {
+                    Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                    return FALSE;
+                }
+
+                if (GdtEntry.DirConf)
+                {
+                    /* Conforming Code Segment */
+
+                    if (GdtEntry.Dpl > Fast486GetCurrentPrivLevel(State))
+                    {
+                        /* Must be accessed from lower-privileged code */
+                        Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                        return FALSE;
+                    }
+                }
+                else
+                {
+                    /* Regular code segment */
+
+                    if ((GET_SEGMENT_RPL(Selector) > Fast486GetCurrentPrivLevel(State))
+                        || (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl))
+                    {
+                        Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                        return FALSE;
+                    }
+                }
+
+                /* Update CPL */
+                State->Cpl = GET_SEGMENT_RPL(Selector);
+            }
+        }
+        else
+        {
+            /* Loading a data segment */
+
+            if (!GdtEntry.SystemType)
+            {
+                /* This is a special descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
+                || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                return FALSE;
+            }
+        }
+
+        /* Update the cache entry */
+        CachedDescriptor->Selector = Selector;
+        CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
+        CachedDescriptor->Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+        CachedDescriptor->Accessed = GdtEntry.Accessed;
+        CachedDescriptor->ReadWrite = GdtEntry.ReadWrite;
+        CachedDescriptor->DirConf = GdtEntry.DirConf;
+        CachedDescriptor->Executable = GdtEntry.Executable;
+        CachedDescriptor->SystemType = GdtEntry.SystemType;
+        CachedDescriptor->Dpl = GdtEntry.Dpl;
+        CachedDescriptor->Present = GdtEntry.Present;
+        CachedDescriptor->Size = GdtEntry.Size;
+
+        /* Check for page granularity */
+        if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12;
+    }
+    else
+    {
+        /* Update the selector and base */
+        CachedDescriptor->Selector = Selector;
+        CachedDescriptor->Base = Selector << 4;
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486FetchByte(PFAST486_STATE State,
+                 PUCHAR Data)
+{
+    PFAST486_SEG_REG CachedDescriptor;
+
+    /* Get the cached descriptor of CS */
+    CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS];
+
+    /* Read from memory */
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_CS,
+                           (CachedDescriptor->Size) ? State->InstPtr.Long
+                                                    : State->InstPtr.LowWord,
+                           TRUE,
+                           Data,
+                           sizeof(UCHAR)))
+    {
+        /* Exception occurred during instruction fetch */
+        return FALSE;
+    }
+
+    /* Advance the instruction pointer */
+    if (CachedDescriptor->Size) State->InstPtr.Long++;
+    else State->InstPtr.LowWord++;
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486FetchWord(PFAST486_STATE State,
+                 PUSHORT Data)
+{
+    PFAST486_SEG_REG CachedDescriptor;
+
+    /* Get the cached descriptor of CS */
+    CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS];
+
+    /* Read from memory */
+    // FIXME: Fix byte order on big-endian machines
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_CS,
+                           (CachedDescriptor->Size) ? State->InstPtr.Long
+                                                    : State->InstPtr.LowWord,
+                           TRUE,
+                           Data,
+                           sizeof(USHORT)))
+    {
+        /* Exception occurred during instruction fetch */
+        return FALSE;
+    }
+
+    /* Advance the instruction pointer */
+    if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(USHORT);
+    else State->InstPtr.LowWord += sizeof(USHORT);
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486FetchDword(PFAST486_STATE State,
+                  PULONG Data)
+{
+    PFAST486_SEG_REG CachedDescriptor;
+
+    /* Get the cached descriptor of CS */
+    CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS];
+
+    /* Read from memory */
+    // FIXME: Fix byte order on big-endian machines
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_CS,
+                           (CachedDescriptor->Size) ? State->InstPtr.Long
+                                                    : State->InstPtr.LowWord,
+                           TRUE,
+                           Data,
+                           sizeof(ULONG)))
+    {
+        /* Exception occurred during instruction fetch */
+        return FALSE;
+    }
+
+    /* Advance the instruction pointer */
+    if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(ULONG);
+    else State->InstPtr.LowWord += sizeof(ULONG);
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486GetIntVector(PFAST486_STATE State,
+                    UCHAR Number,
+                    PFAST486_IDT_ENTRY IdtEntry)
+{
+    ULONG FarPointer;
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    {
+        /* Read from the IDT */
+        if (!Fast486ReadLinearMemory(State,
+                                     State->Idtr.Address
+                                     + Number * sizeof(*IdtEntry),
+                                     IdtEntry,
+                                     sizeof(*IdtEntry)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Read from the real-mode IVT */
+
+        /* Paging is always disabled in real mode */
+        State->MemReadCallback(State,
+                               State->Idtr.Address
+                               + Number * sizeof(FarPointer),
+                               &FarPointer,
+                               sizeof(FarPointer));
+
+        /* Fill a fake IDT entry */
+        IdtEntry->Offset = LOWORD(FarPointer);
+        IdtEntry->Selector = HIWORD(FarPointer);
+        IdtEntry->Zero = 0;
+        IdtEntry->Type = FAST486_IDT_INT_GATE;
+        IdtEntry->Storage = FALSE;
+        IdtEntry->Dpl = 0;
+        IdtEntry->Present = TRUE;
+        IdtEntry->OffsetHigh = 0;
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486CalculateParity(UCHAR Number)
+{
+    // See http://graphics.stanford.edu/~seander/bithacks.html#ParityLookupTable too...
+    return (0x9669 >> ((Number & 0x0F) ^ (Number >> 4))) & 1;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ParseModRegRm(PFAST486_STATE State,
+                     BOOLEAN AddressSize,
+                     PFAST486_MOD_REG_RM ModRegRm)
+{
+    UCHAR ModRmByte, Mode, RegMem;
+
+    /* Fetch the MOD REG R/M byte */
+    if (!Fast486FetchByte(State, &ModRmByte))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Unpack the mode and R/M */
+    Mode = ModRmByte >> 6;
+    RegMem = ModRmByte & 0x07;
+
+    /* Set the register operand */
+    ModRegRm->Register = (ModRmByte >> 3) & 0x07;
+
+    /* Check the mode */
+    if ((ModRmByte >> 6) == 3)
+    {
+        /* The second operand is also a register */
+        ModRegRm->Memory = FALSE;
+        ModRegRm->SecondRegister = RegMem;
+
+        /* Done parsing */
+        return TRUE;
+    }
+
+    /* The second operand is memory */
+    ModRegRm->Memory = TRUE;
+
+    if (AddressSize)
+    {
+        if (RegMem == FAST486_REG_ESP)
+        {
+            UCHAR SibByte;
+            ULONG Scale, Index, Base;
+
+            /* Fetch the SIB byte */
+            if (!Fast486FetchByte(State, &SibByte))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Unpack the scale, index and base */
+            Scale = 1 << (SibByte >> 6);
+            Index = (SibByte >> 3) & 0x07;
+            if (Index != FAST486_REG_ESP) Index = State->GeneralRegs[Index].Long;
+            else Index = 0;
+
+            if (((SibByte & 0x07) != FAST486_REG_EBP) || (Mode != 0))
+            {
+                /* Use the register a base */
+                Base = State->GeneralRegs[SibByte & 0x07].Long;
+            }
+            else
+            {
+                /* Fetch the base */
+                if (!Fast486FetchDword(State, &Base))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+
+            if ((SibByte & 0x07) == FAST486_REG_ESP)
+            {
+                /* Check if there is no segment override */
+                if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+                {
+                    /* Add a SS: prefix */
+                    State->PrefixFlags |= FAST486_PREFIX_SEG;
+                    State->SegmentOverride = FAST486_REG_SS;
+                }
+            }
+
+            /* Calculate the address */
+            ModRegRm->MemoryAddress = Base + Index * Scale;
+        }
+        else if (RegMem == FAST486_REG_EBP)
+        {
+            if (Mode) ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].Long;
+            else ModRegRm->MemoryAddress = 0;
+        }
+        else
+        {
+            /* Get the base from the register */
+            ModRegRm->MemoryAddress = State->GeneralRegs[RegMem].Long;
+        }
+
+        /* Check if there is no segment override */
+        if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+        {
+            /* Check if the default segment should be SS */
+            if ((RegMem == FAST486_REG_EBP) && Mode)
+            {
+                /* Add a SS: prefix */
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_SS;
+            }
+        }
+
+        if (Mode == 1)
+        {
+            CHAR Offset;
+
+            /* Fetch the byte */
+            if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Add the signed offset to the address */
+            ModRegRm->MemoryAddress += (LONG)Offset;
+        }
+        else if ((Mode == 2) || ((Mode == 0) && (RegMem == FAST486_REG_EBP)))
+        {
+            LONG Offset;
+
+            /* Fetch the dword */
+            if (!Fast486FetchDword(State, (PULONG)&Offset))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Add the signed offset to the address */
+            ModRegRm->MemoryAddress += Offset;
+        }
+    }
+    else
+    {
+        /* Check the operand */
+        switch (RegMem)
+        {
+            case 0:
+            {
+                /* [BX + SI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+                                           + State->GeneralRegs[FAST486_REG_ESI].LowWord;
+
+                break;
+            }
+
+            case 1:
+            {
+                /* [BX + DI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+                                           + State->GeneralRegs[FAST486_REG_EDI].LowWord;
+
+                break;
+            }
+
+            case 2:
+            {
+                /* SS:[BP + SI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+                                           + State->GeneralRegs[FAST486_REG_ESI].LowWord;
+
+                break;
+            }
+
+            case 3:
+            {
+                /* SS:[BP + DI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+                                           + State->GeneralRegs[FAST486_REG_EDI].LowWord;
+
+                break;
+            }
+
+            case 4:
+            {
+                /* [SI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_ESI].LowWord;
+
+                break;
+            }
+
+            case 5:
+            {
+                /* [DI] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EDI].LowWord;
+
+                break;
+            }
+
+            case 6:
+            {
+                if (Mode)
+                {
+                    /* [BP] */
+                    ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord;
+                }
+                else
+                {
+                    /* [constant] (added later) */
+                    ModRegRm->MemoryAddress = 0;
+                }
+
+                break;
+            }
+
+            case 7:
+            {
+                /* [BX] */
+                ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord;
+
+                break;
+            }
+        }
+
+        /* Check if there is no segment override */
+        if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+        {
+            /* Check if the default segment should be SS */
+            if ((RegMem == 2) || (RegMem == 3) || ((RegMem == 6) && Mode))
+            {
+                /* Add a SS: prefix */
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_SS;
+            }
+        }
+
+        if (Mode == 1)
+        {
+            CHAR Offset;
+
+            /* Fetch the byte */
+            if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Add the signed offset to the address */
+            ModRegRm->MemoryAddress += (LONG)Offset;
+        }
+        else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6)))
+        {
+            SHORT Offset;
+
+            /* Fetch the word */
+            if (!Fast486FetchWord(State, (PUSHORT)&Offset))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Add the signed offset to the address */
+            ModRegRm->MemoryAddress += (LONG)Offset;
+        }
+
+        /* Clear the top 16 bits */
+        ModRegRm->MemoryAddress &= 0x0000FFFF;
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadModrmByteOperands(PFAST486_STATE State,
+                             PFAST486_MOD_REG_RM ModRegRm,
+                             PUCHAR RegValue,
+                             PUCHAR RmValue)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (RegValue)
+    {
+        /* Get the register value */
+        if (ModRegRm->Register & 0x04)
+        {
+            /* AH, CH, DH, BH */
+            *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte;
+        }
+        else
+        {
+            /* AL, CL, DL, BL */
+            *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte;
+        }
+    }
+
+    if (RmValue)
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Get the second register value */
+            if (ModRegRm->SecondRegister & 0x04)
+            {
+                /* AH, CH, DH, BH */
+                *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte;
+            }
+            else
+            {
+                /* AL, CL, DL, BL */
+                *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte;
+            }
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read memory */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm->MemoryAddress,
+                                   FALSE,
+                                   RmValue,
+                                   sizeof(UCHAR)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadModrmWordOperands(PFAST486_STATE State,
+                             PFAST486_MOD_REG_RM ModRegRm,
+                             PUSHORT RegValue,
+                             PUSHORT RmValue)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (RegValue)
+    {
+        /* Get the register value */
+        *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord;
+    }
+
+    if (RmValue)
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Get the second register value */
+            *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord;
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read memory */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm->MemoryAddress,
+                                   FALSE,
+                                   RmValue,
+                                   sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadModrmDwordOperands(PFAST486_STATE State,
+                              PFAST486_MOD_REG_RM ModRegRm,
+                              PULONG RegValue,
+                              PULONG RmValue)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (RegValue)
+    {
+        /* Get the register value */
+        *RegValue = State->GeneralRegs[ModRegRm->Register].Long;
+    }
+
+    if (RmValue)
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Get the second register value */
+            *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long;
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read memory */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm->MemoryAddress,
+                                   FALSE,
+                                   RmValue,
+                                   sizeof(ULONG)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteModrmByteOperands(PFAST486_STATE State,
+                              PFAST486_MOD_REG_RM ModRegRm,
+                              BOOLEAN WriteRegister,
+                              UCHAR Value)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (WriteRegister)
+    {
+        /* Store the value in the register */
+        if (ModRegRm->Register & 0x04)
+        {
+            /* AH, CH, DH, BH */
+            State->GeneralRegs[ModRegRm->Register & 0x03].HighByte = Value;
+        }
+        else
+        {
+            /* AL, CL, DL, BL */
+            State->GeneralRegs[ModRegRm->Register & 0x03].LowByte = Value;
+        }
+    }
+    else
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Store the value in the second register */
+            if (ModRegRm->SecondRegister & 0x04)
+            {
+                /* AH, CH, DH, BH */
+                State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte = Value;
+            }
+            else
+            {
+                /* AL, CL, DL, BL */
+                State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte = Value;
+            }
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Write memory */
+            if (!Fast486WriteMemory(State,
+                                    Segment,
+                                    ModRegRm->MemoryAddress,
+                                    &Value,
+                                    sizeof(UCHAR)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteModrmWordOperands(PFAST486_STATE State,
+                              PFAST486_MOD_REG_RM ModRegRm,
+                              BOOLEAN WriteRegister,
+                              USHORT Value)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (WriteRegister)
+    {
+        /* Store the value in the register */
+        State->GeneralRegs[ModRegRm->Register].LowWord = Value;
+    }
+    else
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Store the value in the second register */
+            State->GeneralRegs[ModRegRm->SecondRegister].LowWord = Value;
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Write memory */
+            if (!Fast486WriteMemory(State,
+                                    Segment,
+                                    ModRegRm->MemoryAddress,
+                                    &Value,
+                                    sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteModrmDwordOperands(PFAST486_STATE State,
+                               PFAST486_MOD_REG_RM ModRegRm,
+                               BOOLEAN WriteRegister,
+                               ULONG Value)
+{
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    if (WriteRegister)
+    {
+        /* Store the value in the register */
+        State->GeneralRegs[ModRegRm->Register].Long = Value;
+    }
+    else
+    {
+        if (!ModRegRm->Memory)
+        {
+            /* Store the value in the second register */
+            State->GeneralRegs[ModRegRm->SecondRegister].Long = Value;
+        }
+        else
+        {
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Write memory */
+            if (!Fast486WriteMemory(State,
+                                    Segment,
+                                    ModRegRm->MemoryAddress,
+                                    &Value,
+                                    sizeof(ULONG)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+/* EOF */
diff --git a/lib/fast486/extraops.c b/lib/fast486/extraops.c
new file mode 100644 (file)
index 0000000..f9fe386
--- /dev/null
@@ -0,0 +1,2387 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * extraops.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "opcodes.h"
+#include "common.h"
+#include "opgroups.h"
+#include "extraops.h"
+
+/* PUBLIC VARIABLES ***********************************************************/
+
+FAST486_OPCODE_HANDLER_PROC
+Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
+{
+    Fast486OpcodeGroup0F00,
+    Fast486OpcodeGroup0F01,
+    Fast486ExtOpcodeLar,
+    Fast486ExtOpcodeLsl,
+    NULL, // Invalid
+    NULL, // Invalid
+    Fast486ExtOpcodeClts,
+    NULL, // Invalid
+    NULL, // TODO: OPCODE 0x08 NOT IMPLEMENTED
+    NULL, // TODO: OPCODE 0x09 NOT IMPLEMENTED
+    NULL, // Invalid
+    NULL, // Reserved (UD1)
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    Fast486ExtOpcodeStoreControlReg,
+    Fast486ExtOpcodeStoreDebugReg,
+    Fast486ExtOpcodeLoadControlReg,
+    Fast486ExtOpcodeLoadDebugReg,
+    NULL, // TODO: OPCODE 0x24 NOT IMPLEMENTED
+    NULL, // Invalid
+    NULL, // TODO: OPCODE 0x26 NOT IMPLEMENTED
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalJmp,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodeConditionalSet,
+    Fast486ExtOpcodePushFs,
+    Fast486ExtOpcodePopFs,
+    NULL, // Invalid
+    Fast486ExtOpcodeBitTest,
+    Fast486ExtOpcodeShld,
+    Fast486ExtOpcodeShld,
+    NULL, // Invalid
+    NULL, // Invalid
+    Fast486ExtOpcodePushGs,
+    Fast486ExtOpcodePopGs,
+    NULL, // Invalid
+    Fast486ExtOpcodeBts,
+    Fast486ExtOpcodeShrd,
+    Fast486ExtOpcodeShrd,
+    NULL, // Invalid
+    Fast486ExtOpcodeImul,
+    Fast486ExtOpcodeCmpXchgByte,
+    Fast486ExtOpcodeCmpXchg,
+    Fast486ExtOpcodeLss,
+    Fast486ExtOpcodeBtr,
+    Fast486ExtOpcodeLfsLgs,
+    Fast486ExtOpcodeLfsLgs,
+    Fast486ExtOpcodeMovzxByte,
+    Fast486ExtOpcodeMovzxWord,
+    NULL, // Invalid
+    Fast486OpcodeGroup0FB9,
+    Fast486OpcodeGroup0FBA,
+    Fast486ExtOpcodeBtc,
+    Fast486ExtOpcodeBsf,
+    Fast486ExtOpcodeBsr,
+    Fast486ExtOpcodeMovsxByte,
+    Fast486ExtOpcodeMovsxWord,
+    Fast486ExtOpcodeXaddByte,
+    Fast486ExtOpcodeXadd,
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    Fast486ExtOpcodeBswap,
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+    NULL, // Invalid
+};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    USHORT Selector;
+    FAST486_GDT_ENTRY GdtEntry;
+    DWORD AccessRights;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+        || State->Flags.Vm)
+    {
+        /* Not recognized */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    
+        Selector = LOWORD(Value);
+    }
+    else
+    {
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    if (!(Selector & SEGMENT_TABLE_INDICATOR))
+    {
+        /* Check if the GDT contains the entry */
+        if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+        {
+            State->Flags.Zf = FALSE;
+            return TRUE;
+        }
+
+        /* Read the GDT */
+        if (!Fast486ReadLinearMemory(State,
+                                     State->Gdtr.Address
+                                     + GET_SEGMENT_INDEX(Selector),
+                                     &GdtEntry,
+                                     sizeof(GdtEntry)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Check if the LDT contains the entry */
+        if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+        {
+            State->Flags.Zf = FALSE;
+            return TRUE;
+        }
+
+        /* Read the LDT */
+        if (!Fast486ReadLinearMemory(State,
+                                     State->Ldtr.Base
+                                     + GET_SEGMENT_INDEX(Selector),
+                                     &GdtEntry,
+                                     sizeof(GdtEntry)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Privilege check */
+    if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl))
+        || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+    {
+        State->Flags.Zf = FALSE;
+        return TRUE;
+    }
+
+    /* Set ZF */
+    State->Flags.Zf = TRUE;
+
+    /* Get the access rights */
+    AccessRights = ((PDWORD)&GdtEntry)[1] & 0x00F0FF00;
+
+    /* Return the access rights */
+    if (OperandSize)
+    {
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, AccessRights))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(AccessRights)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    USHORT Selector;
+    ULONG Limit;
+    FAST486_GDT_ENTRY GdtEntry;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+        || State->Flags.Vm)
+    {
+        /* Not recognized */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    
+        Selector = LOWORD(Value);
+    }
+    else
+    {
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    if (!(Selector & SEGMENT_TABLE_INDICATOR))
+    {
+        /* Check if the GDT contains the entry */
+        if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+        {
+            State->Flags.Zf = FALSE;
+            return TRUE;
+        }
+
+        /* Read the GDT */
+        if (!Fast486ReadLinearMemory(State,
+                                     State->Gdtr.Address
+                                     + GET_SEGMENT_INDEX(Selector),
+                                     &GdtEntry,
+                                     sizeof(GdtEntry)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Check if the LDT contains the entry */
+        if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+        {
+            State->Flags.Zf = FALSE;
+            return TRUE;
+        }
+
+        /* Read the LDT */
+        if (!Fast486ReadLinearMemory(State,
+                                     State->Ldtr.Base
+                                     + GET_SEGMENT_INDEX(Selector),
+                                     &GdtEntry,
+                                     sizeof(GdtEntry)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Privilege check */
+    if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl))
+        || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+    {
+        State->Flags.Zf = FALSE;
+        return TRUE;
+    }
+
+    /* Calculate the limit */
+    Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+    if (GdtEntry.Granularity) Limit <<= 12;
+
+    /* Set ZF */
+    State->Flags.Zf = TRUE;
+
+    if (OperandSize)
+    {
+        /* Return the limit */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Limit))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Return the limit */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(Limit)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts)
+{
+    NO_LOCK_PREFIX();
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Clear the task switch bit */
+    State->ControlRegisters[FAST486_REG_CR0] &= ~FAST486_CR0_TS;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
+    {
+        /* CR1, CR4, CR5, CR6 and CR7 don't exist */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* CR2 and CR3 and are stored in array indexes 1 and 2 */
+        ModRegRm.Register--;
+    }
+
+    /* Store the value of the control register */
+    State->GeneralRegs[ModRegRm.SecondRegister].Long = State->ControlRegisters[ModRegRm.Register];
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
+    {
+        /* DR6 and DR7 are aliases to DR4 and DR5 */
+        ModRegRm.Register -= 2;
+    }
+
+    if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
+    {
+        /* Disallow access to debug registers */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Store the value of the debug register */
+    State->GeneralRegs[ModRegRm.SecondRegister].Long = State->DebugRegisters[ModRegRm.Register];
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg)
+{
+    ULONG Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
+    {
+        /* CR1, CR4, CR5, CR6 and CR7 don't exist */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* CR2 and CR3 and are stored in array indexes 1 and 2 */
+        ModRegRm.Register--;
+    }
+
+    /* Get the value */
+    Value = State->GeneralRegs[ModRegRm.SecondRegister].Long;
+
+    if (ModRegRm.Register == (INT)FAST486_REG_CR0)
+    {
+        /* CR0 checks */
+
+        if (((Value & (FAST486_CR0_PG | FAST486_CR0_PE)) == FAST486_CR0_PG)
+            || ((Value & (FAST486_CR0_CD | FAST486_CR0_NW)) == FAST486_CR0_NW))
+        {
+            /* Invalid value */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+    }
+
+    /* Load a value to the control register */
+    State->ControlRegisters[ModRegRm.Register] = Value;
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The current privilege level must be zero */
+    if (Fast486GetCurrentPrivLevel(State) != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
+    {
+        /* DR6 and DR7 are aliases to DR4 and DR5 */
+        ModRegRm.Register -= 2;
+    }
+
+    if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
+    {
+        /* Disallow access to debug registers */
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Load a value to the debug register */
+    State->DebugRegisters[ModRegRm.Register] = State->GeneralRegs[ModRegRm.SecondRegister].Long;
+
+    if (ModRegRm.Register == (INT)FAST486_REG_DR4)
+    {
+        /* The reserved bits are 1 */
+        State->DebugRegisters[ModRegRm.Register] |= FAST486_DR4_RESERVED;
+    }
+    else if (ModRegRm.Register == (INT)FAST486_REG_DR5)
+    {
+        /* The reserved bits are 0 */
+        State->DebugRegisters[ModRegRm.Register] &= ~FAST486_DR5_RESERVED;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_FS].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs)
+{
+    ULONG NewSelector;
+
+    if (!Fast486StackPop(State, &NewSelector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486LoadSegment(State, FAST486_REG_FS, LOWORD(NewSelector));
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UINT DataSize;
+    ULONG BitNumber;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Get the bit number */
+    BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
+                            : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
+
+    if (ModRegRm.Memory)
+    {
+        /*
+         * For memory operands, add the bit offset divided by
+         * the data size to the address
+         */
+        ModRegRm.MemoryAddress += BitNumber / DataSize;
+    }
+
+    /* Normalize the bit number */
+    BitNumber %= DataSize;
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UCHAR Count;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xA4);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Opcode == 0xA4)
+    {
+        /* Fetch the count */
+        if (!Fast486FetchByte(State, &Count))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* The count is in CL */
+        Count = State->GeneralRegs[FAST486_REG_ECX].LowByte;
+    }
+
+    /* Normalize the count */
+    Count &= 0x1F;
+
+    /* Do nothing if the count is zero */
+    if (Count == 0) return TRUE;
+
+    if (OperandSize)
+    {
+        ULONG Source, Destination, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = (Destination << Count) | (Source >> (32 - Count));
+
+        /* Update flags */
+        State->Flags.Cf = (Destination >> (32 - Count)) & 1;
+        if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG)
+                                          != (Destination & SIGN_FLAG_LONG);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
+    }
+    else
+    {
+        USHORT Source, Destination, Result;
+        ULONG DoubleSource;
+
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        DoubleSource = Source | (Source << 16);
+
+        /* Calculate the result */
+        Result = (Destination << Count) | (DoubleSource >> (32 - Count));
+
+        /* Update flags */
+        if (Count <= 16) State->Flags.Cf = (Destination >> (16 - Count)) & 1;
+        else  State->Flags.Cf = (Source >> (32 - Count)) & 1;
+
+        if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD)
+                                          != (Destination & SIGN_FLAG_WORD);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_GS].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs)
+{
+    ULONG NewSelector;
+
+    if (!Fast486StackPop(State, &NewSelector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486LoadSegment(State, FAST486_REG_GS, LOWORD(NewSelector));
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UINT DataSize;
+    ULONG BitNumber;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Get the bit number */
+    BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
+                            : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
+
+    if (ModRegRm.Memory)
+    {
+        /*
+         * For memory operands, add the bit offset divided by
+         * the data size to the address
+         */
+        ModRegRm.MemoryAddress += BitNumber / DataSize;
+    }
+
+    /* Normalize the bit number */
+    BitNumber %= DataSize;
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Set the bit */
+        Value |= 1 << BitNumber;
+
+        /* Write back the result */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Set the bit */
+        Value |= 1 << BitNumber;
+
+        /* Write back the result */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UCHAR Count;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xAC);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Opcode == 0xAC)
+    {
+        /* Fetch the count */
+        if (!Fast486FetchByte(State, &Count))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* The count is in CL */
+        Count = State->GeneralRegs[FAST486_REG_ECX].LowByte;
+    }
+
+    /* Normalize the count */
+    Count &= 0x1F;
+
+    /* Do nothing if the count is zero */
+    if (Count == 0) return TRUE;
+
+    if (OperandSize)
+    {
+        ULONG Source, Destination, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = (Destination >> Count) | (Source << (32 - Count));
+
+        /* Update flags */
+        State->Flags.Cf = (Destination >> (Count - 1)) & 1;
+        if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG)
+                                          != (Destination & SIGN_FLAG_LONG);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
+    }
+    else
+    {
+        USHORT Source, Destination, Result;
+
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = (Destination >> Count) | (Source << (16 - Count));
+
+        if (Count >= 16) Result |= (ULONG)(Source | (Source << 16)) >> (Count - 16);
+
+        /* Update flags */
+        if (Count <= 16) State->Flags.Cf = (Destination >> (Count - 1)) & 1;
+        else State->Flags.Cf = (Source >> (Count - 17)) & 1;
+
+        if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD)
+                                          != (Destination & SIGN_FLAG_WORD);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        LONG Source, Destination;
+        LONGLONG Result;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State,
+                                           &ModRegRm,
+                                           (PULONG)&Destination,
+                                           (PULONG)&Source))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = (LONGLONG)Source * (LONGLONG)Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL));
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, (ULONG)((LONG)Result));
+    }
+    else
+    {
+        SHORT Source, Destination;
+        LONG Result;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          (PUSHORT)&Destination,
+                                          (PUSHORT)&Source))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = (LONG)Source * (LONG)Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767));
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, (USHORT)((SHORT)Result));
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    UCHAR Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR Source, Destination, Result;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Source, &Destination))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Compare AL with the destination */
+    Result = Accumulator - Destination;
+
+    /* Update the flags */
+    State->Flags.Cf = (Accumulator < Destination);
+    State->Flags.Of = ((Accumulator & SIGN_FLAG_BYTE) != (Destination & SIGN_FLAG_BYTE))
+                      && ((Accumulator & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    if (State->Flags.Zf)
+    {
+        /* Load the source operand into the destination */
+        return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Source);
+    }
+    else
+    {
+        /* Load the destination into AL */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte = Destination;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Source, Destination, Result;
+        ULONG Accumulator = State->GeneralRegs[FAST486_REG_EAX].Long;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Compare EAX with the destination */
+        Result = Accumulator - Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = (Accumulator < Destination);
+        State->Flags.Of = ((Accumulator & SIGN_FLAG_LONG) != (Destination & SIGN_FLAG_LONG))
+                          && ((Accumulator & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        if (State->Flags.Zf)
+        {
+            /* Load the source operand into the destination */
+            return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Source);
+        }
+        else
+        {
+            /* Load the destination into EAX */
+            State->GeneralRegs[FAST486_REG_EAX].Long = Destination;
+        }
+    }
+    else
+    {
+        USHORT Source, Destination, Result;
+        USHORT Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Compare AX with the destination */
+        Result = Accumulator - Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = (Accumulator < Destination);
+        State->Flags.Of = ((Accumulator & SIGN_FLAG_WORD) != (Destination & SIGN_FLAG_WORD))
+                          && ((Accumulator & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        if (State->Flags.Zf)
+        {
+            /* Load the source operand into the destination */
+            return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Source);
+        }
+        else
+        {
+            /* Load the destination into AX */
+            State->GeneralRegs[FAST486_REG_EAX].LowWord = Destination;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss)
+{
+    UCHAR FarPointer[6];
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xB2);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!ModRegRm.Memory)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486ReadMemory(State,
+                           (State->PrefixFlags & FAST486_PREFIX_SEG)
+                           ? State->SegmentOverride : FAST486_REG_DS,
+                           ModRegRm.MemoryAddress,
+                           FALSE,
+                           FarPointer,
+                           OperandSize ? 6 : 4))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Offset = *((PULONG)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].Long = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  FAST486_REG_SS,
+                                  Segment);
+    }
+    else
+    {
+        USHORT Offset = *((PUSHORT)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  FAST486_REG_SS,
+                                  Segment);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UINT DataSize;
+    ULONG BitNumber;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Get the bit number */
+    BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
+                            : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
+
+    if (ModRegRm.Memory)
+    {
+        /*
+         * For memory operands, add the bit offset divided by
+         * the data size to the address
+         */
+        ModRegRm.MemoryAddress += BitNumber / DataSize;
+    }
+
+    /* Normalize the bit number */
+    BitNumber %= DataSize;
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Clear the bit */
+        Value &= ~(1 << BitNumber);
+
+        /* Write back the result */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Clear the bit */
+        Value &= ~(1 << BitNumber);
+
+        /* Write back the result */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs)
+{
+    UCHAR FarPointer[6];
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xB4);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!ModRegRm.Memory)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486ReadMemory(State,
+                           (State->PrefixFlags & FAST486_PREFIX_SEG)
+                           ? State->SegmentOverride : FAST486_REG_DS,
+                           ModRegRm.MemoryAddress,
+                           FALSE,
+                           FarPointer,
+                           OperandSize ? 6 : 4))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Offset = *((PULONG)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].Long = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  (Opcode == 0xB4)
+                                  ? FAST486_REG_FS : FAST486_REG_GS,
+                                  Segment);
+    }
+    else
+    {
+        USHORT Offset = *((PUSHORT)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  (Opcode == 0xB4)
+                                  ? FAST486_REG_FS : FAST486_REG_GS,
+                                  Segment);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte)
+{
+    UCHAR Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xB6);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write back the zero-extended value */
+    return Fast486WriteModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          TRUE,
+                                          (ULONG)Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord)
+{
+    USHORT Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xB7);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write back the zero-extended value */
+    return Fast486WriteModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          TRUE,
+                                          (ULONG)Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    UINT DataSize;
+    ULONG BitNumber;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Get the bit number */
+    BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
+                            : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
+
+    if (ModRegRm.Memory)
+    {
+        /*
+         * For memory operands, add the bit offset divided by
+         * the data size to the address
+         */
+        ModRegRm.MemoryAddress += BitNumber / DataSize;
+    }
+
+    /* Normalize the bit number */
+    BitNumber %= DataSize;
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Toggle the bit */
+        Value ^= 1 << BitNumber;
+
+        /* Write back the result */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        /* Toggle the bit */
+        Value ^= 1 << BitNumber;
+
+        /* Write back the result */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf)
+{
+    INT i;
+    ULONG Value = 0;
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    ULONG BitNumber;
+    UINT DataSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xBC);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the value */
+    if (OperandSize)
+    {
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          (PUSHORT)NULL,
+                                          (PUSHORT)&Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Set ZF */
+    State->Flags.Zf = (Value == 0);
+    if (State->Flags.Zf) return TRUE;
+
+    for (i = 0; i < DataSize; i++)
+    {
+        if(Value & (1 << i))
+        {
+            /* Save the bit number */
+            BitNumber = i;
+
+            /* Exit the loop */
+            break;
+        }
+    }
+
+    /* Write back the result */
+    if (OperandSize)
+    {
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr)
+{
+    INT i;
+    ULONG Value = 0;
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    ULONG BitNumber;
+    UINT DataSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xBD);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the value */
+    if (OperandSize)
+    {
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          (PUSHORT)NULL,
+                                          (PUSHORT)&Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Set ZF according to the value */
+    State->Flags.Zf = (Value == 0);
+    if (State->Flags.Zf) return TRUE;
+
+    for (i = DataSize - 1; i >= 0; i--)
+    {
+        if(Value & (1 << i))
+        {
+            /* Save the bit number */
+            BitNumber = i;
+
+            /* Exit the loop */
+            break;
+        }
+    }
+
+    /* Write back the result */
+    if (OperandSize)
+    {
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte)
+{
+    CHAR Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xBE);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, (PUCHAR)&Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write back the sign-extended value */
+    return Fast486WriteModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          TRUE,
+                                          (ULONG)((LONG)Value));
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord)
+{
+    SHORT Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xBF);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write back the sign-extended value */
+    return Fast486WriteModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          TRUE,
+                                          (ULONG)((LONG)Value));
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp)
+{
+    BOOLEAN Jump = FALSE;
+    LONG Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF0) == 0x80);
+
+    /* Fetch the offset */
+    if (Size)
+    {
+        if (!Fast486FetchDword(State, (PULONG)&Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        SHORT Value;
+
+        if (!Fast486FetchWord(State, (PUSHORT)&Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Sign-extend */
+        Offset = (LONG)Value;
+    }
+
+    switch ((Opcode & 0x0F) >> 1)
+    {
+        /* JO / JNO */
+        case 0:
+        {
+            Jump = State->Flags.Of;
+            break;
+        }
+
+        /* JC / JNC */
+        case 1:
+        {
+            Jump = State->Flags.Cf;
+            break;
+        }
+
+        /* JZ / JNZ */
+        case 2:
+        {
+            Jump = State->Flags.Zf;
+            break;
+        }
+
+        /* JBE / JNBE */
+        case 3:
+        {
+            Jump = State->Flags.Cf || State->Flags.Zf;
+            break;
+        }
+
+        /* JS / JNS */
+        case 4:
+        {
+            Jump = State->Flags.Sf;
+            break;
+        }
+
+        /* JP / JNP */
+        case 5:
+        {
+            Jump = State->Flags.Pf;
+            break;
+        }
+
+        /* JL / JNL */
+        case 6:
+        {
+            Jump = State->Flags.Sf != State->Flags.Of;
+            break;
+        }
+
+        /* JLE / JNLE */
+        case 7:
+        {
+            Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
+            break;
+        }
+    }
+
+    if (Opcode & 1)
+    {
+        /* Invert the result */
+        Jump = !Jump;
+    }
+
+    if (Jump)
+    {
+        /* Move the instruction pointer */
+        State->InstPtr.Long += Offset;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet)
+{
+    BOOLEAN Value = FALSE;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF0) == 0x90);
+
+    switch ((Opcode & 0x0F) >> 1)
+    {
+        /* SETO / SETNO */
+        case 0:
+        {
+            Value = State->Flags.Of;
+            break;
+        }
+
+        /* SETC / SETNC */
+        case 1:
+        {
+            Value = State->Flags.Cf;
+            break;
+        }
+
+        /* SETZ / SETNZ */
+        case 2:
+        {
+            Value = State->Flags.Zf;
+            break;
+        }
+
+        /* SETBE / SETNBE */
+        case 3:
+        {
+            Value = State->Flags.Cf || State->Flags.Zf;
+            break;
+        }
+
+        /* SETS / SETNS */
+        case 4:
+        {
+            Value = State->Flags.Sf;
+            break;
+        }
+
+        /* SETP / SETNP */
+        case 5:
+        {
+            Value = State->Flags.Pf;
+            break;
+        }
+
+        /* SETL / SETNL */
+        case 6:
+        {
+            Value = State->Flags.Sf != State->Flags.Of;
+            break;
+        }
+
+        /* SETLE / SETNLE */
+        case 7:
+        {
+            Value = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
+            break;
+        }
+    }
+
+    if (Opcode & 1)
+    {
+        /* Invert the result */
+        Value = !Value;
+    }
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte)
+{
+    UCHAR Source, Destination, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xC0);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &Source,
+                                      &Destination))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = Source + Destination;
+
+    /* Update the flags */
+    State->Flags.Cf = (Result < Source) && (Result < Destination);
+    State->Flags.Of = ((Source & SIGN_FLAG_BYTE) == (Destination & SIGN_FLAG_BYTE))
+                      && ((Source & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write the sum to the destination */
+    if (!Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write the old value of the destination to the source */
+    if (!Fast486WriteModrmByteOperands(State, &ModRegRm, TRUE, Destination))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xC1);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG Source, Destination, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &Source,
+                                          &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = Source + Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < Source) && (Result < Destination);
+        State->Flags.Of = ((Source & SIGN_FLAG_LONG) == (Destination & SIGN_FLAG_LONG))
+                          && ((Source & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write the old value of the destination to the source */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the sum to the destination */
+        if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT Source, Destination, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &Source,
+                                          &Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = Source + Destination;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < Source) && (Result < Destination);
+        State->Flags.Of = ((Source & SIGN_FLAG_WORD) == (Destination & SIGN_FLAG_WORD))
+                          && ((Source & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write the old value of the destination to the source */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, Destination))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the sum to the destination */
+        if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap)
+{
+    PUCHAR Pointer;
+
+    NO_LOCK_PREFIX();
+
+    /* Get a pointer to the value */
+    Pointer = (PUCHAR)&State->GeneralRegs[Opcode & 0x07].Long;
+
+    /* Swap the byte order */
+    SWAP(Pointer[0], Pointer[3]);
+    SWAP(Pointer[1], Pointer[2]);
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeExtended)
+{
+    UCHAR SecondOpcode;
+
+    /* Fetch the second operation code */
+    if (!Fast486FetchByte(State, &SecondOpcode))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Fast486ExtendedHandlers[SecondOpcode] != NULL)
+    {
+        /* Call the extended opcode handler */
+        return Fast486ExtendedHandlers[SecondOpcode](State, SecondOpcode);
+    }
+    else
+    {
+        /* This is not a valid opcode */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+}
+
diff --git a/lib/fast486/extraops.h b/lib/fast486/extraops.h
new file mode 100644 (file)
index 0000000..eab8e28
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * extraops.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _EXTRAOPS_H_
+#define _EXTRAOPS_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap);
+FAST486_OPCODE_HANDLER(Fast486OpcodeExtended);
+
+#endif // _EXTRAOPS_H_
+
+/* EOF */
+
diff --git a/lib/fast486/fast486.c b/lib/fast486/fast486.c
new file mode 100644 (file)
index 0000000..c47814b
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fast486.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "common.h"
+#include "opcodes.h"
+
+/* DEFINES ********************************************************************/
+
+typedef enum
+{
+    FAST486_STEP_INTO,
+    FAST486_STEP_OVER,
+    FAST486_STEP_OUT,
+    FAST486_CONTINUE
+} FAST486_EXEC_CMD;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static
+inline
+VOID
+NTAPI
+Fast486ExecutionControl(PFAST486_STATE State, FAST486_EXEC_CMD Command)
+{
+    UCHAR Opcode;
+    INT ProcedureCallCount = 0;
+
+    /* Main execution loop */
+    do
+    {
+        /* Check if this is a new instruction */
+        if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr;
+
+        /* Perform an instruction fetch */
+        if (!Fast486FetchByte(State, &Opcode))
+        {
+            /* Exception occurred */
+            State->PrefixFlags = 0;
+            continue;
+        }
+
+        // TODO: Check for CALL/RET to update ProcedureCallCount.
+
+        if (Fast486OpcodeHandlers[Opcode] != NULL)
+        {
+            /* Call the opcode handler */
+            Fast486OpcodeHandlers[Opcode](State, Opcode);
+        }
+        else
+        {
+            /* This is not a valid opcode */
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+        }
+
+        if (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix)
+        {
+            /* This is a prefix, go to the next instruction immediately */
+            continue;
+        }
+
+        /* A non-prefix opcode has been executed, reset the prefix flags */
+        State->PrefixFlags = 0;
+
+        /*
+         * Check if there is an interrupt to execute, or a hardware interrupt signal
+         * while interrupts are enabled.
+         */
+        if (State->IntStatus == FAST486_INT_EXECUTE)
+        {
+            FAST486_IDT_ENTRY IdtEntry;
+
+            /* Get the interrupt vector */
+            if (Fast486GetIntVector(State, State->PendingIntNum, &IdtEntry))
+            {
+                /* Perform the interrupt */
+                Fast486InterruptInternal(State,
+                                         IdtEntry.Selector,
+                                         MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
+                                         IdtEntry.Type);
+
+                /* Restore the prefix flags, which would be set to OPSIZE for 32-bit real mode */
+                State->PrefixFlags = 0;
+            }
+
+            /* Clear the interrupt status */
+            State->IntStatus = FAST486_INT_NONE;
+        }
+        else if (State->Flags.If
+                 && (State->IntAckCallback != NULL)
+                 && (State->IntStatus == FAST486_INT_SIGNAL))
+        {
+            /* Acknowledge the interrupt to get the number */
+            State->PendingIntNum = State->IntAckCallback(State);
+
+            /* Set the interrupt status to execute on the next instruction */
+            State->IntStatus = FAST486_INT_EXECUTE;
+        }
+    }
+    while ((Command == FAST486_CONTINUE)
+           || (Command == FAST486_STEP_OVER && ProcedureCallCount > 0)
+           || (Command == FAST486_STEP_OUT && ProcedureCallCount >= 0)
+           || (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix));
+}
+
+/* DEFAULT CALLBACKS **********************************************************/
+
+static VOID
+NTAPI
+Fast486MemReadCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    RtlMoveMemory(Buffer, (PVOID)Address, Size);
+}
+
+static VOID
+NTAPI
+Fast486MemWriteCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    RtlMoveMemory((PVOID)Address, Buffer, Size);
+}
+
+static VOID
+NTAPI
+Fast486IoReadCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
+{
+    UNREFERENCED_PARAMETER(State);
+    UNREFERENCED_PARAMETER(Port);
+    UNREFERENCED_PARAMETER(Buffer);
+    UNREFERENCED_PARAMETER(DataCount);
+    UNREFERENCED_PARAMETER(DataSize);
+}
+
+static VOID
+NTAPI
+Fast486IoWriteCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
+{
+    UNREFERENCED_PARAMETER(State);
+    UNREFERENCED_PARAMETER(Port);
+    UNREFERENCED_PARAMETER(Buffer);
+    UNREFERENCED_PARAMETER(DataCount);
+    UNREFERENCED_PARAMETER(DataSize);
+}
+
+static VOID
+NTAPI
+Fast486IdleCallback(PFAST486_STATE State)
+{
+    UNREFERENCED_PARAMETER(State);
+}
+
+static VOID
+NTAPI
+Fast486BopCallback(PFAST486_STATE State, UCHAR BopCode)
+{
+    UNREFERENCED_PARAMETER(State);
+    UNREFERENCED_PARAMETER(BopCode);
+}
+
+static UCHAR
+NTAPI
+Fast486IntAckCallback(PFAST486_STATE State)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    /* Return something... */
+    return 0;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+NTAPI
+Fast486Initialize(PFAST486_STATE         State,
+                  FAST486_MEM_READ_PROC  MemReadCallback,
+                  FAST486_MEM_WRITE_PROC MemWriteCallback,
+                  FAST486_IO_READ_PROC   IoReadCallback,
+                  FAST486_IO_WRITE_PROC  IoWriteCallback,
+                  FAST486_IDLE_PROC      IdleCallback,
+                  FAST486_BOP_PROC       BopCallback,
+                  FAST486_INT_ACK_PROC   IntAckCallback,
+                  PULONG                 Tlb)
+{
+    /* Set the callbacks (or use default ones if some are NULL) */
+    State->MemReadCallback  = (MemReadCallback  ? MemReadCallback  : Fast486MemReadCallback );
+    State->MemWriteCallback = (MemWriteCallback ? MemWriteCallback : Fast486MemWriteCallback);
+    State->IoReadCallback   = (IoReadCallback   ? IoReadCallback   : Fast486IoReadCallback  );
+    State->IoWriteCallback  = (IoWriteCallback  ? IoWriteCallback  : Fast486IoWriteCallback );
+    State->IdleCallback     = (IdleCallback     ? IdleCallback     : Fast486IdleCallback    );
+    State->BopCallback      = (BopCallback      ? BopCallback      : Fast486BopCallback     );
+    State->IntAckCallback   = (IntAckCallback   ? IntAckCallback   : Fast486IntAckCallback  );
+
+    /* Set the TLB (if given) */
+    State->Tlb = Tlb;
+
+    /* Reset the CPU */
+    Fast486Reset(State);
+}
+
+VOID
+NTAPI
+Fast486Reset(PFAST486_STATE State)
+{
+    FAST486_SEG_REGS i;
+
+    FAST486_MEM_READ_PROC  MemReadCallback  = State->MemReadCallback;
+    FAST486_MEM_WRITE_PROC MemWriteCallback = State->MemWriteCallback;
+    FAST486_IO_READ_PROC   IoReadCallback   = State->IoReadCallback;
+    FAST486_IO_WRITE_PROC  IoWriteCallback  = State->IoWriteCallback;
+    FAST486_IDLE_PROC      IdleCallback     = State->IdleCallback;
+    FAST486_BOP_PROC       BopCallback      = State->BopCallback;
+    FAST486_INT_ACK_PROC   IntAckCallback   = State->IntAckCallback;
+    PULONG                 Tlb              = State->Tlb;
+
+    /* Clear the entire structure */
+    RtlZeroMemory(State, sizeof(*State));
+
+    /* Initialize the registers */
+    State->Flags.AlwaysSet = 1;
+    State->InstPtr.LowWord = 0xFFF0;
+
+    /* Set the CPL to 0 */
+    State->Cpl = 0;
+
+    /* Initialize segments */
+    for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
+    {
+        State->SegmentRegs[i].Selector = 0;
+        State->SegmentRegs[i].Base = 0;
+        State->SegmentRegs[i].Limit = 0xFFFF;
+        State->SegmentRegs[i].Present = TRUE;
+        State->SegmentRegs[i].ReadWrite = TRUE;
+        State->SegmentRegs[i].Executable = FALSE;
+        State->SegmentRegs[i].DirConf = FALSE;
+        State->SegmentRegs[i].SystemType = 1; // Segment descriptor
+        State->SegmentRegs[i].Dpl = 0;
+        State->SegmentRegs[i].Size = FALSE; // 16-bit
+    }
+
+    /* Initialize the code segment */
+    State->SegmentRegs[FAST486_REG_CS].Executable = TRUE;
+    State->SegmentRegs[FAST486_REG_CS].Selector = 0xF000;
+    State->SegmentRegs[FAST486_REG_CS].Base = 0xFFFF0000;
+
+    /* Initialize the IDT */
+    State->Idtr.Size = 0x3FF;
+    State->Idtr.Address = 0;
+
+#ifndef FAST486_NO_FPU
+    /* Initialize CR0 */
+    State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET;
+#endif
+
+    /* Restore the callbacks and TLB */
+    State->MemReadCallback  = MemReadCallback;
+    State->MemWriteCallback = MemWriteCallback;
+    State->IoReadCallback   = IoReadCallback;
+    State->IoWriteCallback  = IoWriteCallback;
+    State->IdleCallback     = IdleCallback;
+    State->BopCallback      = BopCallback;
+    State->IntAckCallback   = IntAckCallback;
+    State->Tlb              = Tlb;
+}
+
+VOID
+NTAPI
+Fast486DumpState(PFAST486_STATE State)
+{
+    DPRINT1("\nCPU currently executing in %s mode at %04X:%08X\n",
+            (State->ControlRegisters[0] & FAST486_CR0_PE) ? "protected" : "real",
+            State->SegmentRegs[FAST486_REG_CS].Selector,
+            State->InstPtr.Long);
+    DPRINT1("\nGeneral purpose registers:\n"
+            "EAX = %08X\tECX = %08X\tEDX = %08X\tEBX = %08X\n"
+            "ESP = %08X\tEBP = %08X\tESI = %08X\tEDI = %08X\n",
+            State->GeneralRegs[FAST486_REG_EAX].Long,
+            State->GeneralRegs[FAST486_REG_ECX].Long,
+            State->GeneralRegs[FAST486_REG_EDX].Long,
+            State->GeneralRegs[FAST486_REG_EBX].Long,
+            State->GeneralRegs[FAST486_REG_ESP].Long,
+            State->GeneralRegs[FAST486_REG_EBP].Long,
+            State->GeneralRegs[FAST486_REG_ESI].Long,
+            State->GeneralRegs[FAST486_REG_EDI].Long);
+    DPRINT1("\nSegment registers:\n"
+            "ES = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
+            "CS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
+            "SS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
+            "DS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
+            "FS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n"
+            "GS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n",
+            State->SegmentRegs[FAST486_REG_ES].Selector,
+            State->SegmentRegs[FAST486_REG_ES].Base,
+            State->SegmentRegs[FAST486_REG_ES].Limit,
+            State->SegmentRegs[FAST486_REG_ES].Dpl,
+            State->SegmentRegs[FAST486_REG_CS].Selector,
+            State->SegmentRegs[FAST486_REG_CS].Base,
+            State->SegmentRegs[FAST486_REG_CS].Limit,
+            State->SegmentRegs[FAST486_REG_CS].Dpl,
+            State->SegmentRegs[FAST486_REG_SS].Selector,
+            State->SegmentRegs[FAST486_REG_SS].Base,
+            State->SegmentRegs[FAST486_REG_SS].Limit,
+            State->SegmentRegs[FAST486_REG_SS].Dpl,
+            State->SegmentRegs[FAST486_REG_DS].Selector,
+            State->SegmentRegs[FAST486_REG_DS].Base,
+            State->SegmentRegs[FAST486_REG_DS].Limit,
+            State->SegmentRegs[FAST486_REG_DS].Dpl,
+            State->SegmentRegs[FAST486_REG_FS].Selector,
+            State->SegmentRegs[FAST486_REG_FS].Base,
+            State->SegmentRegs[FAST486_REG_FS].Limit,
+            State->SegmentRegs[FAST486_REG_FS].Dpl,
+            State->SegmentRegs[FAST486_REG_GS].Selector,
+            State->SegmentRegs[FAST486_REG_GS].Base,
+            State->SegmentRegs[FAST486_REG_GS].Limit,
+            State->SegmentRegs[FAST486_REG_GS].Dpl);
+    DPRINT1("\nFlags: %08X (%s %s %s %s %s %s %s %s %s %s %s %s) Iopl: %u\n",
+            State->Flags.Long,
+            State->Flags.Cf ? "CF" : "cf",
+            State->Flags.Pf ? "PF" : "pf",
+            State->Flags.Af ? "AF" : "af",
+            State->Flags.Zf ? "ZF" : "zf",
+            State->Flags.Sf ? "SF" : "sf",
+            State->Flags.Tf ? "TF" : "tf",
+            State->Flags.If ? "IF" : "if",
+            State->Flags.Df ? "DF" : "df",
+            State->Flags.Of ? "OF" : "of",
+            State->Flags.Nt ? "NT" : "nt",
+            State->Flags.Rf ? "RF" : "rf",
+            State->Flags.Vm ? "VM" : "vm",
+            State->Flags.Iopl);
+    DPRINT1("\nControl Registers:\n"
+            "CR0 = %08X\tCR2 = %08X\tCR3 = %08X\n",
+            State->ControlRegisters[FAST486_REG_CR0],
+            State->ControlRegisters[FAST486_REG_CR2],
+            State->ControlRegisters[FAST486_REG_CR3]);
+    DPRINT1("\nDebug Registers:\n"
+            "DR0 = %08X\tDR1 = %08X\tDR2 = %08X\n"
+            "DR3 = %08X\tDR4 = %08X\tDR5 = %08X\n",
+            State->DebugRegisters[FAST486_REG_DR0],
+            State->DebugRegisters[FAST486_REG_DR1],
+            State->DebugRegisters[FAST486_REG_DR2],
+            State->DebugRegisters[FAST486_REG_DR3],
+            State->DebugRegisters[FAST486_REG_DR4],
+            State->DebugRegisters[FAST486_REG_DR5]);
+}
+
+VOID
+NTAPI
+Fast486Continue(PFAST486_STATE State)
+{
+    /* Call the internal function */
+    Fast486ExecutionControl(State, FAST486_CONTINUE);
+}
+
+VOID
+NTAPI
+Fast486StepInto(PFAST486_STATE State)
+{
+    /* Call the internal function */
+    Fast486ExecutionControl(State, FAST486_STEP_INTO);
+}
+
+VOID
+NTAPI
+Fast486StepOver(PFAST486_STATE State)
+{
+    /* Call the internal function */
+    Fast486ExecutionControl(State, FAST486_STEP_OVER);
+}
+
+VOID
+NTAPI
+Fast486StepOut(PFAST486_STATE State)
+{
+    /* Call the internal function */
+    Fast486ExecutionControl(State, FAST486_STEP_OUT);
+}
+
+VOID
+NTAPI
+Fast486Interrupt(PFAST486_STATE State, UCHAR Number)
+{
+    /* Set the interrupt status and the number */
+    State->IntStatus = FAST486_INT_EXECUTE;
+    State->PendingIntNum = Number;
+}
+
+VOID
+NTAPI
+Fast486InterruptSignal(PFAST486_STATE State)
+{
+    /* Set the interrupt status */
+    State->IntStatus = FAST486_INT_SIGNAL;
+}
+
+VOID
+NTAPI
+Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
+{
+    /* Load the new CS */
+    if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
+    {
+        /* An exception occurred, let the handler execute instead */
+        return;
+    }
+
+    /* Set the new IP */
+    State->InstPtr.Long = Offset;
+}
+
+VOID
+NTAPI
+Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset)
+{
+    /* Load the new SS */
+    if (!Fast486LoadSegment(State, FAST486_REG_SS, Segment))
+    {
+        /* An exception occurred, let the handler execute instead */
+        return;
+    }
+
+    /* Set the new SP */
+    State->GeneralRegs[FAST486_REG_ESP].Long = Offset;
+}
+
+VOID
+NTAPI
+Fast486SetSegment(PFAST486_STATE State,
+                  FAST486_SEG_REGS Segment,
+                  USHORT Selector)
+{
+    /* Call the internal function */
+    Fast486LoadSegment(State, Segment, Selector);
+}
+
+/* EOF */
diff --git a/lib/fast486/fpu.c b/lib/fast486/fpu.c
new file mode 100644 (file)
index 0000000..18f4a89
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fpu.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "common.h"
+#include "opcodes.h"
+#include "fpu.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+#else
+    /* Do nothing */
+    return TRUE;
+#endif
+}
+
+/* EOF */
diff --git a/lib/fast486/fpu.h b/lib/fast486/fpu.h
new file mode 100644 (file)
index 0000000..63128a4
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fpu.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _FPU_H_
+#define _FPU_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+#define FPU_CHECK() if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_EM) \
+                    { \
+                        Fast486Exception(State, FAST486_EXCEPTION_NM); \
+                        return FALSE; \
+                    }
+#define FPU_ST(i) State->FpuRegisters[(State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS]
+
+enum
+{
+    FPU_SINGLE_PRECISION = 0,
+    FPU_DOUBLE_PRECISION = 2,
+    FPU_DOUBLE_EXT_PRECISION = 3
+};
+
+enum
+{
+    FPU_TAG_VALID = 0,
+    FPU_TAG_ZERO = 1,
+    FPU_TAG_SPECIAL = 2,
+    FPU_TAG_EMPTY = 3
+};
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF);
+
+#endif // _FPU_H_
+
+/* EOF */
diff --git a/lib/fast486/opcodes.c b/lib/fast486/opcodes.c
new file mode 100644 (file)
index 0000000..3dffdaa
--- /dev/null
@@ -0,0 +1,6312 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opcodes.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "opcodes.h"
+#include "opgroups.h"
+#include "extraops.h"
+#include "common.h"
+#include "fpu.h"
+
+/* PUBLIC VARIABLES ***********************************************************/
+
+FAST486_OPCODE_HANDLER_PROC
+Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS] =
+{
+    Fast486OpcodeAddByteModrm,
+    Fast486OpcodeAddModrm,
+    Fast486OpcodeAddByteModrm,
+    Fast486OpcodeAddModrm,
+    Fast486OpcodeAddAl,
+    Fast486OpcodeAddEax,
+    Fast486OpcodePushEs,
+    Fast486OpcodePopEs,
+    Fast486OpcodeOrByteModrm,
+    Fast486OpcodeOrModrm,
+    Fast486OpcodeOrByteModrm,
+    Fast486OpcodeOrModrm,
+    Fast486OpcodeOrAl,
+    Fast486OpcodeOrEax,
+    Fast486OpcodePushCs,
+    Fast486OpcodeExtended,
+    Fast486OpcodeAdcByteModrm,
+    Fast486OpcodeAdcModrm,
+    Fast486OpcodeAdcByteModrm,
+    Fast486OpcodeAdcModrm,
+    Fast486OpcodeAdcAl,
+    Fast486OpcodeAdcEax,
+    Fast486OpcodePushSs,
+    Fast486OpcodePopSs,
+    Fast486OpcodeSbbByteModrm,
+    Fast486OpcodeSbbModrm,
+    Fast486OpcodeSbbByteModrm,
+    Fast486OpcodeSbbModrm,
+    Fast486OpcodeSbbAl,
+    Fast486OpcodeSbbEax,
+    Fast486OpcodePushDs,
+    Fast486OpcodePopDs,
+    Fast486OpcodeAndByteModrm,
+    Fast486OpcodeAndModrm,
+    Fast486OpcodeAndByteModrm,
+    Fast486OpcodeAndModrm,
+    Fast486OpcodeAndAl,
+    Fast486OpcodeAndEax,
+    Fast486OpcodePrefix,
+    Fast486OpcodeDaa,
+    Fast486OpcodeCmpSubByteModrm,
+    Fast486OpcodeCmpSubModrm,
+    Fast486OpcodeCmpSubByteModrm,
+    Fast486OpcodeCmpSubModrm,
+    Fast486OpcodeCmpSubAl,
+    Fast486OpcodeCmpSubEax,
+    Fast486OpcodePrefix,
+    Fast486OpcodeDas,
+    Fast486OpcodeXorByteModrm,
+    Fast486OpcodeXorModrm,
+    Fast486OpcodeXorByteModrm,
+    Fast486OpcodeXorModrm,
+    Fast486OpcodeXorAl,
+    Fast486OpcodeXorEax,
+    Fast486OpcodePrefix,
+    Fast486OpcodeAaa,
+    Fast486OpcodeCmpSubByteModrm,
+    Fast486OpcodeCmpSubModrm,
+    Fast486OpcodeCmpSubByteModrm,
+    Fast486OpcodeCmpSubModrm,
+    Fast486OpcodeCmpSubAl,
+    Fast486OpcodeCmpSubEax,
+    Fast486OpcodePrefix,
+    Fast486OpcodeAas,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeIncrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodeDecrement,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePushReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePopReg,
+    Fast486OpcodePushAll,
+    Fast486OpcodePopAll,
+    Fast486OpcodeBound,
+    Fast486OpcodeArpl,
+    Fast486OpcodePrefix,
+    Fast486OpcodePrefix,
+    Fast486OpcodePrefix,
+    Fast486OpcodePrefix,
+    Fast486OpcodePushImm,
+    Fast486OpcodeImulModrmImm,
+    Fast486OpcodePushByteImm,
+    Fast486OpcodeImulModrmImm,
+    Fast486OpcodeIns,
+    Fast486OpcodeIns,
+    Fast486OpcodeOuts,
+    Fast486OpcodeOuts,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeShortConditionalJmp,
+    Fast486OpcodeGroup8082,
+    Fast486OpcodeGroup81,
+    Fast486OpcodeGroup8082,
+    Fast486OpcodeGroup83,
+    Fast486OpcodeTestByteModrm,
+    Fast486OpcodeTestModrm,
+    Fast486OpcodeXchgByteModrm,
+    Fast486OpcodeXchgModrm,
+    Fast486OpcodeMovByteModrm,
+    Fast486OpcodeMovModrm,
+    Fast486OpcodeMovByteModrm,
+    Fast486OpcodeMovModrm,
+    Fast486OpcodeMovStoreSeg,
+    Fast486OpcodeLea,
+    Fast486OpcodeMovLoadSeg,
+    Fast486OpcodeGroup8F,
+    Fast486OpcodeNop,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeExchangeEax,
+    Fast486OpcodeCwde,
+    Fast486OpcodeCdq,
+    Fast486OpcodeCallAbs,
+    Fast486OpcodeWait,
+    Fast486OpcodePushFlags,
+    Fast486OpcodePopFlags,
+    Fast486OpcodeSahf,
+    Fast486OpcodeLahf,
+    Fast486OpcodeMovAlOffset,
+    Fast486OpcodeMovEaxOffset,
+    Fast486OpcodeMovOffsetAl,
+    Fast486OpcodeMovOffsetEax,
+    Fast486OpcodeMovs,
+    Fast486OpcodeMovs,
+    Fast486OpcodeCmps,
+    Fast486OpcodeCmps,
+    Fast486OpcodeTestAl,
+    Fast486OpcodeTestEax,
+    Fast486OpcodeStos,
+    Fast486OpcodeStos,
+    Fast486OpcodeLods,
+    Fast486OpcodeLods,
+    Fast486OpcodeScas,
+    Fast486OpcodeScas,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovByteRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeMovRegImm,
+    Fast486OpcodeGroupC0,
+    Fast486OpcodeGroupC1,
+    Fast486OpcodeRet,
+    Fast486OpcodeRet,
+    Fast486OpcodeLdsLes,
+    Fast486OpcodeLdsLes,
+    Fast486OpcodeGroupC6,
+    Fast486OpcodeGroupC7,
+    Fast486OpcodeEnter,
+    Fast486OpcodeLeave,
+    Fast486OpcodeRetFar,
+    Fast486OpcodeRetFar,
+    Fast486OpcodeInt,
+    Fast486OpcodeInt,
+    Fast486OpcodeInt,
+    Fast486OpcodeIret,
+    Fast486OpcodeGroupD0,
+    Fast486OpcodeGroupD1,
+    Fast486OpcodeGroupD2,
+    Fast486OpcodeGroupD3,
+    Fast486OpcodeAam,
+    Fast486OpcodeAad,
+    Fast486OpcodeSalc,
+    Fast486OpcodeXlat,
+    Fast486FpuOpcodeD8,
+    Fast486FpuOpcodeD9,
+    Fast486FpuOpcodeDA,
+    Fast486FpuOpcodeDB,
+    Fast486FpuOpcodeDC,
+    Fast486FpuOpcodeDD,
+    Fast486FpuOpcodeDE,
+    Fast486FpuOpcodeDF,
+    Fast486OpcodeLoop,
+    Fast486OpcodeLoop,
+    Fast486OpcodeLoop,
+    Fast486OpcodeJecxz,
+    Fast486OpcodeInByte,
+    Fast486OpcodeIn,
+    Fast486OpcodeOutByte,
+    Fast486OpcodeOut,
+    Fast486OpcodeCall,
+    Fast486OpcodeJmp,
+    Fast486OpcodeJmpAbs,
+    Fast486OpcodeShortJump,
+    Fast486OpcodeInByte,
+    Fast486OpcodeIn,
+    Fast486OpcodeOutByte,
+    Fast486OpcodeOut,
+    Fast486OpcodePrefix,
+    NULL, // Invalid
+    Fast486OpcodePrefix,
+    Fast486OpcodePrefix,
+    Fast486OpcodeHalt,
+    Fast486OpcodeComplCarry,
+    Fast486OpcodeGroupF6,
+    Fast486OpcodeGroupF7,
+    Fast486OpcodeClearCarry,
+    Fast486OpcodeSetCarry,
+    Fast486OpcodeClearInt,
+    Fast486OpcodeSetInt,
+    Fast486OpcodeClearDir,
+    Fast486OpcodeSetDir,
+    Fast486OpcodeGroupFE,
+    Fast486OpcodeGroupFF,
+};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePrefix)
+{
+    BOOLEAN Valid = FALSE;
+
+    switch (Opcode)
+    {
+        /* ES: */
+        case 0x26:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_ES;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* CS: */
+        case 0x2E:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_CS;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* SS: */
+        case 0x36:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_SS;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* DS: */
+        case 0x3E:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_DS;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* FS: */
+        case 0x64:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_FS;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* GS: */
+        case 0x65:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_SEG))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_SEG;
+                State->SegmentOverride = FAST486_REG_GS;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* OPSIZE */
+        case 0x66:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_OPSIZE))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* ADSIZE */
+        case 0x67:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_ADSIZE))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_ADSIZE;
+                Valid = TRUE;
+            }
+            break;
+        }
+
+        /* LOCK */
+        case 0xF0:
+        {
+            if (!(State->PrefixFlags & FAST486_PREFIX_LOCK))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_LOCK;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* REPNZ */
+        case 0xF2:
+        {
+            /* Mutually exclusive with REP */
+            if (!(State->PrefixFlags
+                & (FAST486_PREFIX_REPNZ | FAST486_PREFIX_REP)))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_REPNZ;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+
+        /* REP / REPZ */
+        case 0xF3:
+        {
+            /* Mutually exclusive with REPNZ */
+            if (!(State->PrefixFlags
+                & (FAST486_PREFIX_REPNZ | FAST486_PREFIX_REP)))
+            {
+                State->PrefixFlags |= FAST486_PREFIX_REP;
+                Valid = TRUE;
+            }
+
+            break;
+        }
+    }
+
+    if (!Valid)
+    {
+        /* Clear all prefixes */
+        State->PrefixFlags = 0;
+
+        /* Throw an exception */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement)
+{
+    ULONG Value;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0x40);
+
+    if (Size)
+    {
+        Value = ++State->GeneralRegs[Opcode & 0x07].Long;
+
+        State->Flags.Of = (Value == SIGN_FLAG_LONG);
+        State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
+    }
+    else
+    {
+        Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
+
+        State->Flags.Of = (Value == SIGN_FLAG_WORD);
+        State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
+    }
+
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Af = ((Value & 0x0F) == 0);
+    State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value));
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement)
+{
+    ULONG Value;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0x48);
+
+    if (Size)
+    {
+        Value = --State->GeneralRegs[Opcode & 0x07].Long;
+
+        State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1));
+        State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
+    }
+    else
+    {
+        Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
+
+        State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1));
+        State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
+    }
+
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Af = ((Value & 0x0F) == 0x0F);
+    State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value));
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushReg)
+{
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0x50);
+
+    /* Call the internal function */
+    return Fast486StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopReg)
+{
+    ULONG Value;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0x58);
+
+    /* Call the internal function */
+    if (!Fast486StackPop(State, &Value)) return FALSE;
+
+    /* Store the value */
+    if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
+    else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeNop)
+{
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        /* Idle cycle */
+        State->IdleCallback(State);
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax)
+{
+    INT Reg = Opcode & 0x07;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0x90);
+
+    /* Exchange the values */
+    if (Size)
+    {
+        ULONG Value;
+
+        Value = State->GeneralRegs[Reg].Long;
+        State->GeneralRegs[Reg].Long = State->GeneralRegs[FAST486_REG_EAX].Long;
+        State->GeneralRegs[FAST486_REG_EAX].Long = Value;
+    }
+    else
+    {
+        USHORT Value;
+
+        Value = State->GeneralRegs[Reg].LowWord;
+        State->GeneralRegs[Reg].LowWord = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Value;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp)
+{
+    BOOLEAN Jump = FALSE;
+    CHAR Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF0) == 0x70);
+
+    TOGGLE_OPSIZE(Size);
+
+    /* Fetch the offset */
+    if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+    {
+        /* An exception occurred */
+        return FALSE;
+    }
+
+    switch ((Opcode & 0x0F) >> 1)
+    {
+        /* JO / JNO */
+        case 0:
+        {
+            Jump = State->Flags.Of;
+            break;
+        }
+
+        /* JC / JNC */
+        case 1:
+        {
+            Jump = State->Flags.Cf;
+            break;
+        }
+
+        /* JZ / JNZ */
+        case 2:
+        {
+            Jump = State->Flags.Zf;
+            break;
+        }
+
+        /* JBE / JNBE */
+        case 3:
+        {
+            Jump = State->Flags.Cf || State->Flags.Zf;
+            break;
+        }
+
+        /* JS / JNS */
+        case 4:
+        {
+            Jump = State->Flags.Sf;
+            break;
+        }
+
+        /* JP / JNP */
+        case 5:
+        {
+            Jump = State->Flags.Pf;
+            break;
+        }
+
+        /* JL / JNL */
+        case 6:
+        {
+            Jump = State->Flags.Sf != State->Flags.Of;
+            break;
+        }
+
+        /* JLE / JNLE */
+        case 7:
+        {
+            Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
+            break;
+        }
+    }
+
+    if (Opcode & 1)
+    {
+        /* Invert the result */
+        Jump = !Jump;
+    }
+
+    if (Jump)
+    {
+        /* Move the instruction pointer */
+        State->InstPtr.Long += Offset;
+
+        if (!Size)
+        {
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xF8);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Clear CF and return success */
+    State->Flags.Cf = FALSE;
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xF9);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Set CF and return success*/
+    State->Flags.Cf = TRUE;
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xF5);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Toggle CF and return success */
+    State->Flags.Cf = !State->Flags.Cf;
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xFA);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    {
+        /* Check IOPL */
+        if (State->Flags.Iopl >= State->SegmentRegs[FAST486_REG_CS].Dpl)
+        {
+            /* Clear the interrupt flag */
+            State->Flags.If = FALSE;
+        }
+        else
+        {
+            /* General Protection Fault */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Just clear the interrupt flag */
+        State->Flags.If = FALSE;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xFB);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    {
+        /* Check IOPL */
+        if (State->Flags.Iopl >= State->SegmentRegs[FAST486_REG_CS].Dpl)
+        {
+            /* Set the interrupt flag */
+            State->Flags.If = TRUE;
+        }
+        else
+        {
+            /* General Protection Fault */
+            Fast486Exception(State, FAST486_EXCEPTION_GP);
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Just set the interrupt flag */
+        State->Flags.If = TRUE;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xFC);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Clear DF and return success */
+    State->Flags.Df = FALSE;
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xFD);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Set DF and return success*/
+    State->Flags.Df = TRUE;
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeHalt)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xF4);
+
+    /* No prefixes allowed */
+    if (State->PrefixFlags)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Privileged instructions can only be executed under CPL = 0 */
+    if (State->SegmentRegs[FAST486_REG_CS].Dpl != 0)
+    {
+        Fast486Exception(State, FAST486_EXCEPTION_GP);
+        return FALSE;
+    }
+
+    /* Halt */
+    // TODO: Halt the CPU until an interrupt occurs, using IdleCallback if needed.
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeInByte)
+{
+    UCHAR Data;
+    ULONG Port;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF7) == 0xE4);
+
+    if (Opcode == 0xE4)
+    {
+        /* Fetch the parameter */
+        if (!Fast486FetchByte(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set the port number to the parameter */
+        Port = Data;
+    }
+    else
+    {
+        /* The port number is in DX */
+        Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
+    }
+
+    /* Read a byte from the I/O port */
+    State->IoReadCallback(State, Port, &Data, 1, sizeof(UCHAR));
+
+    /* Store the result in AL */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Data;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeIn)
+{
+    ULONG Port;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF7) == 0xE5);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Opcode == 0xE5)
+    {
+        UCHAR Data;
+
+        /* Fetch the parameter */
+        if (!Fast486FetchByte(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set the port number to the parameter */
+        Port = Data;
+    }
+    else
+    {
+        /* The port number is in DX */
+        Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
+    }
+
+    if (Size)
+    {
+        ULONG Data;
+
+        /* Read a dword from the I/O port */
+        State->IoReadCallback(State, Port, &Data, 1, sizeof(ULONG));
+
+        /* Store the value in EAX */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Data;
+    }
+    else
+    {
+        USHORT Data;
+
+        /* Read a word from the I/O port */
+        State->IoReadCallback(State, Port, &Data, 1, sizeof(USHORT));
+
+        /* Store the value in AX */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Data;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte)
+{
+    UCHAR Data;
+    ULONG Port;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF7) == 0xE6);
+
+    if (Opcode == 0xE6)
+    {
+        /* Fetch the parameter */
+        if (!Fast486FetchByte(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set the port number to the parameter */
+        Port = Data;
+    }
+    else
+    {
+        /* The port number is in DX */
+        Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
+    }
+
+    /* Read the value from AL */
+    Data = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /* Write the byte to the I/O port */
+    State->IoWriteCallback(State, Port, &Data, 1, sizeof(UCHAR));
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOut)
+{
+    ULONG Port;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF7) == 0xE7);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Opcode == 0xE7)
+    {
+        UCHAR Data;
+
+        /* Fetch the parameter */
+        if (!Fast486FetchByte(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set the port number to the parameter */
+        Port = Data;
+    }
+    else
+    {
+        /* The port number is in DX */
+        Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
+    }
+
+    if (Size)
+    {
+        /* Get the value from EAX */
+        ULONG Data = State->GeneralRegs[FAST486_REG_EAX].Long;
+
+        /* Write a dword to the I/O port */
+        State->IoWriteCallback(State, Port, &Data, 1, sizeof(ULONG));
+    }
+    else
+    {
+        /* Get the value from AX */
+        USHORT Data = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+
+        /* Write a word to the I/O port */
+        State->IoWriteCallback(State, Port, &Data, 1, sizeof(USHORT));
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump)
+{
+    CHAR Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xEB);
+
+    /* Fetch the offset */
+    if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+    {
+        /* An exception occurred */
+        return FALSE;
+    }
+
+    /* Move the instruction pointer */
+    State->InstPtr.Long += Offset;
+
+    if (!Size)
+    {
+        /* Clear the top half of EIP */
+        State->InstPtr.Long &= 0xFFFF;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0xB8);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Size)
+    {
+        ULONG Value;
+
+        /* Fetch the dword */
+        if (!Fast486FetchDword(State, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Store the value in the register */
+        State->GeneralRegs[Opcode & 0x07].Long = Value;
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Fetch the word */
+        if (!Fast486FetchWord(State, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Store the value in the register */
+        State->GeneralRegs[Opcode & 0x07].LowWord = Value;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm)
+{
+    UCHAR Value;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xF8) == 0xB0);
+
+    if (State->PrefixFlags != 0)
+    {
+        /* Invalid prefix */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Fetch the byte */
+    if (!Fast486FetchByte(State, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Opcode & 0x04)
+    {
+        /* AH, CH, DH or BH */
+        State->GeneralRegs[Opcode & 0x03].HighByte = Value;
+    }
+    else
+    {
+        /* AL, CL, DL or BL */
+        State->GeneralRegs[Opcode & 0x03].LowByte = Value;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x00);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue + SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x01);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x04);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue + SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x05);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x08);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue | SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x09);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue | SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue | SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x0C);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue | SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x0D);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue | SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue | SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x20);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue & SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x21);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x24);
+
+    NO_LOCK_PREFIX();
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue & SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x25);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x30);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue ^ SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x31);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue ^ SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue ^ SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x34);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue ^ SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x35);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue ^ SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue ^ SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x84);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+    /* Calculate the result */
+    Result = FirstValue & SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* The result is discarded */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x85);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
+
+    /* The result is discarded */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA8);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue & SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = FALSE;
+    State->Flags.Of = FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* The result is discarded */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA9);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue & SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = FALSE;
+        State->Flags.Of = FALSE;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
+
+    /* The result is discarded */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm)
+{
+    UCHAR FirstValue, SecondValue;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x86);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write the value from the register to the R/M */
+    if (!Fast486WriteModrmByteOperands(State,
+                                       &ModRegRm,
+                                       FALSE,
+                                       FirstValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write the value from the R/M to the register */
+    if (!Fast486WriteModrmByteOperands(State,
+                                       &ModRegRm,
+                                       TRUE,
+                                       SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x87);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the value from the register to the R/M */
+        if (!Fast486WriteModrmDwordOperands(State,
+                                            &ModRegRm,
+                                            FALSE,
+                                            FirstValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the value from the R/M to the register */
+        if (!Fast486WriteModrmDwordOperands(State,
+                                            &ModRegRm,
+                                            TRUE,
+                                            SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the value from the register to the R/M */
+        if (!Fast486WriteModrmWordOperands(State,
+                                           &ModRegRm,
+                                           FALSE,
+                                           FirstValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write the value from the R/M to the register */
+        if (!Fast486WriteModrmWordOperands(State,
+                                           &ModRegRm,
+                                           TRUE,
+                                           SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* The result is discarded */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushEs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_ES].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopEs)
+{
+    ULONG NewSelector;
+
+    if (!Fast486StackPop(State, &NewSelector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486LoadSegment(State, FAST486_REG_ES, LOWORD(NewSelector));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushCs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x10);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue + SecondValue + State->Flags.Cf;
+
+    /* Special exception for CF */
+    State->Flags.Cf = State->Flags.Cf
+                      && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
+
+    /* Update the flags */
+    State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x11);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue + State->Flags.Cf;
+
+        /* Special exception for CF */
+        State->Flags.Cf = State->Flags.Cf
+                          && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue + State->Flags.Cf;
+
+        /* Special exception for CF */
+        State->Flags.Cf = State->Flags.Cf
+                          && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x14);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue + SecondValue + State->Flags.Cf;
+
+    /* Special exception for CF */
+    State->Flags.Cf = State->Flags.Cf &&
+                      ((FirstValue == 0xFF) || (SecondValue == 0xFF));
+
+    /* Update the flags */
+    State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x15);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue + State->Flags.Cf;
+
+        /* Special exception for CF */
+        State->Flags.Cf = State->Flags.Cf &&
+                          ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue + SecondValue + State->Flags.Cf;
+
+        /* Special exception for CF */
+        State->Flags.Cf = State->Flags.Cf &&
+                          ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
+
+        /* Update the flags */
+        State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushSs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_SS].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopSs)
+{
+    ULONG NewSelector;
+
+    if (!Fast486StackPop(State, &NewSelector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486LoadSegment(State, FAST486_REG_SS, LOWORD(NewSelector));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    INT Carry = State->Flags.Cf ? 1 : 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x18);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check if this is the instruction that writes to R/M */
+    if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+    {
+        /* Swap the order */
+        SWAP(FirstValue, SecondValue);
+    }
+
+    /* Calculate the result */
+    Result = FirstValue - SecondValue - Carry;
+
+    /* Update the flags */
+    State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+    INT Carry = State->Flags.Cf ? 1 : 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x19);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                           &ModRegRm,
+                                           &FirstValue,
+                                           &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Check if this is the instruction that writes to R/M */
+        if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+        {
+            /* Swap the order */
+            SWAP(FirstValue, SecondValue);
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue - Carry;
+
+        /* Update the flags */
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Check if this is the instruction that writes to R/M */
+        if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+        {
+            /* Swap the order */
+            SWAP(FirstValue, SecondValue);
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue - Carry;
+
+        /* Update the flags */
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             Opcode & FAST486_OPCODE_WRITE_REG,
+                                             Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+    INT Carry = State->Flags.Cf ? 1 : 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x1C);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue - SecondValue - Carry;
+
+    /* Update the flags */
+    State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Write back the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+
+    return TRUE;
+
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    INT Carry = State->Flags.Cf ? 1 : 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x1D);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue - Carry;
+
+        /* Update the flags */
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue - Carry;
+
+        /* Update the flags */
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+    }
+
+    return TRUE;
+
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushDs)
+{
+    /* Call the internal API */
+    return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_DS].Selector);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopDs)
+{
+    ULONG NewSelector;
+
+    if (!Fast486StackPop(State, &NewSelector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486LoadSegment(State, FAST486_REG_DS, LOWORD(NewSelector));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeDaa)
+{
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    BOOLEAN Carry = State->Flags.Cf;
+
+    /* Clear the carry flag */
+    State->Flags.Cf = FALSE;
+
+    /* Check if the first BCD digit is invalid or there was a carry from it */
+    if (((Value & 0x0F) > 9) || State->Flags.Af)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x06;
+        if (State->GeneralRegs[FAST486_REG_EAX].LowByte < 0x06)
+        {
+            /* A carry occurred */
+            State->Flags.Cf = TRUE;
+        }
+
+        /* Set the adjust flag */
+        State->Flags.Af = TRUE;
+    }
+
+    /* Check if the second BCD digit is invalid or there was a carry from it */
+    if ((Value > 0x99) || Carry)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x60;
+
+        /* There was a carry */
+        State->Flags.Cf = TRUE;
+    }
+
+    Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /* Update the flags */
+    State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xED) == 0x28);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check if this is the instruction that writes to R/M */
+    if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+    {
+        /* Swap the order */
+        SWAP(FirstValue, SecondValue);
+    }
+
+    /* Calculate the result */
+    Result = FirstValue - SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Check if this is not a CMP */
+    if (!(Opcode & 0x10))
+    {
+        /* Write back the result */
+        return Fast486WriteModrmByteOperands(State,
+                                             &ModRegRm,
+                                             Opcode & FAST486_OPCODE_WRITE_REG,
+                                             Result);
+    }
+    else
+    {
+        /* Discard the result */
+        return TRUE;
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xED) == 0x29);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Check if this is the instruction that writes to R/M */
+        if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+        {
+            /* Swap the order */
+            SWAP(FirstValue, SecondValue);
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Check if this is not a CMP */
+        if (!(Opcode & 0x10))
+        {
+            /* Write back the result */
+            return Fast486WriteModrmDwordOperands(State,
+                                                  &ModRegRm,
+                                                  Opcode & FAST486_OPCODE_WRITE_REG,
+                                                  Result);
+        }
+        else
+        {
+            /* Discard the result */
+            return TRUE;
+        }
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Check if this is the instruction that writes to R/M */
+        if (!(Opcode & FAST486_OPCODE_WRITE_REG))
+        {
+            /* Swap the order */
+            SWAP(FirstValue, SecondValue);
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Check if this is not a CMP */
+        if (!(Opcode & 0x10))
+        {
+            /* Write back the result */
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 Opcode & FAST486_OPCODE_WRITE_REG,
+                                                 Result);
+        }
+        else
+        {
+            /* Discard the result */
+            return TRUE;
+        }
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl)
+{
+    UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    UCHAR SecondValue, Result;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xEF) == 0x2C);
+
+    if (State->PrefixFlags)
+    {
+        /* This opcode doesn't take any prefixes */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Result = FirstValue - SecondValue;
+
+    /* Update the flags */
+    State->Flags.Cf = (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
+                      && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
+    State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Check if this is not a CMP */
+    if (!(Opcode & 0x10))
+    {
+        /* Write back the result */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xEF) == 0x2D);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+        ULONG SecondValue, Result;
+
+        if (!Fast486FetchDword(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
+                          && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
+        State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Check if this is not a CMP */
+        if (!(Opcode & 0x10))
+        {
+            /* Write back the result */
+            State->GeneralRegs[FAST486_REG_EAX].Long = Result;
+        }
+    }
+    else
+    {
+        USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+        USHORT SecondValue, Result;
+
+        if (!Fast486FetchWord(State, &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Result = FirstValue - SecondValue;
+
+        /* Update the flags */
+        State->Flags.Cf = (FirstValue < SecondValue);
+        State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
+                          && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
+        State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+
+        /* Check if this is not a CMP */
+        if (!(Opcode & 0x10))
+        {
+            /* Write back the result */
+            State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeDas)
+{
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+    BOOLEAN Carry = State->Flags.Cf;
+
+    /* Clear the carry flag */
+    State->Flags.Cf = FALSE;
+
+    /* Check if the first BCD digit is invalid or there was a borrow */
+    if (((Value & 0x0F) > 9) || State->Flags.Af)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x06;
+        if (State->GeneralRegs[FAST486_REG_EAX].LowByte > 0xFB)
+        {
+            /* A borrow occurred */
+            State->Flags.Cf = TRUE;
+        }
+
+        /* Set the adjust flag */
+        State->Flags.Af = TRUE;
+    }
+
+    /* Check if the second BCD digit is invalid or there was a borrow */
+    if ((Value > 0x99) || Carry)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x60;
+
+        /* There was a borrow */
+        State->Flags.Cf = TRUE;
+    }
+
+    Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /* Update the flags */
+    State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAaa)
+{
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /*
+     * Check if the value in AL is not a valid BCD digit,
+     * or there was a carry from the lowest 4 bits of AL
+     */
+    if (((Value & 0x0F) > 9) || State->Flags.Af)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord += 0x06;
+        State->GeneralRegs[FAST486_REG_EAX].HighByte++;
+
+        /* Set CF and AF */
+        State->Flags.Cf = State->Flags.Af = TRUE;
+    }
+    else
+    {
+        /* Clear CF and AF */
+        State->Flags.Cf = State->Flags.Af = FALSE;
+    }
+
+    /* Keep only the lowest 4 bits of AL */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAas)
+{
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /*
+     * Check if the value in AL is not a valid BCD digit,
+     * or there was a borrow from the lowest 4 bits of AL
+     */
+    if (((Value & 0x0F) > 9) || State->Flags.Af)
+    {
+        /* Correct it */
+        State->GeneralRegs[FAST486_REG_EAX].LowWord -= 0x06;
+        State->GeneralRegs[FAST486_REG_EAX].HighByte--;
+
+        /* Set CF and AF */
+        State->Flags.Cf = State->Flags.Af = TRUE;
+    }
+    else
+    {
+        /* Clear CF and AF */
+        State->Flags.Cf = State->Flags.Af = FALSE;
+    }
+
+    /* Keep only the lowest 4 bits of AL */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushAll)
+{
+    INT i;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_REG SavedEsp = State->GeneralRegs[FAST486_REG_ESP];
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x60);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Push all the registers in order */
+    for (i = 0; i < FAST486_NUM_GEN_REGS; i++)
+    {
+        if (i == FAST486_REG_ESP)
+        {
+            /* Use the saved ESP instead */
+            if (!Fast486StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+        else
+        {
+            /* Push the register */
+            if (!Fast486StackPush(State, Size ? State->GeneralRegs[i].Long
+                                              : State->GeneralRegs[i].LowWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopAll)
+{
+    INT i;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    ULONG Value;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x61);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Pop all the registers in reverse order */
+    for (i = FAST486_NUM_GEN_REGS - 1; i >= 0; i--)
+    {
+        /* Pop the value */
+        if (!Fast486StackPop(State, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Don't modify ESP */
+        if (i != FAST486_REG_ESP)
+        {
+            if (Size) State->GeneralRegs[i].Long = Value;
+            else State->GeneralRegs[i].LowWord = LOWORD(Value);
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeBound)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!ModRegRm.Memory)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Check for the segment override */
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead */
+        Segment = State->SegmentOverride;
+    }
+
+    if (OperandSize)
+    {
+        LONG Index, LowerBound, UpperBound;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State,
+                                           &ModRegRm,
+                                           (PULONG)&Index,
+                                           (PULONG)&LowerBound))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (!Fast486ReadMemory(State,
+                               Segment,
+                               ModRegRm.MemoryAddress + sizeof(ULONG),
+                               FALSE,
+                               &UpperBound,
+                               sizeof(ULONG)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if ((Index < LowerBound) || (Index > UpperBound))
+        {
+            /* Out of bounds */
+            Fast486Exception(State, FAST486_EXCEPTION_BR);
+            return FALSE;
+        }
+    }
+    else
+    {
+        SHORT Index, LowerBound, UpperBound;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          (PUSHORT)&Index,
+                                          (PUSHORT)&LowerBound))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (!Fast486ReadMemory(State,
+                               Segment,
+                               ModRegRm.MemoryAddress + sizeof(USHORT),
+                               FALSE,
+                               &UpperBound,
+                               sizeof(USHORT)))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if ((Index < LowerBound) || (Index > UpperBound))
+        {
+            /* Out of bounds */
+            Fast486Exception(State, FAST486_EXCEPTION_BR);
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeArpl)
+{
+    USHORT FirstValue, SecondValue;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+        || State->Flags.Vm
+        || (State->PrefixFlags & FAST486_PREFIX_LOCK))
+    {
+        /* Cannot be used in real mode or with a LOCK prefix */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmWordOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check if the RPL needs adjusting */
+    if ((SecondValue & 3) < (FirstValue & 3))
+    {
+        /* Adjust the RPL */
+        SecondValue &= ~3;
+        SecondValue |= FirstValue & 3;
+
+        /* Set ZF */
+        State->Flags.Zf = TRUE;
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
+    }
+    else
+    {
+        /* Clear ZF */
+        State->Flags.Zf = FALSE;
+        return TRUE;
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushImm)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x68);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        ULONG Data;
+
+        if (!Fast486FetchDword(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Call the internal API */
+        return Fast486StackPush(State, Data);
+    }
+    else
+    {
+        USHORT Data;
+
+        if (!Fast486FetchWord(State, &Data))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Call the internal API */
+        return Fast486StackPush(State, Data);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+    LONG Multiplier;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x69);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Fetch the parameters */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Opcode == 0x6B)
+    {
+        CHAR Byte;
+
+        /* Fetch the immediate operand */
+        if (!Fast486FetchByte(State, (PUCHAR)&Byte))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        Multiplier = (LONG)Byte;
+    }
+    else
+    {
+        if (OperandSize)
+        {
+            LONG Dword;
+
+            /* Fetch the immediate operand */
+            if (!Fast486FetchDword(State, (PULONG)&Dword))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            Multiplier = Dword;
+        }
+        else
+        {
+            SHORT Word;
+
+            /* Fetch the immediate operand */
+            if (!Fast486FetchWord(State, (PUSHORT)&Word))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            Multiplier = (LONG)Word;
+        }
+    }
+
+    if (OperandSize)
+    {
+        LONG RegValue, Multiplicand;
+        LONGLONG Product;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State,
+                                           &ModRegRm,
+                                           (PULONG)&RegValue,
+                                           (PULONG)&Multiplicand))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Multiply */
+        Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
+
+        /* Check for carry/overflow */
+        State->Flags.Cf = State->Flags.Of = ((Product < MINLONG) || (Product > MAXLONG));
+
+        /* Write-back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              TRUE,
+                                              (ULONG)((LONG)Product));
+    }
+    else
+    {
+        SHORT RegValue, Multiplicand;
+        LONG Product;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          (PUSHORT)&RegValue,
+                                          (PUSHORT)&Multiplicand))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Multiply */
+        Product = (LONG)Multiplicand * (LONG)Multiplier;
+
+        /* Check for carry/overflow */
+        State->Flags.Cf = State->Flags.Of = ((Product < MINSHORT) || (Product > MAXSHORT));
+
+        /* Write-back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             TRUE,
+                                             (USHORT)((SHORT)Product));
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
+{
+    UCHAR Data;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x6A);
+
+    if (!Fast486FetchByte(State, &Data))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Call the internal API */
+    return Fast486StackPush(State, Data);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm)
+{
+    UCHAR FirstValue, SecondValue, Result;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x88);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ReadModrmByteOperands(State,
+                                      &ModRegRm,
+                                      &FirstValue,
+                                      &SecondValue))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
+    else Result = FirstValue;
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         Opcode & FAST486_OPCODE_WRITE_REG,
+                                         Result);
+
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFD) == 0x89);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check the operand size */
+    if (OperandSize)
+    {
+        ULONG FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmDwordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
+        else Result = FirstValue;
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              Opcode & FAST486_OPCODE_WRITE_REG,
+                                              Result);
+    }
+    else
+    {
+        USHORT FirstValue, SecondValue, Result;
+
+        if (!Fast486ReadModrmWordOperands(State,
+                                          &ModRegRm,
+                                          &FirstValue,
+                                          &SecondValue))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue;
+        else Result = FirstValue;
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             Opcode & FAST486_OPCODE_WRITE_REG,
+                                             Result);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovStoreSeg)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x8C);
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register >= FAST486_NUM_SEG_REGS)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              FALSE,
+                                              State->SegmentRegs[ModRegRm.Register].Selector);
+    }
+    else
+    {
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             FALSE,
+                                             State->SegmentRegs[ModRegRm.Register].Selector);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLea)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x8D);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* The second operand must be memory */
+    if (!ModRegRm.Memory)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Write the address to the register */
+    if (OperandSize)
+    {
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              TRUE,
+                                              ModRegRm.MemoryAddress);
+    }
+    else
+    {
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             TRUE,
+                                             ModRegRm.MemoryAddress);
+
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg)
+{
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x8E);
+
+    TOGGLE_ADSIZE(AddressSize);
+    TOGGLE_OPSIZE(OperandSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if ((ModRegRm.Register >= FAST486_NUM_SEG_REGS)
+        || ((FAST486_SEG_REGS)ModRegRm.Register == FAST486_REG_CS))
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Selector;
+
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Selector))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        return Fast486LoadSegment(State, ModRegRm.Register, LOWORD(Selector));
+    }
+    else
+    {
+        USHORT Selector;
+
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        return Fast486LoadSegment(State, ModRegRm.Register, Selector);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCwde)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x98);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Size)
+    {
+        /* Sign extend AX to EAX */
+        State->GeneralRegs[FAST486_REG_EAX].Long = MAKELONG
+        (
+            State->GeneralRegs[FAST486_REG_EAX].LowWord,
+            (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD)
+            ? 0xFFFF : 0x0000
+        );
+    }
+    else
+    {
+        /* Sign extend AL to AX */
+        State->GeneralRegs[FAST486_REG_EAX].HighByte =
+        (State->GeneralRegs[FAST486_REG_EAX].LowByte & SIGN_FLAG_BYTE)
+        ? 0xFF : 0x00;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCdq)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x99);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Size)
+    {
+        /* Sign extend EAX to EDX:EAX */
+        State->GeneralRegs[FAST486_REG_EDX].Long =
+        (State->GeneralRegs[FAST486_REG_EAX].Long & SIGN_FLAG_LONG)
+        ? 0xFFFFFFFF : 0x00000000;
+    }
+    else
+    {
+        /* Sign extend AX to DX:AX */
+        State->GeneralRegs[FAST486_REG_EDX].LowWord =
+        (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD)
+        ? 0xFFFF : 0x0000;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs)
+{
+    USHORT Segment = 0;
+    ULONG Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x9A);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Fetch the offset */
+    if (Size)
+    {
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486FetchWord(State, (PUSHORT)&Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Fetch the segment */
+    if (!Fast486FetchWord(State, &Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Push the current code segment selector */
+    if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Push the current value of the instruction pointer */
+    if (!Fast486StackPush(State, State->InstPtr.Long))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load the new CS */
+    if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load new (E)IP */
+    if (Size) State->InstPtr.Long = Offset;
+    else State->InstPtr.LowWord = LOWORD(Offset);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeWait)
+{
+    // TODO: NOT IMPLEMENTED
+    UNIMPLEMENTED;
+
+    return FALSE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    /* Check for VM86 mode when IOPL is not 3 */
+    if (State->Flags.Vm && (State->Flags.Iopl != 3))
+    {
+        /* Call the VM86 monitor */
+        Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
+        return FALSE;
+    }
+
+    /* Push the flags */
+    if (Size) return Fast486StackPush(State, State->Flags.Long);
+    else return Fast486StackPush(State, LOWORD(State->Flags.Long));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    INT Cpl = Fast486GetCurrentPrivLevel(State);
+    FAST486_FLAGS_REG NewFlags;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    /* Pop the new flags */
+    if (!Fast486StackPop(State, &NewFlags.Long))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check for VM86 mode when IOPL is not 3 */
+    if (State->Flags.Vm && (State->Flags.Iopl != 3))
+    {
+        /* Call the VM86 monitor */
+        Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
+        return FALSE;
+    }
+
+    State->Flags.Cf = NewFlags.Cf;
+    State->Flags.Pf = NewFlags.Pf;
+    State->Flags.Af = NewFlags.Af;
+    State->Flags.Zf = NewFlags.Zf;
+    State->Flags.Sf = NewFlags.Sf;
+    State->Flags.Tf = NewFlags.Tf;
+    State->Flags.Df = NewFlags.Df;
+    State->Flags.Of = NewFlags.Of;
+    State->Flags.Nt = NewFlags.Nt;
+    State->Flags.Ac = NewFlags.Ac;
+
+    if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
+    if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSahf)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x9E);
+
+    /* Set the low-order byte of FLAGS to AH */
+    State->Flags.Long &= 0xFFFFFF00;
+    State->Flags.Long |= State->GeneralRegs[FAST486_REG_EAX].HighByte;
+
+    /* Restore the reserved bits of FLAGS */
+    State->Flags.AlwaysSet = TRUE;
+    State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLahf)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0x9F);
+
+    /* Set AH to the low-order byte of FLAGS */
+    State->GeneralRegs[FAST486_REG_EAX].HighByte = LOBYTE(State->Flags.Long);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeRet)
+{
+    ULONG ReturnAddress;
+    USHORT BytesToPop = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xC2);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Opcode == 0xC2)
+    {
+        /* Fetch the number of bytes to pop after the return */
+        if (!Fast486FetchWord(State, &BytesToPop)) return FALSE;
+    }
+
+    /* Pop the return address */
+    if (!Fast486StackPop(State, &ReturnAddress)) return FALSE;
+
+    /* Return to the calling procedure, and if necessary, pop the parameters */
+    if (Size)
+    {
+        State->InstPtr.Long = ReturnAddress;
+        State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop;
+    }
+    else
+    {
+        State->InstPtr.LowWord = LOWORD(ReturnAddress);
+        State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes)
+{
+    UCHAR FarPointer[6];
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_MOD_REG_RM ModRegRm;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xC4);
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the operands */
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!ModRegRm.Memory)
+    {
+        /* Check if this is a BOP and the host supports BOPs */
+        if ((Opcode == 0xC4)
+            && (ModRegRm.Register == FAST486_REG_EAX)
+            && (ModRegRm.SecondRegister == FAST486_REG_ESP)
+            && (State->BopCallback != NULL))
+        {
+            UCHAR BopCode;
+
+            /* Fetch the BOP code */
+            if (!Fast486FetchByte(State, &BopCode))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Call the BOP handler */
+            State->BopCallback(State, BopCode);
+
+            /* Return success */
+            return TRUE;
+        }
+
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (!Fast486ReadMemory(State,
+                           (State->PrefixFlags & FAST486_PREFIX_SEG)
+                           ? State->SegmentOverride : FAST486_REG_DS,
+                           ModRegRm.MemoryAddress,
+                           FALSE,
+                           FarPointer,
+                           OperandSize ? 6 : 4))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Offset = *((PULONG)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].Long = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  (Opcode == 0xC4)
+                                  ? FAST486_REG_ES : FAST486_REG_DS,
+                                  Segment);
+    }
+    else
+    {
+        USHORT Offset = *((PUSHORT)FarPointer);
+        USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
+
+        /* Set the register to the offset */
+        State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
+
+        /* Load the segment */
+        return Fast486LoadSegment(State,
+                                  (Opcode == 0xC4)
+                                  ? FAST486_REG_ES : FAST486_REG_DS,
+                                  Segment);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeEnter)
+{
+    INT i;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    USHORT FrameSize;
+    UCHAR NestingLevel;
+    FAST486_REG FramePointer;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xC8);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (!Fast486FetchWord(State, &FrameSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486FetchByte(State, &NestingLevel))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Push EBP */
+    if (!Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Save ESP */
+    FramePointer = State->GeneralRegs[FAST486_REG_ESP];
+
+    /* Set up the nested procedure stacks */
+    for (i = 1; i < NestingLevel; i++)
+    {
+        if (Size)
+        {
+            State->GeneralRegs[FAST486_REG_EBP].Long -= 4;
+            Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long);
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_EBP].LowWord -= 2;
+            Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].LowWord);
+        }
+    }
+
+    if (NestingLevel > 0) Fast486StackPush(State, FramePointer.Long);
+
+    /* Set EBP to the frame pointer */
+    State->GeneralRegs[FAST486_REG_EBP] = FramePointer;
+
+    /* Reserve space for the frame */
+    if (Size) State->GeneralRegs[FAST486_REG_ESP].Long -= (ULONG)FrameSize;
+    else State->GeneralRegs[FAST486_REG_ESP].LowWord -= FrameSize;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLeave)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xC9);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    if (Size)
+    {
+        /* Set the stack pointer (ESP) to the base pointer (EBP) */
+        State->GeneralRegs[FAST486_REG_ESP].Long = State->GeneralRegs[FAST486_REG_EBP].Long;
+
+        /* Pop the saved base pointer from the stack */
+        return Fast486StackPop(State, &State->GeneralRegs[FAST486_REG_EBP].Long);
+    }
+    else
+    {
+        ULONG Value;
+
+        /* Set the stack pointer (SP) to the base pointer (BP) */
+        State->GeneralRegs[FAST486_REG_ESP].LowWord = State->GeneralRegs[FAST486_REG_EBP].LowWord;
+
+        /* Pop the saved base pointer from the stack */
+        if (Fast486StackPop(State, &Value))
+        {
+            State->GeneralRegs[FAST486_REG_EBP].LowWord = LOWORD(Value);
+            return TRUE;
+        }
+        else return FALSE;
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar)
+{
+    ULONG Segment = 0;
+    ULONG Offset = 0;
+    USHORT BytesToPop = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xCA);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Opcode == 0xCA)
+    {
+        /* Fetch the number of bytes to pop after the return */
+        if (!Fast486FetchWord(State, &BytesToPop)) return FALSE;
+    }
+
+    /* Pop the offset */
+    if (!Fast486StackPop(State, &Offset))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Pop the segment */
+    if (!Fast486StackPop(State, &Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load the new CS */
+    if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load new (E)IP, and if necessary, pop the parameters */
+    if (Size)
+    {
+        State->InstPtr.Long = Offset;
+        State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop;
+    }
+    else
+    {
+        State->InstPtr.LowWord = LOWORD(Offset);
+        State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeInt)
+{
+    UCHAR IntNum;
+    FAST486_IDT_ENTRY IdtEntry;
+
+    switch (Opcode)
+    {
+        case 0xCC:
+        {
+            /* This is the INT3 instruction */
+            IntNum = 3;
+            break;
+        }
+
+        case 0xCD:
+        {
+            /* Fetch the interrupt number */
+            if (!Fast486FetchByte(State, &IntNum))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            break;
+        }
+
+        case 0xCE:
+        {
+            /* Don't do anything if OF is cleared */
+            if (!State->Flags.Of) return TRUE;
+
+            /* Exception #OF */
+            IntNum = FAST486_EXCEPTION_OF;
+
+            break;
+        }
+
+        default:
+        {
+            /* Should not happen */
+            ASSERT(FALSE);
+        }
+    }
+
+    /* Get the interrupt vector */
+    if (!Fast486GetIntVector(State, IntNum, &IdtEntry))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Perform the interrupt */
+    if (!Fast486InterruptInternal(State,
+                                  IdtEntry.Selector,
+                                  MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
+                                  IdtEntry.Type))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
+{
+    FAST486_SEG_REGS i;
+    ULONG InstPtr, CodeSel, StackPtr, StackSel;
+    FAST486_FLAGS_REG NewFlags;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xCF);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_OPSIZE(Size);
+
+    /* Pop EIP */
+    if (!Fast486StackPop(State, &InstPtr))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Pop CS */
+    if (!Fast486StackPop(State, &CodeSel))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Pop EFLAGS */
+    if (!Fast486StackPop(State, &NewFlags.Long))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+    {
+        INT Cpl = Fast486GetCurrentPrivLevel(State);
+
+        if (State->Flags.Vm)
+        {
+            /* Return from VM86 mode */
+
+            /* Check the IOPL */
+            if (State->Flags.Iopl == 3)
+            {
+                /* Set new EIP */
+                State->InstPtr.Long = LOWORD(InstPtr);
+
+                /* Load new CS */
+                if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+
+                /* Set the new flags */
+                if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
+                else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
+                State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
+                State->Flags.Iopl = 3;
+            }
+            else
+            {
+                /* Call the VM86 monitor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
+                return FALSE;
+            }
+
+            return TRUE;
+        }
+
+        if (State->Flags.Nt)
+        {
+            /* Nested task return */
+
+            UNIMPLEMENTED;
+            return FALSE;
+        }
+
+        if (NewFlags.Vm)
+        {
+            /* Return to VM86 mode */
+            ULONG Es, Ds, Fs, Gs;
+
+            /* Pop ESP, SS, ES, FS, GS */
+            if (!Fast486StackPop(State, &StackPtr)) return FALSE;
+            if (!Fast486StackPop(State, &StackSel)) return FALSE;
+            if (!Fast486StackPop(State, &Es)) return FALSE;
+            if (!Fast486StackPop(State, &Ds)) return FALSE;
+            if (!Fast486StackPop(State, &Fs)) return FALSE;
+            if (!Fast486StackPop(State, &Gs)) return FALSE;
+
+            /* Set the new IP */
+            State->InstPtr.Long = LOWORD(InstPtr);
+
+            /* Set the new flags */
+            if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
+            else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
+            State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
+
+            /* Load the new segments */
+            if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_ES, Es)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_DS, Ds)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_FS, Fs)) return FALSE;
+            if (!Fast486LoadSegment(State, FAST486_REG_GS, Gs)) return FALSE;
+
+            return TRUE;
+        }
+
+        /* Load the new CS */
+        if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set EIP */
+        if (Size) State->InstPtr.Long = InstPtr;
+        else State->InstPtr.LowWord = LOWORD(InstPtr);
+
+        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
+        {
+            /* Pop ESP */
+            if (!Fast486StackPop(State, &StackPtr))
+            {
+                /* Exception */
+                return FALSE;
+            }
+
+            /* Pop SS */
+            if (!Fast486StackPop(State, &StackSel))
+            {
+                /* Exception */
+                return FALSE;
+            }
+
+            /* Load new SS */
+            if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
+            {
+                /* Exception */
+                return FALSE;
+            }
+
+            /* Set ESP */
+            if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
+            else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr);
+        }
+
+        /* Set the new flags */
+        if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
+        else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
+        State->Flags.AlwaysSet = TRUE;
+
+        /* Set additional flags */
+        if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
+        if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
+
+        if (GET_SEGMENT_RPL(CodeSel) > Cpl)
+        {
+            /* Update the CPL */
+            Cpl = Fast486GetCurrentPrivLevel(State);
+
+            /* Check segment security */
+            for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
+            {
+                /* Don't check CS or SS */
+                if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
+
+                if ((Cpl > State->SegmentRegs[i].Dpl)
+                    && (!State->SegmentRegs[i].Executable
+                    || !State->SegmentRegs[i].DirConf))
+                {
+                    /* Load the NULL descriptor in the segment */
+                    if (!Fast486LoadSegment(State, i, 0)) return FALSE;
+                }
+            }
+        }
+    }
+    else
+    {
+        if (Size && (InstPtr & 0xFFFF0000))
+        {
+            /* Invalid */
+            Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
+            return FALSE;
+        }
+
+        /* Set new EIP */
+        State->InstPtr.Long = InstPtr;
+
+        /* Load new CS */
+        if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set the new flags */
+        if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
+        else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
+        State->Flags.AlwaysSet = TRUE;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAam)
+{
+    UCHAR Base;
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    NO_LOCK_PREFIX();
+
+    /* Fetch the base */
+    if (!Fast486FetchByte(State, &Base))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check if the base is zero */
+    if (Base == 0)
+    {
+        /* Divide error */
+        Fast486Exception(State, FAST486_EXCEPTION_DE);
+        return FALSE;
+    }
+
+    /* Adjust */
+    State->GeneralRegs[FAST486_REG_EAX].HighByte = Value / Base;
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Value %= Base;
+
+    /* Update flags */
+    State->Flags.Af = FALSE;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeAad)
+{
+    UCHAR Base;
+    UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    NO_LOCK_PREFIX();
+
+    /* Fetch the base */
+    if (!Fast486FetchByte(State, &Base))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Adjust */
+    Value += State->GeneralRegs[FAST486_REG_EAX].HighByte * Base;
+    State->GeneralRegs[FAST486_REG_EAX].LowWord = Value;
+
+    /* Update flags */
+    State->Flags.Af = FALSE;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeXlat)
+{
+    UCHAR Value;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Read a byte from DS:[(E)BX + AL] */
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_DS,
+                           (AddressSize ? State->GeneralRegs[FAST486_REG_EBX].Long
+                                        : State->GeneralRegs[FAST486_REG_EBX].LowWord)
+                           + State->GeneralRegs[FAST486_REG_EAX].LowByte,
+                           FALSE,
+                           &Value,
+                           sizeof(UCHAR)))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Set AL to the result */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = Value;
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLoop)
+{
+    BOOLEAN Condition;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    CHAR Offset = 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(Size);
+
+    if (Size) Condition = ((--State->GeneralRegs[FAST486_REG_ECX].Long) != 0);
+    else Condition = ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) != 0);
+
+    if (Opcode == 0xE0)
+    {
+        /* Additional rule for LOOPNZ */
+        if (State->Flags.Zf) Condition = FALSE;
+    }
+
+    if (Opcode == 0xE1)
+    {
+        /* Additional rule for LOOPZ */
+        if (!State->Flags.Zf) Condition = FALSE;
+    }
+
+    /* Fetch the offset */
+    if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+    {
+        /* An exception occurred */
+        return FALSE;
+    }
+
+    if (Condition)
+    {
+        /* Move the instruction pointer */
+        if (Size) State->InstPtr.Long += Offset;
+        else State->InstPtr.LowWord += Offset;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz)
+{
+    BOOLEAN Condition;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    CHAR Offset = 0;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xE3);
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(Size);
+
+    if (Size) Condition = (State->GeneralRegs[FAST486_REG_ECX].Long == 0);
+    else Condition = (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0);
+
+    /* Fetch the offset */
+    if (!Fast486FetchByte(State, (PUCHAR)&Offset))
+    {
+        /* An exception occurred */
+        return FALSE;
+    }
+
+    if (Condition)
+    {
+        /* Move the instruction pointer */
+        if (Size) State->InstPtr.Long += Offset;
+        else State->InstPtr.LowWord += Offset;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCall)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xE8);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Size)
+    {
+        LONG Offset = 0;
+
+        /* Fetch the offset */
+        if (!Fast486FetchDword(State, (PULONG)&Offset))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Push the current value of the instruction pointer */
+        if (!Fast486StackPush(State, State->InstPtr.Long))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Move the instruction pointer */
+        State->InstPtr.Long += Offset;
+    }
+    else
+    {
+        SHORT Offset = 0;
+
+        /* Fetch the offset */
+        if (!Fast486FetchWord(State, (PUSHORT)&Offset))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Push the current value of the instruction pointer */
+        if (!Fast486StackPush(State, State->InstPtr.Long))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Move the instruction pointer */
+        State->InstPtr.LowWord += Offset;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeJmp)
+{
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xE9);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    if (Size)
+    {
+        LONG Offset = 0;
+
+        /* Fetch the offset */
+        if (!Fast486FetchDword(State, (PULONG)&Offset))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Move the instruction pointer */
+        State->InstPtr.Long += Offset;
+    }
+    else
+    {
+        SHORT Offset = 0;
+
+        /* Fetch the offset */
+        if (!Fast486FetchWord(State, (PUSHORT)&Offset))
+        {
+            /* An exception occurred */
+            return FALSE;
+        }
+
+        /* Move the instruction pointer */
+        State->InstPtr.Long += Offset;
+
+        /* Clear the top half of EIP */
+        State->InstPtr.Long &= 0xFFFF;
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs)
+{
+    USHORT Segment = 0;
+    ULONG Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xEA);
+
+    TOGGLE_OPSIZE(Size);
+    NO_LOCK_PREFIX();
+
+    /* Fetch the offset */
+    if (Size)
+    {
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!Fast486FetchWord(State, (PUSHORT)&Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    /* Fetch the segment */
+    if (!Fast486FetchWord(State, &Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load the new CS */
+    if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Load new EIP */
+    State->InstPtr.Long = Offset;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    ULONG Offset;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA0);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (AddressSize)
+    {
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT WordOffset;
+
+        if (!Fast486FetchWord(State, &WordOffset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        Offset = (ULONG)WordOffset;
+    }
+
+    /* Read from memory */
+    return Fast486ReadMemory(State,
+                             (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                             State->SegmentOverride : FAST486_REG_DS,
+                             Offset,
+                             FALSE,
+                             &State->GeneralRegs[FAST486_REG_EAX].LowByte,
+                             sizeof(UCHAR));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset)
+{
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA1);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (AddressSize)
+    {
+        ULONG Offset;
+
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Read from memory */
+        if (OperandSize)
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                     sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                     sizeof(USHORT));
+        }
+    }
+    else
+    {
+        USHORT Offset;
+
+        if (!Fast486FetchWord(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Read from memory */
+        if (OperandSize)
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                     sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                     sizeof(USHORT));
+        }
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetAl)
+{
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    ULONG Offset;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA2);
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (AddressSize)
+    {
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        USHORT WordOffset;
+
+        if (!Fast486FetchWord(State, &WordOffset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        Offset = (ULONG)WordOffset;
+    }
+
+    /* Write to memory */
+    return Fast486WriteMemory(State,
+                             (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                             State->SegmentOverride : FAST486_REG_DS,
+                             Offset,
+                             &State->GeneralRegs[FAST486_REG_EAX].LowByte,
+                             sizeof(UCHAR));
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetEax)
+{
+    BOOLEAN OperandSize, AddressSize;
+    
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xA3);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (AddressSize)
+    {
+        ULONG Offset;
+
+        if (!Fast486FetchDword(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write to memory */
+        if (OperandSize)
+        {
+            return Fast486WriteMemory(State,
+                                      (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                      State->SegmentOverride : FAST486_REG_DS,
+                                      Offset,
+                                      &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                      sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486WriteMemory(State,
+                                      (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                      State->SegmentOverride : FAST486_REG_DS,
+                                      Offset,
+                                      &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                      sizeof(USHORT));
+        }
+    }
+    else
+    {
+        USHORT Offset;
+
+        if (!Fast486FetchWord(State, &Offset))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write to memory */
+        if (OperandSize)
+        {
+            return Fast486WriteMemory(State,
+                                      (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                      State->SegmentOverride : FAST486_REG_DS,
+                                      Offset,
+                                      &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                      sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486WriteMemory(State,
+                                      (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                      State->SegmentOverride : FAST486_REG_DS,
+                                      Offset,
+                                      &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                      sizeof(USHORT));
+        }
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeSalc)
+{
+    /* Make sure this is the right instruction */
+    ASSERT(Opcode == 0xD6);
+
+    NO_LOCK_PREFIX();
+
+    /* Set all the bits of AL to CF */
+    State->GeneralRegs[FAST486_REG_EAX].LowByte = State->Flags.Cf ? 0xFF : 0x00;
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
+{
+    ULONG Data, DataSize;
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xA4);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead of DS */
+        Segment = State->SegmentOverride;
+    }
+
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
+            || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
+        {
+            /* Do nothing */
+            return TRUE;
+        }
+    }
+
+    /* Calculate the size */
+    if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    /* Read from the source operand */
+    if (!Fast486ReadMemory(State,
+                           Segment,
+                           AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
+                                       : State->GeneralRegs[FAST486_REG_ESI].LowWord,
+                           FALSE,
+                           &Data,
+                           DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Write to the destination operand */
+    if (!Fast486WriteMemory(State,
+                            FAST486_REG_ES,
+                            AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                        : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                            &Data,
+                            DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Increment/decrement ESI and EDI */
+    if (AddressSize)
+    {
+        if (!State->Flags.Df)
+        {
+            State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+        }
+    }
+    else
+    {
+        if (!State->Flags.Df)
+        {
+            State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+        }
+    }
+
+    // FIXME: This method is slow!
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        if (AddressSize)
+        {
+            if (--State->GeneralRegs[FAST486_REG_ECX].Long)
+            {
+                /* Repeat the instruction */
+                State->InstPtr = State->SavedInstPtr;
+            }
+        }
+        else
+        {
+            if (--State->GeneralRegs[FAST486_REG_ECX].LowWord)
+            {
+                /* Repeat the instruction */
+                State->InstPtr = State->SavedInstPtr;
+            }
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmps)
+{
+    ULONG FirstValue = 0, SecondValue = 0, Result;
+    ULONG DataSize, DataMask, SignFlag;
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xA6);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead of DS */
+        Segment = State->SegmentOverride;
+    }
+
+    if ((State->PrefixFlags & FAST486_PREFIX_REP)
+        || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
+    {
+        if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
+            || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
+        {
+            /* Do nothing */
+            return TRUE;
+        }
+    }
+
+    /* Calculate the size */
+    if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    /* Calculate the mask and sign flag */
+    SignFlag = 1 << ((DataSize * 8) - 1);
+    DataMask = SignFlag | (SignFlag - 1);
+
+    /* Read from the first source operand */
+    if (!Fast486ReadMemory(State,
+                           Segment,
+                           AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
+                                       : State->GeneralRegs[FAST486_REG_ESI].LowWord,
+                           FALSE,
+                           &FirstValue,
+                           DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read from the second source operand */
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_ES,
+                           AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                       : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                           FALSE,
+                           &SecondValue,
+                           DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    FirstValue &= DataMask;
+    SecondValue &= DataMask;
+    Result = (FirstValue - SecondValue) & DataMask;
+
+    /* Update the flags */
+    State->Flags.Cf = (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
+                      && ((FirstValue & SignFlag) != (Result & SignFlag));
+    State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SignFlag) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Increment/decrement ESI and EDI */
+    if (AddressSize)
+    {
+        if (!State->Flags.Df)
+        {
+            State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+        }
+    }
+    else
+    {
+        if (!State->Flags.Df)
+        {
+            State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
+            State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+        }
+    }
+
+    // FIXME: This method is slow!
+    if ((State->PrefixFlags & FAST486_PREFIX_REP)
+        || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
+    {
+        BOOLEAN Repeat = TRUE;
+
+        if (AddressSize)
+        {
+            if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
+            {
+                /* ECX is 0 */
+                Repeat = FALSE;
+            }
+        }
+        else
+        {
+            if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0)
+            {
+                /* CX is 0 */
+                Repeat = FALSE;
+            }
+        }
+
+        if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf)
+            || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf))
+        {
+            /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+            Repeat = FALSE;
+        }
+
+        if (Repeat)
+        {
+            /* Repeat the instruction */
+            State->InstPtr = State->SavedInstPtr;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeStos)
+{
+    ULONG DataSize;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xAA);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Calculate the size */
+    if (Opcode == 0xAA) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        UCHAR Block[STRING_BLOCK_SIZE];
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+                                  : State->GeneralRegs[FAST486_REG_ECX].LowWord;
+
+        /* Fill the memory block with the data */
+        if (DataSize == sizeof(UCHAR))
+        {
+            RtlFillMemory(Block, sizeof(Block), State->GeneralRegs[FAST486_REG_EAX].LowByte);
+        }
+        else
+        {
+            ULONG i;
+
+            for (i = 0; i < STRING_BLOCK_SIZE / DataSize; i++)
+            {
+                if (DataSize == sizeof(USHORT))
+                {
+                    ((PUSHORT)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].LowWord;
+                }
+                else
+                {
+                    ((PULONG)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].Long;
+                }
+            }
+        }
+
+        /* Transfer until finished */
+        while (Count)
+        {
+            ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = State->Flags.Df
+                                 ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
+                                 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
+            if (State->Flags.Df)
+            {
+                /* Set EDI to the starting location */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= (Processed - 1) * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord -= (Processed - 1) * DataSize;
+            }
+
+            /* Write to memory */
+            if (!Fast486WriteMemory(State,
+                                    FAST486_REG_ES,
+                                    AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                                : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                                    Block,
+                                    Processed * DataSize))
+            {
+                /* Set ECX */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
+
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (!State->Flags.Df)
+            {
+                /* Increase EDI by the number of bytes transfered */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
+            }
+            else
+            {
+                /* Reduce EDI */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+            }
+
+            /* Reduce the total count by the number processed in this run */
+            Count -= Processed;
+        }
+
+        /* Clear ECX */
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
+    }
+    else
+    {
+        /* Write to the destination operand */
+        if (!Fast486WriteMemory(State,
+                                FAST486_REG_ES,
+                                AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                            : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                                &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                DataSize))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Increment/decrement EDI */
+        if (AddressSize)
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
+            else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+        }
+        else
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
+            else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeLods)
+{
+    ULONG DataSize;
+    BOOLEAN OperandSize, AddressSize;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xAC);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead of DS */
+        Segment = State->SegmentOverride;
+    }
+
+    /* Calculate the size */
+    if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+                                  : State->GeneralRegs[FAST486_REG_ECX].LowWord;
+
+        /* If the count is 0, do nothing */
+        if (Count == 0) return TRUE;
+
+        /* Only the last entry will be loaded */
+        if (!State->Flags.Df)
+        {
+            if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long += (Count - 1) * DataSize;
+            else State->GeneralRegs[FAST486_REG_ESI].LowWord += (Count - 1) * DataSize;
+        }
+        else
+        {
+            if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long -= (Count - 1) * DataSize;
+            else State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Count - 1) * DataSize;
+        }
+
+        /* Clear ECX */
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
+    }
+
+    /* Read from the source operand */
+    if (!Fast486ReadMemory(State,
+                           Segment,
+                           AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
+                                       : State->GeneralRegs[FAST486_REG_ESI].LowWord,
+                           FALSE,
+                           &State->GeneralRegs[FAST486_REG_EAX].Long,
+                           DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Increment/decrement ESI */
+    if (AddressSize)
+    {
+        if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
+        else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
+    }
+    else
+    {
+        if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
+        else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeScas)
+{
+    ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
+    ULONG SecondValue = 0;
+    ULONG Result;
+    ULONG DataSize, DataMask, SignFlag;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0xAE);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if ((State->PrefixFlags & FAST486_PREFIX_REP)
+        || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
+    {
+        if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
+            || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
+        {
+            /* Do nothing */
+            return TRUE;
+        }
+    }
+
+    /* Calculate the size */
+    if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    /* Calculate the mask and sign flag */
+    SignFlag = 1 << ((DataSize * 8) - 1);
+    DataMask = SignFlag | (SignFlag - 1);
+
+    /* Read from the source operand */
+    if (!Fast486ReadMemory(State,
+                           FAST486_REG_ES,
+                           AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                       : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                           FALSE,
+                           &SecondValue,
+                           DataSize))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    FirstValue &= DataMask;
+    SecondValue &= DataMask;
+    Result = (FirstValue - SecondValue) & DataMask;
+
+    /* Update the flags */
+    State->Flags.Cf = (FirstValue < SecondValue);
+    State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
+                      && ((FirstValue & SignFlag) != (Result & SignFlag));
+    State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SignFlag) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Result);
+
+    /* Increment/decrement EDI */
+    if (AddressSize)
+    {
+        if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
+        else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+    }
+    else
+    {
+        if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
+        else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+    }
+
+    // FIXME: This method is slow!
+    if ((State->PrefixFlags & FAST486_PREFIX_REP)
+        || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
+    {
+        BOOLEAN Repeat = TRUE;
+
+        if (AddressSize)
+        {
+            if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
+            {
+                /* ECX is 0 */
+                Repeat = FALSE;
+            }
+        }
+        else
+        {
+            if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0)
+            {
+                /* CX is 0 */
+                Repeat = FALSE;
+            }
+        }
+
+        if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf)
+            || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf))
+        {
+            /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+            Repeat = FALSE;
+        }
+
+        if (Repeat)
+        {
+            /* Repeat the instruction */
+            State->InstPtr = State->SavedInstPtr;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
+{
+    ULONG DataSize;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0x6C);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Calculate the size */
+    if (Opcode == 0x6C) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        UCHAR Block[STRING_BLOCK_SIZE];
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+                                  : State->GeneralRegs[FAST486_REG_ECX].LowWord;
+
+        /* Clear the memory block */
+        RtlZeroMemory(Block, sizeof(Block));
+
+        /* Transfer until finished */
+        while (Count)
+        {
+            ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = State->Flags.Df
+                                 ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
+                                 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
+            /* Read from the I/O port */
+            State->IoReadCallback(State,
+                                  State->GeneralRegs[FAST486_REG_EDX].LowWord,
+                                  Block,
+                                  Processed,
+                                  DataSize);
+
+            if (State->Flags.Df)
+            {
+                ULONG i, j;
+
+                /* Reduce EDI by the number of bytes to transfer */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= Processed * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord -= Processed * DataSize;
+
+                /* Reverse the block data */
+                for (i = 0; i < Processed / 2; i++)
+                {
+                    /* Swap the values */
+                    for (j = 0; j < DataSize; j++)
+                    {
+                        UCHAR Temp = Block[i * DataSize + j];
+                        Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
+                        Block[(Processed - i - 1) * DataSize + j] = Temp;
+                    }
+                }
+            }
+
+            /* Write to memory */
+            if (!Fast486WriteMemory(State,
+                                    FAST486_REG_ES,
+                                    AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                                : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                                    Block,
+                                    Processed * DataSize))
+            {
+                /* Set ECX */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
+
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (!State->Flags.Df)
+            {
+                /* Increase EDI by the number of bytes transfered */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
+            }
+
+            /* Reduce the total count by the number processed in this run */
+            Count -= Processed;
+        }
+
+        /* Clear ECX */
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
+    }
+    else
+    {
+        ULONG Data = 0;
+
+        /* Read from the I/O port */
+        State->IoReadCallback(State,
+                              State->GeneralRegs[FAST486_REG_EDX].LowWord,
+                              &Data,
+                              1,
+                              DataSize);
+
+        /* Write to the destination operand */
+        if (!Fast486WriteMemory(State,
+                                FAST486_REG_ES,
+                                AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                            : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                                &Data,
+                                DataSize))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Increment/decrement EDI */
+        if (AddressSize)
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
+            else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
+        }
+        else
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
+            else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
+{
+    ULONG DataSize;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    /* Make sure this is the right instruction */
+    ASSERT((Opcode & 0xFE) == 0x6E);
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Calculate the size */
+    if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
+    else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+
+    if (State->PrefixFlags & FAST486_PREFIX_REP)
+    {
+        UCHAR Block[STRING_BLOCK_SIZE];
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+                                  : State->GeneralRegs[FAST486_REG_ECX].LowWord;
+
+        /* Clear the memory block */
+        RtlZeroMemory(Block, sizeof(Block));
+
+        /* Transfer until finished */
+        while (Count)
+        {
+            ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+            /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+            if (!AddressSize)
+            {
+                ULONG MaxBytes = State->Flags.Df
+                                 ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
+                                 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
+
+                Processed = min(Processed, MaxBytes / DataSize);
+                if (Processed == 0) Processed = 1;
+            }
+
+            /* Read from memory */
+            if (!Fast486ReadMemory(State,
+                                   FAST486_REG_ES,
+                                   AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
+                                               : State->GeneralRegs[FAST486_REG_EDI].LowWord,
+                                   FALSE,
+                                   Block,
+                                   Processed * DataSize))
+            {
+                /* Set ECX */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
+
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (State->Flags.Df)
+            {
+                ULONG i, j;
+
+                /* Reduce EDI by the number of bytes to transfer */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= Processed * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord -= Processed * DataSize;
+
+                /* Reverse the block data */
+                for (i = 0; i < Processed / 2; i++)
+                {
+                    /* Swap the values */
+                    for (j = 0; j < DataSize; j++)
+                    {
+                        UCHAR Temp = Block[i * DataSize + j];
+                        Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
+                        Block[(Processed - i - 1) * DataSize + j] = Temp;
+                    }
+                }
+            }
+
+            /* Write to the I/O port */
+            State->IoWriteCallback(State,
+                                   State->GeneralRegs[FAST486_REG_EDX].LowWord,
+                                   Block,
+                                   Processed,
+                                   DataSize);
+
+            if (!State->Flags.Df)
+            {
+                /* Increase EDI by the number of bytes transfered */
+                if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
+                else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
+            }
+
+            /* Reduce the total count by the number processed in this run */
+            Count -= Processed;
+        }
+
+        /* Clear ECX */
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
+    }
+    else
+    {
+        ULONG Data = 0;
+
+        /* Read from the source operand */
+        if (!Fast486ReadMemory(State,
+                               FAST486_REG_DS,
+                               AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
+                                           : State->GeneralRegs[FAST486_REG_ESI].LowWord,
+                               FALSE,
+                               &Data,
+                               DataSize))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Write to the I/O port */
+        State->IoWriteCallback(State,
+                               State->GeneralRegs[FAST486_REG_EDX].LowWord,
+                               &Data,
+                               1,
+                               DataSize);
+
+        /* Increment/decrement ESI */
+        if (AddressSize)
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
+            else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
+        }
+        else
+        {
+            if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
+            else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
diff --git a/lib/fast486/opcodes.h b/lib/fast486/opcodes.h
new file mode 100644 (file)
index 0000000..3d29e47
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opcodes.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _OPCODES_H_
+#define _OPCODES_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+#define FAST486_NUM_OPCODE_HANDLERS 256
+#define FAST486_OPCODE_WRITE_REG (1 << 1)
+#define FAST486_OPCODE_HANDLER(x)   \
+    BOOLEAN FASTCALL x(PFAST486_STATE State, UCHAR Opcode)
+
+typedef BOOLEAN (FASTCALL *FAST486_OPCODE_HANDLER_PROC)(PFAST486_STATE, UCHAR);
+
+extern
+FAST486_OPCODE_HANDLER_PROC
+Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS];
+
+FAST486_OPCODE_HANDLER(Fast486OpcodePrefix);
+FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement);
+FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushReg);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopReg);
+FAST486_OPCODE_HANDLER(Fast486OpcodeNop);
+FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp);
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry);
+FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry);
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt);
+FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir);
+FAST486_OPCODE_HANDLER(Fast486OpcodeHalt);
+FAST486_OPCODE_HANDLER(Fast486OpcodeInByte);
+FAST486_OPCODE_HANDLER(Fast486OpcodeIn);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOut);
+FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushEs);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopEs);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushCs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushSs);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopSs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushDs);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopDs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeDaa);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeDas);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAaa);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAas);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushAll);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopAll);
+FAST486_OPCODE_HANDLER(Fast486OpcodeBound);
+FAST486_OPCODE_HANDLER(Fast486OpcodeArpl);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovStoreSeg);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLea);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCwde);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCdq);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeWait);
+FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags);
+FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSahf);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLahf);
+FAST486_OPCODE_HANDLER(Fast486OpcodeRet);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes);
+FAST486_OPCODE_HANDLER(Fast486OpcodeEnter);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLeave);
+FAST486_OPCODE_HANDLER(Fast486OpcodeRetFarImm);
+FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar);
+FAST486_OPCODE_HANDLER(Fast486OpcodeInt);
+FAST486_OPCODE_HANDLER(Fast486OpcodeIret);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAam);
+FAST486_OPCODE_HANDLER(Fast486OpcodeAad);
+FAST486_OPCODE_HANDLER(Fast486OpcodeXlat);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLoop);
+FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCall);
+FAST486_OPCODE_HANDLER(Fast486OpcodeJmp);
+FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetAl);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetEax);
+FAST486_OPCODE_HANDLER(Fast486OpcodeSalc);
+FAST486_OPCODE_HANDLER(Fast486OpcodeMovs);
+FAST486_OPCODE_HANDLER(Fast486OpcodeCmps);
+FAST486_OPCODE_HANDLER(Fast486OpcodeStos);
+FAST486_OPCODE_HANDLER(Fast486OpcodeLods);
+FAST486_OPCODE_HANDLER(Fast486OpcodeScas);
+FAST486_OPCODE_HANDLER(Fast486OpcodeIns);
+FAST486_OPCODE_HANDLER(Fast486OpcodeOuts);
+
+#endif // _OPCODES_H_
diff --git a/lib/fast486/opgroups.c b/lib/fast486/opgroups.c
new file mode 100644 (file)
index 0000000..264fa66
--- /dev/null
@@ -0,0 +1,2370 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opgroups.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#include "opcodes.h"
+#include "common.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+inline
+static
+ULONG
+Fast486ArithmeticOperation(PFAST486_STATE State,
+                           INT Operation,
+                           ULONG FirstValue,
+                           ULONG SecondValue,
+                           UCHAR Bits)
+{
+    ULONG Result;
+    ULONG SignFlag = 1 << (Bits - 1);
+    ULONG MaxValue = (SignFlag - 1) | SignFlag;
+
+    /* Make sure the values don't exceed the maximum for their size */
+    FirstValue &= MaxValue;
+    SecondValue &= MaxValue;
+
+    /* Check which operation is this */
+    switch (Operation)
+    {
+        /* ADD */
+        case 0:
+        {
+            Result = (FirstValue + SecondValue) & MaxValue;
+
+            /* Update CF, OF and AF */
+            State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
+            State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
+                              && ((FirstValue & SignFlag) != (Result & SignFlag));
+            State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+
+            break;
+        }
+
+        /* OR */
+        case 1:
+        {
+            Result = FirstValue | SecondValue;
+            break;
+        }
+
+        /* ADC */
+        case 2:
+        {
+            INT Carry = State->Flags.Cf ? 1 : 0;
+
+            Result = (FirstValue + SecondValue + Carry) & MaxValue;
+
+            /* Update CF, OF and AF */
+            State->Flags.Cf = ((SecondValue == MaxValue) && (Carry == 1))
+                              || ((Result < FirstValue) && (Result < (SecondValue + Carry)));
+            State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
+                              && ((FirstValue & SignFlag) != (Result & SignFlag));
+            State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+
+            break;
+        }
+
+        /* SBB */
+        case 3:
+        {
+            INT Carry = State->Flags.Cf ? 1 : 0;
+
+            Result = (FirstValue - SecondValue - Carry) & MaxValue;
+
+            /* Update CF, OF and AF */
+            State->Flags.Cf = Carry
+                              ? (FirstValue <= SecondValue)
+                              : (FirstValue < SecondValue);
+            State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
+                              && ((FirstValue & SignFlag) != (Result & SignFlag));
+            State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
+
+            break;
+        }
+
+        /* AND */
+        case 4:
+        {
+            Result = FirstValue & SecondValue;
+            break;
+        }
+
+        /* SUB or CMP */
+        case 5:
+        case 7:
+        {
+            Result = (FirstValue - SecondValue) & MaxValue;
+
+            /* Update CF, OF and AF */
+            State->Flags.Cf = (FirstValue < SecondValue);
+            State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
+                              && ((FirstValue & SignFlag) != (Result & SignFlag));
+            State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
+
+            break;
+        }
+
+        /* XOR */
+        case 6:
+        {
+            Result = FirstValue ^ SecondValue;
+            break;
+        }
+
+        default:
+        {
+            /* Shouldn't happen */
+            ASSERT(FALSE);
+        }
+    }
+
+    /* Update ZF, SF and PF */
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SignFlag) != 0);
+    State->Flags.Pf = Fast486CalculateParity(LOBYTE(Result));
+
+    /* Return the result */
+    return Result;
+}
+
+static
+inline
+ULONG
+Fast486RotateOperation(PFAST486_STATE State,
+                       INT Operation,
+                       ULONG Value,
+                       UCHAR Bits,
+                       UCHAR Count)
+{
+    ULONG HighestBit = 1 << (Bits - 1);
+    ULONG MaxValue = HighestBit | (HighestBit - 1);
+    ULONG Result;
+
+    /* Normalize the count */
+    Count &= 0x1F;
+
+    if ((Operation == 2) || (Operation == 3)) Count %= Bits + 1;
+
+    /* If the count is zero, do nothing */
+    if (Count == 0) return Value;
+
+    /* Check which operation is this */
+    switch (Operation)
+    {
+        /* ROL */
+        case 0:
+        {
+            Count %= Bits;
+            Result = (Value << Count) | (Value >> (Bits - Count));
+
+            /* Update CF and OF */
+            State->Flags.Cf = Result & 1;
+            if (Count == 1) State->Flags.Of = State->Flags.Cf
+                                              ^ ((Result & HighestBit) != 0);
+
+            break;
+        }
+
+        /* ROR */
+        case 1:
+        {
+            Count %= Bits;
+            Result = (Value >> Count) | (Value << (Bits - Count));
+
+            /* Update CF and OF */
+            State->Flags.Cf = ((Result & HighestBit) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf
+                                              ^ ((Result & (HighestBit >> 1)) != 0);
+
+            break;
+        }
+
+        /* RCL */
+        case 2:
+        {
+            Result = (Value << Count) | (State->Flags.Cf << (Count - 1));
+            
+            /* Complete the calculation, but make sure we don't shift by too much */
+            if ((Bits - Count) < 31) Result |= Value >> (Bits - Count + 1);
+
+            /* Update CF and OF */
+            State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Result & HighestBit) != 0);
+
+            break;
+        }
+
+        /* RCR */
+        case 3:
+        {
+            /* Update OF */
+            if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Value & HighestBit) != 0);
+
+            Result = (Value >> Count) | (State->Flags.Cf << (Bits - Count));
+
+            /* Complete the calculation, but make sure we don't shift by too much */
+            if ((Bits - Count) < 31) Result |= Value << (Bits - Count + 1);
+
+            /* Update CF */
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
+
+            break;
+        }
+
+        /* SHL/SAL */
+        case 4:
+        case 6:
+        {
+            Result = Value << Count;
+
+            /* Update CF and OF */
+            State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf
+                                              ^ ((Result & HighestBit) != 0);
+
+            break;
+        }
+
+        /* SHR */
+        case 5:
+        {
+            Result = Value >> Count;
+
+            /* Update CF and OF */
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
+            if (Count == 1) State->Flags.Of = ((Value & HighestBit) != 0);
+
+            break;
+        }
+
+        /* SAR */
+        case 7:
+        {
+            Result = Value >> Count;
+
+            /* Fill the top Count bits with the sign bit */
+            if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count);
+
+            /* Update CF and OF */
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
+            if (Count == 1) State->Flags.Of = FALSE;
+
+            break;
+        }
+    }
+
+    if (Operation >= 4)
+    {
+        /* Update ZF, SF and PF */
+        State->Flags.Zf = ((Result & MaxValue) == 0);
+        State->Flags.Sf = ((Result & HighestBit) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
+
+    /* Return the result */
+    return Result;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
+{
+    UCHAR Immediate, Value;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Fetch the immediate operand */
+    if (!Fast486FetchByte(State, &Immediate))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 8);
+
+    /* Unless this is CMP, write back the result */
+    if (ModRegRm.Register != 7)
+    {
+        return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Immediate, Value;
+
+        /* Fetch the immediate operand */
+        if (!Fast486FetchDword(State, &Immediate))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32);
+
+        /* Unless this is CMP, write back the result */
+        if (ModRegRm.Register != 7)
+        {
+            return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
+        }
+    }
+    else
+    {
+        USHORT Immediate, Value;
+
+        /* Fetch the immediate operand */
+        if (!Fast486FetchWord(State, &Immediate))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16);
+
+        /* Unless this is CMP, write back the result */
+        if (ModRegRm.Register != 7)
+        {
+            return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83)
+{
+    CHAR ImmByte;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Fetch the immediate operand */
+    if (!Fast486FetchByte(State, (PUCHAR)&ImmByte))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Immediate = (ULONG)((LONG)ImmByte); // Sign extend
+        ULONG Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32);
+
+        /* Unless this is CMP, write back the result */
+        if (ModRegRm.Register != 7)
+        {
+            return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
+        }
+    }
+    else
+    {
+        USHORT Immediate = (USHORT)((SHORT)ImmByte); // Sign extend
+        USHORT Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16);
+
+        /* Unless this is CMP, write back the result */
+        if (ModRegRm.Register != 7)
+        {
+            return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F)
+{
+    ULONG Value;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Pop a value from the stack - this must be done first */
+    if (!Fast486StackPop(State, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred - restore SP */
+        if (OperandSize) State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG);
+        else State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT);
+
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              FALSE,
+                                              Value);
+    }
+    else
+    {
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             FALSE,
+                                             LOWORD(Value));
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0)
+{
+    UCHAR Value, Count;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Fetch the count */
+    if (!Fast486FetchByte(State, &Count))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Value = LOBYTE(Fast486RotateOperation(State,
+                                          ModRegRm.Register,
+                                          Value,
+                                          8,
+                                          Count));
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         FALSE,
+                                         Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1)
+{
+    UCHAR Count;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Fetch the count */
+    if (!Fast486FetchByte(State, &Count))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486RotateOperation(State,
+                                       ModRegRm.Register,
+                                       Value,
+                                       32,
+                                       Count);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = LOWORD(Fast486RotateOperation(State,
+                                              ModRegRm.Register,
+                                              Value,
+                                              16,
+                                              Count));
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6)
+{
+    UCHAR Immediate;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Get the immediate operand */
+    if (!Fast486FetchByte(State, &Immediate))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         FALSE,
+                                         Immediate);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register != 0)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Immediate;
+
+        /* Get the immediate operand */
+        if (!Fast486FetchDword(State, &Immediate))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              FALSE,
+                                              Immediate);
+    }
+    else
+    {
+        USHORT Immediate;
+
+        /* Get the immediate operand */
+        if (!Fast486FetchWord(State, &Immediate))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             FALSE,
+                                             Immediate);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0)
+{
+    UCHAR Value;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Value = LOBYTE(Fast486RotateOperation(State, ModRegRm.Register, Value, 8, 1));
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         FALSE,
+                                         Value);
+
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486RotateOperation(State, ModRegRm.Register, Value, 32, 1);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = LOWORD(Fast486RotateOperation(State, ModRegRm.Register, Value, 16, 1));
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2)
+{
+    UCHAR Value;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Calculate the result */
+    Value = LOBYTE(Fast486RotateOperation(State,
+                                          ModRegRm.Register,
+                                          Value,
+                                          8,
+                                          State->GeneralRegs[FAST486_REG_ECX].LowByte));
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         FALSE,
+                                         Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = Fast486RotateOperation(State,
+                                       ModRegRm.Register,
+                                       Value,
+                                       32,
+                                       State->GeneralRegs[FAST486_REG_ECX].LowByte);
+
+        /* Write back the result */
+        return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the operands */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Calculate the result */
+        Value = LOWORD(Fast486RotateOperation(State,
+                                              ModRegRm.Register,
+                                              Value,
+                                              16,
+                                              State->GeneralRegs[FAST486_REG_ECX].LowByte));
+
+        /* Write back the result */
+        return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
+{
+    UCHAR Value = 0;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    switch (ModRegRm.Register)
+    {
+        /* TEST */
+        case 0:
+        case 1:
+        {
+            UCHAR Immediate, Result;
+
+            /* Fetch the immediate byte */
+            if (!Fast486FetchByte(State, &Immediate))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Calculate the result */
+            Result = Value & Immediate;
+
+            /* Update the flags */
+            State->Flags.Cf = FALSE;
+            State->Flags.Of = FALSE;
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+            State->Flags.Pf = Fast486CalculateParity(Result);
+
+            break;
+        }
+
+        /* NOT */
+        case 2:
+        {
+            /* Write back the result */
+            return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, ~Value);
+        }
+
+        /* NEG */
+        case 3:
+        {
+            /* Calculate the result */
+            UCHAR Result = -Value;
+
+            /* Update the flags */
+            State->Flags.Cf = (Value != 0);
+            State->Flags.Of = (Value & SIGN_FLAG_BYTE) && (Result & SIGN_FLAG_BYTE);
+            State->Flags.Af = ((Value & 0x0F) != 0);
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
+            State->Flags.Pf = Fast486CalculateParity(Result);
+
+            /* Write back the result */
+            return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result);
+        }
+
+        /* MUL */
+        case 4:
+        {
+            USHORT Result = (USHORT)Value * (USHORT)State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+            /* Update the flags */
+            State->Flags.Cf = State->Flags.Of = (HIBYTE(Result) != 0);
+
+            /* Write back the result */
+            State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
+
+            break;
+        }
+
+        /* IMUL */
+        case 5:
+        {
+            SHORT Result = (SHORT)((CHAR)Value) * (SHORT)((CHAR)State->GeneralRegs[FAST486_REG_EAX].LowByte);
+
+            /* Update the flags */
+            State->Flags.Cf = State->Flags.Of = ((Result < -128) || (Result > 127));
+
+            /* Write back the result */
+            State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Result;
+
+            break;
+        }
+
+        /* DIV */
+        case 6:
+        {
+            UCHAR Quotient, Remainder;
+
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value;
+            Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value;
+
+            /* Write back the results */
+            State->GeneralRegs[FAST486_REG_EAX].LowByte = Quotient;
+            State->GeneralRegs[FAST486_REG_EAX].HighByte = Remainder;
+
+            break;
+        }
+
+        /* IDIV */
+        case 7:
+        {
+            CHAR Quotient, Remainder;
+
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value;
+            Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value;
+
+            /* Write back the results */
+            State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient;
+            State->GeneralRegs[FAST486_REG_EAX].HighByte = (UCHAR)Remainder;
+
+            break;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
+{
+    ULONG Value = 0, SignFlag;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Set the sign flag */
+    if (OperandSize) SignFlag = SIGN_FLAG_LONG;
+    else SignFlag = SIGN_FLAG_WORD;
+
+    /* Read the operand */
+    if (OperandSize)
+    {
+        /* 32-bit */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* 16-bit */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+    }
+
+    switch (ModRegRm.Register)
+    {
+        /* TEST */
+        case 0:
+        case 1:
+        {
+            ULONG Immediate = 0, Result = 0;
+
+            if (OperandSize)
+            {
+                /* Fetch the immediate dword */
+                if (!Fast486FetchDword(State, &Immediate))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+            else
+            {
+                /* Fetch the immediate word */
+                if (!Fast486FetchWord(State, (PUSHORT)&Immediate))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+
+            /* Calculate the result */
+            Result = Value & Immediate;
+
+            /* Update the flags */
+            State->Flags.Cf = FALSE;
+            State->Flags.Of = FALSE;
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SignFlag) != 0);
+            State->Flags.Pf = Fast486CalculateParity(Result);
+
+            break;
+        }
+
+        /* NOT */
+        case 2:
+        {
+            /* Write back the result */
+            if (OperandSize)
+            {
+                /* 32-bit */
+                return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, ~Value);
+            }
+            else
+            {
+                /* 16-bit */
+                return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(~Value));
+            }
+        }
+
+        /* NEG */
+        case 3:
+        {
+            /* Calculate the result */
+            ULONG Result = -Value;
+            if (!OperandSize) Result &= 0xFFFF;
+
+            /* Update the flags */
+            State->Flags.Cf = (Value != 0);
+            State->Flags.Of = (Value & SignFlag) && (Result & SignFlag);
+            State->Flags.Af = ((Value & 0x0F) != 0);
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SignFlag) != 0);
+            State->Flags.Pf = Fast486CalculateParity(Result);
+
+            /* Write back the result */
+            if (OperandSize)
+            {
+                /* 32-bit */
+                return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
+            }
+            else
+            {
+                /* 16-bit */
+                return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(Result));
+            }
+        }
+
+        /* MUL */
+        case 4:
+        {
+            if (OperandSize)
+            {
+                ULONGLONG Result = (ULONGLONG)Value * (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long;
+
+                /* Update the flags */
+                State->Flags.Cf = State->Flags.Of = ((Result & 0xFFFFFFFF00000000ULL) != 0);
+
+                /* Write back the result */
+                State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
+                State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32;
+            }
+            else
+            {
+                ULONG Result = (ULONG)Value * (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord;
+
+                /* Update the flags */
+                State->Flags.Cf = State->Flags.Of = (HIWORD(Result) != 0);
+
+                /* Write back the result */
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
+                State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result);
+            }
+
+            break;
+        }
+
+        /* IMUL */
+        case 5:
+        {
+            if (OperandSize)
+            {
+                LONGLONG Result = (LONGLONG)((LONG)Value) * (LONGLONG)((LONG)State->GeneralRegs[FAST486_REG_EAX].Long);
+
+                /* Update the flags */
+                State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL));
+
+                /* Write back the result */
+                State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
+                State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32;
+            }
+            else
+            {
+                LONG Result = (LONG)((SHORT)Value) * (LONG)((SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord);
+
+                /* Update the flags */
+                State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767));
+
+                /* Write back the result */
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
+                State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result);
+            }
+
+            break;
+        }
+
+        /* DIV */
+        case 6:
+        {
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            if (OperandSize)
+            {
+                ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
+                                     | ((ULONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
+                ULONG Quotient = Dividend / Value;
+                ULONG Remainder = Dividend % Value;
+
+                /* Write back the results */
+                State->GeneralRegs[FAST486_REG_EAX].Long = Quotient;
+                State->GeneralRegs[FAST486_REG_EDX].Long = Remainder;
+            }
+            else
+            {
+                ULONG Dividend = (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
+                                 | ((ULONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
+                USHORT Quotient = Dividend / Value;
+                USHORT Remainder = Dividend % Value;
+
+                /* Write back the results */
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = Quotient;
+                State->GeneralRegs[FAST486_REG_EDX].LowWord = Remainder;
+            }
+
+            break;
+        }
+
+        /* IDIV */
+        case 7:
+        {
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            if (OperandSize)
+            {
+                LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
+                                     | ((LONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
+                LONG Quotient = Dividend / (LONG)Value;
+                LONG Remainder = Dividend % (LONG)Value;
+
+                /* Write back the results */
+                State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient;
+                State->GeneralRegs[FAST486_REG_EDX].Long = (ULONG)Remainder;
+            }
+            else
+            {
+                LONG Dividend = (LONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
+                                 | ((LONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
+                SHORT Quotient = Dividend / (SHORT)LOWORD(Value);
+                SHORT Remainder = Dividend % (SHORT)LOWORD(Value);
+
+                /* Write back the results */
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient;
+                State->GeneralRegs[FAST486_REG_EDX].LowWord = (USHORT)Remainder;
+            }
+
+            break;
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
+{
+    UCHAR Value;
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register > 1)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register == 0)
+    {
+        /* Increment and update OF and AF */
+        Value++;
+        State->Flags.Of = (Value == SIGN_FLAG_BYTE);
+        State->Flags.Af = ((Value & 0x0F) == 0);
+    }
+    else
+    {
+        /* Decrement and update OF and AF */
+        State->Flags.Of = (Value == SIGN_FLAG_BYTE);
+        Value--;
+        State->Flags.Af = ((Value & 0x0F) == 0x0F);
+    }
+
+    /* Update flags */
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
+    /* Write back the result */
+    return Fast486WriteModrmByteOperands(State,
+                                         &ModRegRm,
+                                         FALSE,
+                                         Value);
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register == 7)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Read the operands */
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (ModRegRm.Register == 0)
+        {
+            /* Increment and update OF and AF */
+            Value++;
+            State->Flags.Of = (Value == SIGN_FLAG_LONG);
+            State->Flags.Af = ((Value & 0x0F) == 0);
+        }
+        else if (ModRegRm.Register == 1)
+        {
+            /* Decrement and update OF and AF */
+            State->Flags.Of = (Value == SIGN_FLAG_LONG);
+            Value--;
+            State->Flags.Af = ((Value & 0x0F) == 0x0F);
+        }
+        else if (ModRegRm.Register == 2)
+        {
+            /* Push the current value of EIP */
+            if (!Fast486StackPush(State, State->InstPtr.Long))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the EIP to the address */
+            State->InstPtr.Long = Value;
+        }
+        else if (ModRegRm.Register == 3)
+        {
+            USHORT Selector;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read the selector */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress + sizeof(ULONG),
+                                   FALSE,
+                                   &Selector,
+                                   sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Push the current value of CS */
+            if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Push the current value of EIP */
+            if (!Fast486StackPush(State, State->InstPtr.Long))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new code segment */
+            if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the EIP to the address */
+            State->InstPtr.Long = Value;
+        }
+        else if (ModRegRm.Register == 4)
+        {
+            /* Set the EIP to the address */
+            State->InstPtr.Long = Value;
+        }
+        else if (ModRegRm.Register == 5)
+        {
+            USHORT Selector;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read the selector */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress + sizeof(ULONG),
+                                   FALSE,
+                                   &Selector,
+                                   sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new code segment */
+            if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the EIP to the address */
+            State->InstPtr.Long = Value;
+        }
+        else if (ModRegRm.Register == 6)
+        {
+            /* Push the value on to the stack */
+            return Fast486StackPush(State, Value);
+        }
+
+        if (ModRegRm.Register <= 1)
+        {
+            /* Update flags */
+            State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
+            State->Flags.Zf = (Value == 0);
+            State->Flags.Pf = Fast486CalculateParity(Value);
+
+            /* Write back the result */
+            return Fast486WriteModrmDwordOperands(State,
+                                                  &ModRegRm,
+                                                  FALSE,
+                                                  Value);
+        }
+    }
+    else
+    {
+        USHORT Value;
+
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        if (ModRegRm.Register == 0)
+        {
+            /* Increment and update OF */
+            Value++;
+            State->Flags.Of = (Value == SIGN_FLAG_WORD);
+            State->Flags.Af = ((Value & 0x0F) == 0);
+        }
+        else if (ModRegRm.Register == 1)
+        {
+            /* Decrement and update OF */
+            State->Flags.Of = (Value == SIGN_FLAG_WORD);
+            Value--;
+            State->Flags.Af = ((Value & 0x0F) == 0x0F);
+        }
+        else if (ModRegRm.Register == 2)
+        {
+            /* Push the current value of IP */
+            if (!Fast486StackPush(State, State->InstPtr.LowWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the IP to the address */
+            State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
+        else if (ModRegRm.Register == 3)
+        {
+            USHORT Selector;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read the selector */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress + sizeof(USHORT),
+                                   FALSE,
+                                   &Selector,
+                                   sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Push the current value of CS */
+            if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Push the current value of IP */
+            if (!Fast486StackPush(State, State->InstPtr.LowWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new code segment */
+            if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the IP to the address */
+            State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
+        else if (ModRegRm.Register == 4)
+        {
+            /* Set the IP to the address */
+            State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
+        else if (ModRegRm.Register == 5)
+        {
+            USHORT Selector;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+            /* Check for the segment override */
+            if (State->PrefixFlags & FAST486_PREFIX_SEG)
+            {
+                /* Use the override segment instead */
+                Segment = State->SegmentOverride;
+            }
+
+            /* Read the selector */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress + sizeof(USHORT),
+                                   FALSE,
+                                   &Selector,
+                                   sizeof(USHORT)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new code segment */
+            if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Set the IP to the address */
+            State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
+        else if (ModRegRm.Register == 6)
+        {
+            /* Push the value on to the stack */
+            return Fast486StackPush(State, Value);
+        }
+        else
+        {
+            /* Invalid */
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+            return FALSE;
+        }
+
+        if (ModRegRm.Register <= 1)
+        {
+            /* Update flags */
+            State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
+            State->Flags.Zf = (Value == 0);
+            State->Flags.Pf = Fast486CalculateParity(Value);
+
+            /* Write back the result */
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 Value);
+        }
+    }
+
+    return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check which operation this is */
+    switch (ModRegRm.Register)
+    {
+        /* SLDT */
+        case 0:
+        {
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 State->Ldtr.Selector);
+        }
+
+        /* STR */
+        case 1:
+        {
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 State->TaskReg.Selector);
+        }
+
+        /* LLDT */
+        case 2:
+        {
+            USHORT Selector;
+            FAST486_SYSTEM_DESCRIPTOR GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Make sure the GDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the GDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Gdtr.Address
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                RtlZeroMemory(&State->Ldtr, sizeof(State->Ldtr));
+                return TRUE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                return FALSE;
+            }
+
+            if (GdtEntry.Signature != FAST486_LDT_SIGNATURE)
+            {
+                /* This is not a LDT descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Update the LDTR */
+            State->Ldtr.Selector = Selector;
+            State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
+            State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+            if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+            return TRUE;
+        }
+
+        /* LTR */
+        case 3:
+        {
+            USHORT Selector;
+            FAST486_SYSTEM_DESCRIPTOR GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Make sure the GDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the GDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Gdtr.Address
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                return FALSE;
+            }
+
+            if (GdtEntry.Signature != FAST486_TSS_SIGNATURE)
+            {
+                /* This is not a TSS descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Update the TR */
+            State->TaskReg.Selector = Selector;
+            State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
+            State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+            if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12;
+            State->TaskReg.Busy = TRUE;
+
+            return TRUE;
+        }
+
+        /* VERR/VERW */
+        case 4:
+        case 5:
+        {
+            USHORT Selector;
+            FAST486_GDT_ENTRY GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (!(Selector & SEGMENT_TABLE_INDICATOR))
+            {
+                /* Make sure the GDT contains the entry */
+                if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+                {
+                    /* Clear ZF */
+                    State->Flags.Zf = FALSE;
+                    return TRUE;
+                }
+
+                /* Read the GDT */
+                if (!Fast486ReadLinearMemory(State,
+                                             State->Gdtr.Address
+                                             + GET_SEGMENT_INDEX(Selector),
+                                             &GdtEntry,
+                                             sizeof(GdtEntry)))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+            else
+            {
+                /* Make sure the LDT contains the entry */
+                if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+                {
+                    /* Clear ZF */
+                    State->Flags.Zf = FALSE;
+                    return TRUE;
+                }
+
+                /* Read the LDT */
+                if (!Fast486ReadLinearMemory(State,
+                                             State->Ldtr.Base
+                                             + GET_SEGMENT_INDEX(Selector),
+                                             &GdtEntry,
+                                             sizeof(GdtEntry)))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+
+            /* Set ZF if it is valid and accessible */
+            State->Flags.Zf = GdtEntry.Present // must be present
+                               && GdtEntry.SystemType // must be a segment
+                               && (((ModRegRm.Register == 4)
+                               /* code segments are only readable if the RW bit is set */
+                               && (!GdtEntry.Executable || GdtEntry.ReadWrite))
+                               || ((ModRegRm.Register == 5)
+                               /* code segments are never writable, data segments are writable when RW is set */
+                               && (!GdtEntry.Executable && GdtEntry.ReadWrite)))
+                               /*
+                                * for segments other than conforming code segments,
+                                * both RPL and CPL must be less than or equal to DPL
+                                */
+                               && ((!GdtEntry.Executable || !GdtEntry.DirConf)
+                               && ((GET_SEGMENT_RPL(Selector) <= GdtEntry.Dpl)
+                               && (Fast486GetCurrentPrivLevel(State) <= GdtEntry.Dpl)))
+                               /* for conforming code segments, DPL must be less than or equal to CPL */
+                               && ((GdtEntry.Executable && GdtEntry.DirConf)
+                               && (GdtEntry.Dpl <= Fast486GetCurrentPrivLevel(State)));
+
+
+            return TRUE;
+        }
+
+        /* Invalid */
+        default:
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+            return FALSE;
+        }
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
+{
+    UCHAR TableReg[6];
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check for the segment override */
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead */
+        Segment = State->SegmentOverride;
+    }
+
+    /* Check which operation this is */
+    switch (ModRegRm.Register)
+    {
+        /* SGDT */
+        case 0:
+        {
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Fill the 6-byte table register */
+            RtlCopyMemory(TableReg, &State->Gdtr.Size, sizeof(USHORT));
+            RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Gdtr.Address, sizeof(ULONG));
+
+            /* Store the GDTR */
+            return Fast486WriteMemory(State,
+                                      Segment,
+                                      ModRegRm.MemoryAddress,
+                                      TableReg,
+                                      sizeof(TableReg));
+        }
+
+        /* SIDT */
+        case 1:
+        {
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Fill the 6-byte table register */
+            RtlCopyMemory(TableReg, &State->Idtr.Size, sizeof(USHORT));
+            RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Idtr.Address, sizeof(ULONG));
+
+            /* Store the IDTR */
+            return Fast486WriteMemory(State,
+                                      Segment,
+                                      ModRegRm.MemoryAddress,
+                                      TableReg,
+                                      sizeof(TableReg));
+        }
+
+        /* LGDT */
+        case 2:
+        {
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Read the new GDTR */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress,
+                                   FALSE,
+                                   TableReg,
+                                   sizeof(TableReg)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new GDT */
+            State->Gdtr.Size = *((PUSHORT)TableReg);
+            State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
+
+            return TRUE;
+        }
+
+        /* LIDT */
+        case 3:
+        {
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Read the new IDTR */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress,
+                                   FALSE,
+                                   TableReg,
+                                   sizeof(TableReg)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new IDT */
+            State->Idtr.Size = *((PUSHORT)TableReg);
+            State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
+
+            return TRUE;
+        }
+
+        /* SMSW */
+        case 4:
+        {
+            /* Store the lower 16 bits (Machine Status Word) of CR0 */
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 LOWORD(State->ControlRegisters[FAST486_REG_CR0]));
+        }
+
+        /* LMSW */
+        case 6:
+        {
+            USHORT MachineStatusWord;
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            /* Read the new Machine Status Word */
+            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &MachineStatusWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* This instruction cannot be used to return to real mode */
+            if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                && !(MachineStatusWord & FAST486_CR0_PE))
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            /* Set the lowest 4 bits */
+            State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF0;
+            State->ControlRegisters[FAST486_REG_CR0] |= MachineStatusWord & 0x0F;
+
+            return TRUE;
+        }
+
+        /* INVLPG */
+        case 7:
+        {
+            UNIMPLEMENTED;
+            return FALSE;
+        }
+
+        /* Invalid */
+        default:
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+            return FALSE;
+        }
+    }
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* All of them are reserved (UD2) */
+    Fast486Exception(State, FAST486_EXCEPTION_UD);
+    return FALSE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN OperandSize, AddressSize;
+    UINT DataSize;
+    UCHAR BitNumber;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Get the number of bits */
+    if (OperandSize) DataSize = 32;
+    else DataSize = 16;
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Register < 4)
+    {
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        return FALSE;
+    }
+
+    /* Get the bit number */
+    if (!Fast486FetchByte(State, &BitNumber))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    if (ModRegRm.Memory)
+    {
+        /*
+         * For memory operands, add the bit offset divided by
+         * the data size to the address
+         */
+        ModRegRm.MemoryAddress += BitNumber / DataSize;
+    }
+
+    /* Normalize the bit number */
+    BitNumber %= DataSize;
+
+    if (OperandSize)
+    {
+        ULONG Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        if (ModRegRm.Register == 5)
+        {
+            /* BTS */
+            Value |= 1 << BitNumber;
+        }
+        else if (ModRegRm.Register == 6)
+        {
+            /* BTR */
+            Value &= ~(1 << BitNumber);
+        }
+        else if (ModRegRm.Register == 7)
+        {
+            /* BTC */
+            Value ^= 1 << BitNumber;
+        }
+
+        if (ModRegRm.Register >= 5)
+        {
+            /* Write back the result */
+            if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+    else
+    {
+        USHORT Value;
+
+        /* Read the value */
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
+        {
+            /* Exception occurred */
+            return FALSE;
+        }
+
+        /* Set CF to the bit value */
+        State->Flags.Cf = (Value >> BitNumber) & 1;
+
+        if (ModRegRm.Register == 5)
+        {
+            /* BTS */
+            Value |= 1 << BitNumber;
+        }
+        else if (ModRegRm.Register == 6)
+        {
+            /* BTR */
+            Value &= ~(1 << BitNumber);
+        }
+        else if (ModRegRm.Register == 7)
+        {
+            /* BTC */
+            Value ^= 1 << BitNumber;
+        }
+
+        if (ModRegRm.Register >= 5)
+        {
+            /* Write back the result */
+            if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+        }
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+/* EOF */
diff --git a/lib/fast486/opgroups.h b/lib/fast486/opgroups.h
new file mode 100644 (file)
index 0000000..bf55cce
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opgroups.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _OPGROUPS_H_
+#define _OPGROUPS_H_
+
+#pragma once
+
+/* DEFINES ********************************************************************/
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA);
+
+#endif // _OPGROUPS_H_
+
+/* EOF */
+
index 1243f59..784e446 100644 (file)
@@ -12,7 +12,7 @@
  *                  Samuel Serapión
  */
 
-/* Based on Wine 1.1.26 */
+/* Based on Wine 1.7.17 */
 
 #include <rtl.h>
 
 BOOLEAN RtlpNotAllowingMultipleActivation;
 
 #define ACTCTX_FLAGS_ALL (\
-    ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
-    ACTCTX_FLAG_LANGID_VALID |\
-    ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
-    ACTCTX_FLAG_RESOURCE_NAME_VALID |\
-    ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
-    ACTCTX_FLAG_APPLICATION_NAME_VALID |\
-    ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
-    ACTCTX_FLAG_HMODULE_VALID )
+ ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
+ ACTCTX_FLAG_LANGID_VALID |\
+ ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
+ ACTCTX_FLAG_RESOURCE_NAME_VALID |\
+ ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
+ ACTCTX_FLAG_APPLICATION_NAME_VALID |\
+ ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
+ ACTCTX_FLAG_HMODULE_VALID )
+
+#define STRSECTION_MAGIC   0x64487353 /* dHsS */
+#define GUIDSECTION_MAGIC  0x64487347 /* dHsG */
 
 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
 
@@ -77,6 +80,291 @@ struct assembly_identity
     BOOL                  optional;
 };
 
+struct strsection_header
+{
+    DWORD magic;
+    ULONG size;
+    DWORD unk1[3];
+    ULONG count;
+    ULONG index_offset;
+    DWORD unk2[2];
+    ULONG global_offset;
+    ULONG global_len;
+};
+
+struct string_index
+{
+    ULONG hash;        /* key string hash */
+    ULONG name_offset;
+    ULONG name_len;
+    ULONG data_offset; /* redirect data offset */
+    ULONG data_len;
+    ULONG rosterindex;
+};
+
+struct guidsection_header
+{
+    DWORD magic;
+    ULONG size;
+    DWORD unk[3];
+    ULONG count;
+    ULONG index_offset;
+    DWORD unk2;
+    ULONG names_offset;
+    ULONG names_len;
+};
+
+struct guid_index
+{
+    GUID  guid;
+    ULONG data_offset;
+    ULONG data_len;
+    ULONG rosterindex;
+};
+
+struct wndclass_redirect_data
+{
+    ULONG size;
+    DWORD res;
+    ULONG name_len;
+    ULONG name_offset;  /* versioned name offset */
+    ULONG module_len;
+    ULONG module_offset;/* container name offset */
+};
+
+struct dllredirect_data
+{
+    ULONG size;
+    ULONG unk;
+    DWORD res[3];
+};
+
+struct tlibredirect_data
+{
+    ULONG  size;
+    DWORD  res;
+    ULONG  name_len;
+    ULONG  name_offset;
+    LANGID langid;
+    WORD   flags;
+    ULONG  help_len;
+    ULONG  help_offset;
+    WORD   major_version;
+    WORD   minor_version;
+};
+
+enum comclass_threadingmodel
+{
+    ThreadingModel_Apartment = 1,
+    ThreadingModel_Free      = 2,
+    ThreadingModel_No        = 3,
+    ThreadingModel_Both      = 4,
+    ThreadingModel_Neutral   = 5
+};
+
+enum comclass_miscfields
+{
+    MiscStatus          = 1,
+    MiscStatusIcon      = 2,
+    MiscStatusContent   = 4,
+    MiscStatusThumbnail = 8,
+    MiscStatusDocPrint  = 16
+};
+
+struct comclassredirect_data
+{
+    ULONG size;
+    BYTE  res;
+    BYTE  miscmask;
+    BYTE  res1[2];
+    DWORD model;
+    GUID  clsid;
+    GUID  alias;
+    GUID  clsid2;
+    GUID  tlbid;
+    ULONG name_len;
+    ULONG name_offset;
+    ULONG progid_len;
+    ULONG progid_offset;
+    ULONG clrdata_len;
+    ULONG clrdata_offset;
+    DWORD miscstatus;
+    DWORD miscstatuscontent;
+    DWORD miscstatusthumbnail;
+    DWORD miscstatusicon;
+    DWORD miscstatusdocprint;
+};
+
+enum ifaceps_mask
+{
+    NumMethods = 1,
+    BaseIface  = 2
+};
+
+struct ifacepsredirect_data
+{
+    ULONG size;
+    DWORD mask;
+    GUID  iid;
+    ULONG nummethods;
+    GUID  tlbid;
+    GUID  base;
+    ULONG name_len;
+    ULONG name_offset;
+};
+
+struct clrsurrogate_data
+{
+    ULONG size;
+    DWORD res;
+    GUID  clsid;
+    ULONG version_offset;
+    ULONG version_len;
+    ULONG name_offset;
+    ULONG name_len;
+};
+
+struct clrclass_data
+{
+    ULONG size;
+    DWORD res[2];
+    ULONG module_len;
+    ULONG module_offset;
+    ULONG name_len;
+    ULONG name_offset;
+    ULONG version_len;
+    ULONG version_offset;
+    DWORD res2[2];
+};
+
+struct progidredirect_data
+{
+    ULONG size;
+    DWORD reserved;
+    ULONG clsid_offset;
+};
+
+/*
+
+   Sections structure.
+
+   Sections are accessible by string or guid key, that defines two types of sections.
+   All sections of each type have same magic value and header structure, index
+   data could be of two possible types too. So every string based section uses
+   the same index format, same applies to guid sections - they share same guid index
+   format.
+
+   - window class redirection section is a plain buffer with following format:
+
+   <section header>
+   <index[]>
+   <data[]> --- <original name>
+                <redirect data>
+                <versioned name>
+                <module name>
+
+   Header is fixed length structure - struct strsection_header,
+   contains redirected classes count;
+
+   Index is an array of fixed length index records, each record is
+   struct string_index.
+
+   All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
+
+   Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
+   others are relative to section itself.
+
+   - dll redirect section format:
+
+   <section header>
+   <index[]>
+   <data[]> --- <dll name>
+                <data>
+
+   This section doesn't seem to carry any payload data except dll names.
+
+   - typelib section format:
+
+   <section header>
+   <module names[]>
+   <index[]>
+   <data[]> --- <data>
+                <helpstring>
+
+   Header is fixed length, index is an array of fixed length 'struct guid_index'.
+   All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
+   4-bytes aligned as a whole.
+
+   Module name offsets are relative to section, helpstring offset is relative to data
+   structure itself.
+
+   - comclass section format:
+
+   <section header>
+   <module names[]>
+   <index[]>
+   <data[]> --- <data>   --- <data>
+                <progid>     <clrdata>
+                             <name>
+                             <version>
+                             <progid>
+
+   This section uses two index records per comclass, one entry contains original guid
+   as specified by context, another one has a generated guid. Index and strings handling
+   is similar to typelib sections.
+
+   For CLR classes additional data is stored after main COM class data, it contains
+   class name and runtime version string, see 'struct clrclass_data'.
+
+   Module name offsets are relative to section, progid offset is relative to data
+   structure itself.
+
+   - COM interface section format:
+
+   <section header>
+   <index[]>
+   <data[]> --- <data>
+                <name>
+
+   Interface section contains data for proxy/stubs and external proxy/stubs. External
+   ones are defined at assembly level, so this section has no module information.
+   All records are indexed with 'iid' value from manifest. There an exception for
+   external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
+   redirect data, but index is still 'iid' from manifest.
+
+   Interface name offset is relative to data structure itself.
+
+   - CLR surrogates section format:
+
+   <section header>
+   <index[]>
+   <data[]> --- <data>
+                <name>
+                <version>
+
+    There's nothing special about this section, same way to store strings is used,
+    no modules part as it belongs to assembly level, not a file.
+
+   - ProgID section format:
+
+   <section header>
+   <guids[]>
+   <index[]>
+   <data[]> --- <progid>
+                <data>
+
+   This sections uses generated alias guids from COM server section. This way
+   ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
+   is stored too, aligned.
+*/
+
+struct progids
+{
+    WCHAR        **progids;
+    unsigned int   num;
+    unsigned int   allocated;
+};
+
 struct entity
 {
     DWORD kind;
@@ -85,30 +373,45 @@ struct entity
         struct
         {
             WCHAR *tlbid;
-            WCHAR *version;
             WCHAR *helpdir;
-        } typelib;
+            WORD   flags;
+            WORD   major;
+            WORD   minor;
+       } typelib;
         struct
         {
             WCHAR *clsid;
-        } comclass;
-        struct {
+            WCHAR *tlbid;
+            WCHAR *progid;
+            WCHAR *name;    /* clrClass: class name */
+            WCHAR *version; /* clrClass: CLR runtime version */
+            DWORD  model;
+            DWORD  miscstatus;
+            DWORD  miscstatuscontent;
+            DWORD  miscstatusthumbnail;
+            DWORD  miscstatusicon;
+            DWORD  miscstatusdocprint;
+            struct progids progids;
+       } comclass;
+       struct {
             WCHAR *iid;
+            WCHAR *base;
+            WCHAR *tlib;
             WCHAR *name;
-        } proxy;
+            WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
+            DWORD  mask;
+            ULONG  nummethods;
+       } ifaceps;
         struct
         {
             WCHAR *name;
+            BOOL   versioned;
         } class;
         struct
         {
             WCHAR *name;
             WCHAR *clsid;
-        } clrclass;
-        struct
-        {
-            WCHAR *name;
-            WCHAR *clsid;
+            WCHAR *version;
         } clrsurrogate;
     } u;
 };
@@ -147,6 +450,17 @@ struct assembly
     struct entity_array      entities;
 };
 
+enum context_sections
+{
+    WINDOWCLASS_SECTION    = 1,
+    DLLREDIRECT_SECTION    = 2,
+    TLIBREDIRECT_SECTION   = 4,
+    SERVERREDIRECT_SECTION = 8,
+    IFACEREDIRECT_SECTION  = 16,
+    CLRSURROGATES_SECTION  = 32,
+    PROGIDREDIRECT_SECTION = 64
+};
+
 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
 {
     ULONG Flags;
@@ -180,6 +494,15 @@ typedef struct _ACTIVATION_CONTEXT
     struct assembly *assemblies;
     unsigned int num_assemblies;
     unsigned int allocated_assemblies;
+    /* section data */
+    DWORD sections;
+    struct strsection_header *wndclass_section;
+    struct strsection_header *dllredirect_section;
+    struct strsection_header *progid_section;
+    struct guidsection_header *tlib_section;
+    struct guidsection_header *comserver_section;
+    struct guidsection_header *ifaceps_section;
+    struct guidsection_header *clrsurrogate_section;
 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
 
 struct actctx_loader
@@ -278,11 +601,87 @@ static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
 static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
+static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
 static const WCHAR typeW[] = {'t','y','p','e',0};
 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
+static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
+static const WCHAR yesW[] = {'y','e','s',0};
+static const WCHAR noW[] = {'n','o',0};
+static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
+static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
+static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
+static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
+static const WCHAR flagsW[] = {'f','l','a','g','s',0};
+static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
+static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
+static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
+static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
+static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
+static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
+static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
+static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
+static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
+static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
+static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
+
+static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
+static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
+static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
+static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
+static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
+static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
+static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
+static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
+static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
+static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
+static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
+static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
+static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
+static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
+static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
+static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
+static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
+static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
+static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
+static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
+static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
+static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
+
+struct olemisc_entry
+{
+    const WCHAR *name;
+    OLEMISC value;
+};
+
+static const struct olemisc_entry olemisc_values[] =
+{
+    { activatewhenvisibleW,          OLEMISC_ACTIVATEWHENVISIBLE },
+    { actslikebuttonW,               OLEMISC_ACTSLIKEBUTTON },
+    { actslikelabelW,                OLEMISC_ACTSLIKELABEL },
+    { alignableW,                    OLEMISC_ALIGNABLE },
+    { alwaysrunW,                    OLEMISC_ALWAYSRUN },
+    { canlinkbyole1W,                OLEMISC_CANLINKBYOLE1 },
+    { cantlinkinsideW,               OLEMISC_CANTLINKINSIDE },
+    { ignoreactivatewhenvisibleW,    OLEMISC_IGNOREACTIVATEWHENVISIBLE },
+    { imemodeW,                      OLEMISC_IMEMODE },
+    { insertnotreplaceW,             OLEMISC_INSERTNOTREPLACE },
+    { insideoutW,                    OLEMISC_INSIDEOUT },
+    { invisibleatruntimeW,           OLEMISC_INVISIBLEATRUNTIME },
+    { islinkobjectW,                 OLEMISC_ISLINKOBJECT },
+    { nouiactivateW,                 OLEMISC_NOUIACTIVATE },
+    { onlyiconicW,                   OLEMISC_ONLYICONIC },
+    { recomposeonresizeW,            OLEMISC_RECOMPOSEONRESIZE },
+    { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
+    { setclientsitefirstW,           OLEMISC_SETCLIENTSITEFIRST },
+    { simpleframeW,                  OLEMISC_SIMPLEFRAME },
+    { staticW,                       OLEMISC_STATIC },
+    { supportsmultilevelundoW,       OLEMISC_SUPPORTSMULTILEVELUNDO },
+    { wantstomenumergeW,             OLEMISC_WANTSTOMENUMERGE }
+};
 
 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
 static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
@@ -460,7 +859,7 @@ static struct entity* add_entity(struct entity_array *array, DWORD kind)
 
 static void free_entity_array(struct entity_array *array)
 {
-    unsigned int i;
+    unsigned int i, j;
     for (i = 0; i < array->num; i++)
     {
         struct entity *entity = &array->base[i];
@@ -468,26 +867,31 @@ static void free_entity_array(struct entity_array *array)
         {
         case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
+            for (j = 0; j < entity->u.comclass.progids.num; j++)
+                RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
             break;
         case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
-            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
             break;
         case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version);
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
             break;
         case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
             break;
-        case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
-            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid);
-            break;
         case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
             break;
         default:
             DPRINT1("Unknown entity kind %u\n", entity->kind);
@@ -1004,7 +1408,110 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a
     return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
 }
 
-static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
+{
+    static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
+    static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
+    static const WCHAR freeW[] = {'F','r','e','e',0};
+    static const WCHAR bothW[] = {'B','o','t','h',0};
+
+    if (value->len == 0) return ThreadingModel_No;
+    if (xmlstr_cmp(value, apartW))
+        return ThreadingModel_Apartment;
+    else if (xmlstr_cmp(value, freeW))
+        return ThreadingModel_Free;
+    else if (xmlstr_cmp(value, bothW))
+        return ThreadingModel_Both;
+    else if (xmlstr_cmp(value, neutralW))
+        return ThreadingModel_Neutral;
+    else
+        return ThreadingModel_No;
+};
+
+static OLEMISC get_olemisc_value(const WCHAR *str, int len)
+{
+    int min, max;
+
+    min = 0;
+    max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
+
+    while (min <= max)
+    {
+        int n, c;
+
+        n = (min+max)/2;
+
+        c = strncmpW(olemisc_values[n].name, str, len);
+        if (!c && !olemisc_values[n].name[len])
+            return olemisc_values[n].value;
+
+        if (c >= 0)
+            max = n-1;
+        else
+            min = n+1;
+    }
+
+    DPRINT1("unknown flag %S\n", str);
+    return 0;
+}
+
+static DWORD parse_com_class_misc(const xmlstr_t *value)
+{
+    const WCHAR *str = value->ptr, *start;
+    DWORD flags = 0;
+    int i = 0;
+
+    /* it's comma separated list of flags */
+    while (i < value->len)
+    {
+        start = str;
+        while (*str != ',' && (i++ < value->len)) str++;
+
+        flags |= get_olemisc_value(start, str-start);
+
+        /* skip separator */
+        str++;
+        i++;
+    }
+
+    return flags;
+}
+
+static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
+{
+    struct progids *progids = &entity->u.comclass.progids;
+
+    if (progids->allocated == 0)
+    {
+        progids->allocated = 4;
+        if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
+    }
+
+    if (progids->allocated == progids->num)
+    {
+        progids->allocated *= 2;
+        progids->progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
+    }
+
+    if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
+    progids->num++;
+
+    return TRUE;
+}
+
+static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
+{
+    xmlstr_t content;
+    BOOL end = FALSE;
+
+    if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
+        return FALSE;
+
+    if (!com_class_add_progid(&content, entity)) return FALSE;
+    return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
+}
+
+static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
 {
     xmlstr_t elem, attr_name, attr_value;
     BOOL ret = TRUE, end = FALSE, error;
@@ -1020,6 +1527,42 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
         {
             if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
         }
+        else if (xmlstr_cmp(&attr_name, progidW))
+        {
+            if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, tlbidW))
+        {
+            if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, threadingmodelW))
+        {
+            entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, miscstatusW))
+        {
+            entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
+        {
+            entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
+        {
+            entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, miscstatusiconW))
+        {
+            entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
+        {
+            entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, descriptionW))
+        {
+            /* not stored */
+        }
         else
         {
             attr_nameU = xmlstr2unicode(&attr_name);
@@ -1028,15 +1571,25 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
         }
     }
 
-    if (error || end) return end;
+    if (error) return FALSE;
 
-    while ((ret = next_xml_elem(xmlbuf, &elem)))
+    acl->actctx->sections |= SERVERREDIRECT_SECTION;
+    if (entity->u.comclass.progid)
+        acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
+    if (end) return TRUE;
+
+    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
     {
         if (xmlstr_cmp_end(&elem, comClassW))
         {
             ret = parse_end_element(xmlbuf);
             break;
         }
+        else if (xmlstr_cmp(&elem, progidW))
+        {
+            ret = parse_com_class_progid(xmlbuf, entity);
+        }
         else
         {
             attr_nameU = xmlstr2unicode(&elem);
@@ -1044,10 +1597,35 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
             ret = parse_unknown_elem(xmlbuf, &elem);
         }
     }
+
+    if (entity->u.comclass.progids.num)
+        acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
     return ret;
 }
 
-static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
+{
+    const WCHAR *curr;
+    ULONG num = 0;
+
+    for (curr = str->ptr; curr < str->ptr + str->len; curr++)
+    {
+        if (*curr >= '0' && *curr <= '9')
+            num = num * 10 + *curr - '0';
+        else
+        {
+            UNICODE_STRING strU = xmlstr2unicode(str);
+            DPRINT1("wrong numeric value %wZ\n", &strU);
+            return FALSE;
+        }
+    }
+    entity->u.ifaceps.nummethods = num;
+
+    return TRUE;
+}
+
+static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
 {
     xmlstr_t    attr_name, attr_value;
     BOOL        end = FALSE, error;
@@ -1061,11 +1639,29 @@ static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redi
     {
         if (xmlstr_cmp(&attr_name, iidW))
         {
-            if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+            if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
         }
-        if (xmlstr_cmp(&attr_name, g_nameW))
+        else if (xmlstr_cmp(&attr_name, g_nameW))
+        {
+            if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, baseInterfaceW))
+        {
+            if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
+            entity->u.ifaceps.mask |= BaseIface;
+        }
+        else if (xmlstr_cmp(&attr_name, nummethodsW))
+        {
+            if (!(parse_nummethods(&attr_value, entity))) return FALSE;
+            entity->u.ifaceps.mask |= NumMethods;
+        }
+        else if (xmlstr_cmp(&attr_name, tlbidW))
+        {
+            if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        /* not used */
+        else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
         {
-            if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
         }
         else
         {
@@ -1075,11 +1671,83 @@ static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redi
         }
     }
 
-    if (error || end) return end;
+    if (error) return FALSE;
+    acl->actctx->sections |= IFACEREDIRECT_SECTION;
+    if (end) return TRUE;
+
     return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
 }
 
-static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
+{
+    WORD *flags = &entity->u.typelib.flags;
+    const WCHAR *str = value->ptr, *start;
+    int i = 0;
+
+    *flags = 0;
+
+    /* it's comma separated list of flags */
+    while (i < value->len)
+    {
+        start = str;
+        while (*str != ',' && (i++ < value->len)) str++;
+
+        if (!strncmpiW(start, restrictedW, str-start))
+            *flags |= LIBFLAG_FRESTRICTED;
+        else if (!strncmpiW(start, controlW, str-start))
+            *flags |= LIBFLAG_FCONTROL;
+        else if (!strncmpiW(start, hiddenW, str-start))
+            *flags |= LIBFLAG_FHIDDEN;
+        else if (!strncmpiW(start, hasdiskimageW, str-start))
+            *flags |= LIBFLAG_FHASDISKIMAGE;
+        else
+        {
+            UNICODE_STRING valueU = xmlstr2unicode(value);
+            DPRINT1("unknown flags value %wZ\n", &valueU);
+            return FALSE;
+        }
+
+        /* skip separator */
+        str++;
+        i++;
+    }
+
+    return TRUE;
+}
+
+static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
+{
+    unsigned int ver[2];
+    unsigned int pos;
+    const WCHAR *curr;
+    UNICODE_STRING strW;
+
+    /* major.minor */
+    ver[0] = ver[1] = pos = 0;
+    for (curr = str->ptr; curr < str->ptr + str->len; curr++)
+    {
+        if (*curr >= '0' && *curr <= '9')
+        {
+            ver[pos] = ver[pos] * 10 + *curr - '0';
+            if (ver[pos] >= 0x10000) goto error;
+        }
+        else if (*curr == '.')
+        {
+            if (++pos >= 2) goto error;
+        }
+        else goto error;
+    }
+    entity->u.typelib.major = ver[0];
+    entity->u.typelib.minor = ver[1];
+    return TRUE;
+
+error:
+    strW = xmlstr2unicode(str);
+    DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
+    return FALSE;
+}
+
+static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
 {
     xmlstr_t    attr_name, attr_value;
     BOOL        end = FALSE, error;
@@ -1095,14 +1763,18 @@ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
         {
             if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
         }
-        if (xmlstr_cmp(&attr_name, versionW))
+        else if (xmlstr_cmp(&attr_name, versionW))
         {
-            if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
+            if (!parse_typelib_version(&attr_value, entity)) return FALSE;
         }
-        if (xmlstr_cmp(&attr_name, helpdirW))
+        else if (xmlstr_cmp(&attr_name, helpdirW))
         {
             if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
         }
+        else if (xmlstr_cmp(&attr_name, flagsW))
+        {
+            if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
+        }
         else
         {
             attr_nameU = xmlstr2unicode(&attr_name);
@@ -1111,30 +1783,69 @@ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
         }
     }
 
-    if (error || end) return end;
+    if (error) return FALSE;
+
+    acl->actctx->sections |= TLIBREDIRECT_SECTION;
+
+    if (end) return TRUE;
+
     return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
 }
 
-static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static inline int aligned_string_len(int len)
 {
-    xmlstr_t elem, content;
-    BOOL end = FALSE, ret = TRUE;
-    struct entity*      entity;
-    UNICODE_STRING elemU;
+    return (len + 3) & ~3;
+}
 
-    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
-        return FALSE;
+static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
+{
+    static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
+    struct assembly_version *ver = &assembly->id.version;
+    WCHAR buff[25];
 
-    if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
-    if (end) return FALSE;
+    if (!ret) ret = buff;
+    return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
+}
 
-    if (!parse_text_content(xmlbuf, &content)) return FALSE;
+static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
+{
+    xmlstr_t elem, content, attr_name, attr_value;
+    BOOL end = FALSE, ret = TRUE, error;
+    struct entity*      entity;
+    UNICODE_STRING elemU, attr_nameU, attr_valueU;
 
-    if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
+    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
+        return FALSE;
 
-    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+    entity->u.class.versioned = TRUE;
+    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
     {
-        if (xmlstr_cmp_end(&elem, windowClassW))
+        if (xmlstr_cmp(&attr_name, versionedW))
+        {
+            if (xmlstr_cmpi(&attr_value, noW))
+                entity->u.class.versioned = FALSE;
+            else if (!xmlstr_cmpi(&attr_value, yesW))
+               return FALSE;
+        }
+        else
+        {
+            attr_nameU = xmlstr2unicode(&attr_name);
+            attr_valueU = xmlstr2unicode(&attr_value);
+            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
+        }
+    }
+
+    if (error || end) return end;
+
+    if (!parse_text_content(xmlbuf, &content)) return FALSE;
+
+    if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
+
+    acl->actctx->sections |= WINDOWCLASS_SECTION;
+
+    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+    {
+        if (xmlstr_cmp_end(&elem, windowClassW))
         {
             ret = parse_end_element(xmlbuf);
             break;
@@ -1211,7 +1922,8 @@ static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
 }
 
 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
-                                                         struct assembly* assembly)
+                                                         struct assembly* assembly,
+                                                         struct actctx_loader* acl)
 {
     xmlstr_t            attr_name, attr_value;
     UNICODE_STRING      attr_nameU, attr_valueU;
@@ -1225,11 +1937,29 @@ static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
     {
         if (xmlstr_cmp(&attr_name, iidW))
         {
-            if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+            if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
         }
-        if (xmlstr_cmp(&attr_name, g_nameW))
+        else if (xmlstr_cmp(&attr_name, g_nameW))
+        {
+            if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, baseInterfaceW))
+        {
+            if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
+            entity->u.ifaceps.mask |= BaseIface;
+        }
+        else if (xmlstr_cmp(&attr_name, nummethodsW))
+        {
+            if (!(parse_nummethods(&attr_value, entity))) return FALSE;
+            entity->u.ifaceps.mask |= NumMethods;
+        }
+        else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
+        {
+            if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, tlbidW))
         {
-            if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
+            if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
         }
         else
         {
@@ -1239,43 +1969,89 @@ static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
         }
     }
 
-    if (error || end) return end;
+    if (error) return FALSE;
+    acl->actctx->sections |= IFACEREDIRECT_SECTION;
+    if (end) return TRUE;
+
     return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
 }
 
-static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
 {
-    xmlstr_t    attr_name, attr_value;
-    UNICODE_STRING attr_nameU, attr_valueU;
-    BOOL        end = FALSE, error;
+    xmlstr_t    attr_name, attr_value, elem;
+    BOOL        end = FALSE, error, ret = TRUE;
     struct entity*      entity;
 
-    entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
+    entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
     if (!entity) return FALSE;
 
     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
     {
         if (xmlstr_cmp(&attr_name, g_nameW))
         {
-            if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
+            if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
         }
         else if (xmlstr_cmp(&attr_name, clsidW))
         {
-            if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+            if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, progidW))
+        {
+            if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, tlbidW))
+        {
+            if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
+        }
+        else if (xmlstr_cmp(&attr_name, threadingmodelW))
+        {
+            entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
+        }
+        else if (xmlstr_cmp(&attr_name, runtimeVersionW))
+        {
+            if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
         }
         else
         {
+            UNICODE_STRING attr_nameU, attr_valueU;
             attr_nameU = xmlstr2unicode(&attr_name);
             attr_valueU = xmlstr2unicode(&attr_value);
             DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
         }
     }
 
-    if (error || end) return end;
-    return parse_expect_end_elem(xmlbuf, clrClassW, asmv1W);
+    if (error) return FALSE;
+    acl->actctx->sections |= SERVERREDIRECT_SECTION;
+    if (entity->u.comclass.progid)
+        acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+    if (end) return TRUE;
+
+    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+    {
+        if (xmlstr_cmp_end(&elem, clrClassW))
+        {
+            ret = parse_end_element(xmlbuf);
+            break;
+        }
+        else if (xmlstr_cmp(&elem, progidW))
+        {
+            ret = parse_com_class_progid(xmlbuf, entity);
+        }
+        else
+        {
+            UNICODE_STRING elemU = xmlstr2unicode(&elem);
+            DPRINT1("unknown elem %wZ\n", &elemU);
+            ret = parse_unknown_elem(xmlbuf, &elem);
+        }
+    }
+
+    if (entity->u.comclass.progids.num)
+        acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
+    return ret;
 }
 
-static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
 {
     xmlstr_t    attr_name, attr_value;
     UNICODE_STRING attr_nameU, attr_valueU;
@@ -1295,6 +2071,10 @@ static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly
         {
             if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
         }
+        else if (xmlstr_cmp(&attr_name, runtimeVersionW))
+        {
+            if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
+        }
         else
         {
             attr_nameU = xmlstr2unicode(&attr_name);
@@ -1303,7 +2083,10 @@ static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly
         }
     }
 
-    if (error || end) return end;
+    if (error) return FALSE;
+    acl->actctx->sections |= CLRSURROGATES_SECTION;
+    if (end) return TRUE;
+
     return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
 }
 
@@ -1322,6 +2105,8 @@ static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader
         !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
         return FALSE;
 
+    //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
+
     /* store the newly found identity for later loading */
     if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
 
@@ -1359,7 +2144,6 @@ static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
 
         if (xmlstr_cmp(&attr_name, optionalW))
         {
-            static const WCHAR yesW[] = {'y','e','s',0};
             optional = xmlstr_cmpi( &attr_value, yesW );
             DPRINT1("optional=%wZ\n", &attr_valueU);
         }
@@ -1407,7 +2191,7 @@ static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
     return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
 }
 
-static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
 {
     xmlstr_t    attr_name, attr_value, elem;
     UNICODE_STRING attr_nameU, attr_valueU;
@@ -1443,6 +2227,9 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
     }
 
     if (error || !dll->name) return FALSE;
+
+    acl->actctx->sections |= DLLREDIRECT_SECTION;
+
     if (end) return TRUE;
 
     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
@@ -1454,24 +2241,24 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
         }
         else if (xmlstr_cmp(&elem, comClassW))
         {
-            ret = parse_com_class_elem(xmlbuf, dll);
+            ret = parse_com_class_elem(xmlbuf, dll, acl);
         }
         else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
         {
-            ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
+            ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
         }
-        else if (xmlstr_cmp(&elem, asmv2hashW))
+        else if (xml_elem_cmp(&elem, hashW, asmv2W))
         {
             DPRINT1("asmv2hash (undocumented) not supported\n");
             ret = parse_unknown_elem(xmlbuf, &elem);
         }
         else if (xmlstr_cmp(&elem, typelibW))
         {
-            ret = parse_typelib_elem(xmlbuf, dll);
+            ret = parse_typelib_elem(xmlbuf, dll, acl);
         }
         else if (xmlstr_cmp(&elem, windowClassW))
         {
-            ret = parse_window_class_elem(xmlbuf, dll);
+            ret = parse_window_class_elem(xmlbuf, dll, acl);
         }
         else
         {
@@ -1492,6 +2279,8 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
     UNICODE_STRING attr_nameU, attr_valueU;
     BOOL        end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
 
+    DPRINT("(%p)\n", xmlbuf);
+
     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
     {
         attr_nameU = xmlstr2unicode(&attr_name);
@@ -1532,7 +2321,7 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
         assembly->no_inherit = TRUE;
     }
 
-    if (xmlstr_cmp(&elem, noInheritableW))
+    if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
     {
         if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
             return FALSE;
@@ -1543,36 +2332,36 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
 
     while (ret)
     {
-        if (xmlstr_cmp_end(&elem, assemblyW))
+        if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
         {
             ret = parse_end_element(xmlbuf);
             break;
         }
-        else if (xmlstr_cmp(&elem, descriptionW))
+        else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
         {
             ret = parse_description_elem(xmlbuf);
         }
-        else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW))
+        else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
         {
-            ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
+            ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
         }
-        else if (xmlstr_cmp(&elem, dependencyW))
+        else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
         {
             ret = parse_dependency_elem(xmlbuf, acl);
         }
-        else if (xmlstr_cmp(&elem, fileW))
+        else if (xml_elem_cmp(&elem, fileW, asmv1W))
         {
-            ret = parse_file_elem(xmlbuf, assembly);
+            ret = parse_file_elem(xmlbuf, assembly, acl);
         }
-        else if (xmlstr_cmp(&elem, clrClassW))
+        else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
         {
-            ret = parse_clr_class_elem(xmlbuf, assembly);
+            ret = parse_clr_class_elem(xmlbuf, assembly, acl);
         }
-        else if (xmlstr_cmp(&elem, clrSurrogateW))
+        else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
         {
-            ret = parse_clr_surrogate_elem(xmlbuf, assembly);
+            ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
         }
-        else if (xmlstr_cmp(&elem, assemblyIdentityW))
+        else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
         {
             if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
 
@@ -1625,7 +2414,7 @@ static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembl
         (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
         return STATUS_SXS_CANT_GEN_ACTCTX;
 
-    if (!xmlstr_cmp(&elem, assemblyW))
+    if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
     {
         elemU = xmlstr2unicode(&elem);
         DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
@@ -2220,7 +3009,10 @@ static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
         {
             if (!acl->dependencies[i].optional)
             {
-                DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
+                const struct assembly_version *ver = &acl->dependencies[i].version;
+                DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
+                    acl->dependencies[i].name,
+                    ver->major, ver->minor, ver->build, ver->revision );
                 status = STATUS_SXS_CANT_GEN_ACTCTX;
                 break;
             }
@@ -2266,44 +3058,244 @@ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
     return status;
 }
 
-static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
+static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
+{
+    unsigned int i, j, total_len = 0, dll_count = 0;
+    struct strsection_header *header;
+    struct dllredirect_data *data;
+    struct string_index *index;
+    ULONG name_offset;
+
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+
+            /* each entry needs index, data and string data */
+            total_len += sizeof(*index);
+            total_len += sizeof(*data);
+            total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
+        }
+
+        dll_count += assembly->num_dlls;
+    }
+
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = STRSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = dll_count;
+    header->index_offset = sizeof(*header);
+    index = (struct string_index*)((BYTE*)header + header->index_offset);
+    name_offset = header->index_offset + header->count*sizeof(*index);
+
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            UNICODE_STRING str;
+            WCHAR *ptrW;
+
+            /* setup new index entry */
+            str.Buffer = dll->name;
+            str.Length = strlenW(dll->name)*sizeof(WCHAR);
+            str.MaximumLength = str.Length + sizeof(WCHAR);
+            /* hash original class name */
+            RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
+
+            index->name_offset = name_offset;
+            index->name_len = str.Length;
+            index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
+            index->data_len = sizeof(*data);
+            index->rosterindex = i + 1;
+
+            /* setup data */
+            data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
+            data->size = sizeof(*data);
+            data->unk = 2; /* FIXME: seems to be constant */
+            memset(data->res, 0, sizeof(data->res));
+
+            /* dll name */
+            ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
+            memcpy(ptrW, dll->name, index->name_len);
+            ptrW[index->name_len/sizeof(WCHAR)] = 0;
+
+            name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
+
+            index++;
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
+{
+    struct string_index *iter, *index = NULL;
+    ULONG hash = 0, i;
+
+    RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
+    iter = (struct string_index*)((BYTE*)section + section->index_offset);
+
+    for (i = 0; i < section->count; i++)
+    {
+        if (iter->hash == hash)
+        {
+            const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
+
+            if (!strcmpiW(nameW, name->Buffer))
+            {
+                index = iter;
+                break;
+            }
+            else
+                DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
+        }
+        iter++;
+    }
+
+    return index;
+}
+
+static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
+{
+    struct guid_index *iter, *index = NULL;
+    ULONG i;
+
+    iter = (struct guid_index*)((BYTE*)section + section->index_offset);
+
+    for (i = 0; i < section->count; i++)
+    {
+        if (!memcmp(guid, &iter->guid, sizeof(*guid)))
+        {
+            index = iter;
+            break;
+        }
+        iter++;
+    }
+
+    return index;
+}
+
+static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
+{
+    return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
+}
+
+static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+                                     PACTCTX_SECTION_KEYED_DATA data)
 {
+    struct dllredirect_data *dll;
+    struct string_index *index;
+
+    if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->dllredirect_section)
+    {
+        struct strsection_header *section;
+
+        NTSTATUS status = build_dllredirect_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_string_index(actctx->dllredirect_section, name);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    dll = get_dllredirect_data(actctx, index);
+
     data->ulDataFormatVersion = 1;
-    data->lpData = v1;
-    data->ulLength = 20; /* FIXME */
-    data->lpSectionGlobalData = NULL; /* FIXME */
-    data->ulSectionGlobalDataLength = 0; /* FIXME */
-    data->lpSectionBase = v2;
-    data->ulSectionTotalLength = 0; /* FIXME */
+    data->lpData = dll;
+    data->ulLength = dll->size;
+    data->lpSectionGlobalData = NULL;
+    data->ulSectionGlobalDataLength = 0;
+    data->lpSectionBase = actctx->dllredirect_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
     data->hActCtx = NULL;
-    if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
-        data->ulAssemblyRosterIndex = i + 1;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
 
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
-                                     PACTCTX_SECTION_KEYED_DATA data)
+static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
+{
+    return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
+}
+
+static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
+{
+    return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
+}
+
+static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
 {
-    unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
+    unsigned int i, j, k, total_len = 0, class_count = 0;
+    struct wndclass_redirect_data *data;
+    struct strsection_header *header;
+    struct string_index *index;
+    ULONG name_offset;
 
+    /* compute section length */
     for (i = 0; i < actctx->num_assemblies; i++)
     {
         struct assembly *assembly = &actctx->assemblies[i];
         for (j = 0; j < assembly->num_dlls; j++)
         {
             struct dll_redirect *dll = &assembly->dlls[j];
-            if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
-                return fill_keyed_data(data, dll, assembly, i);
+            for (k = 0; k < dll->entities.num; k++)
+            {
+                struct entity *entity = &dll->entities.base[k];
+                if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
+                {
+                    int class_len = strlenW(entity->u.class.name) + 1;
+                    int len;
+
+                    /* each class entry needs index, data and string data */
+                    total_len += sizeof(*index);
+                    total_len += sizeof(*data);
+                    /* original name is stored separately */
+                    total_len += aligned_string_len(class_len*sizeof(WCHAR));
+                    /* versioned name and module name are stored one after another */
+                    if (entity->u.class.versioned)
+                        len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
+                    else
+                        len = class_len;
+                    len += strlenW(dll->name) + 1;
+                    total_len += aligned_string_len(len*sizeof(WCHAR));
+
+                    class_count++;
+                }
+            }
         }
     }
-    return STATUS_SXS_KEY_NOT_FOUND;
-}
 
-static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
-                                  PACTCTX_SECTION_KEYED_DATA data)
-{
-    unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = STRSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = class_count;
+    header->index_offset = sizeof(*header);
+    index = (struct string_index*)((BYTE*)header + header->index_offset);
+    name_offset = header->index_offset + header->count*sizeof(*index);
 
     for (i = 0; i < actctx->num_assemblies; i++)
     {
@@ -2316,59 +3308,1248 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI
                 struct entity *entity = &dll->entities.base[k];
                 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
                 {
-                    if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
-                        return fill_keyed_data(data, entity, dll, i);
+                    static const WCHAR exclW[] = {'!',0};
+                    ULONG versioned_len, module_len;
+                    UNICODE_STRING str;
+                    WCHAR *ptrW;
+
+                    /* setup new index entry */
+                    str.Buffer = entity->u.class.name;
+                    str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
+                    str.MaximumLength = str.Length + sizeof(WCHAR);
+                    /* hash original class name */
+                    RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
+
+                    /* include '!' separator too */
+                    if (entity->u.class.versioned)
+                        versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
+                    else
+                        versioned_len = str.Length;
+                    module_len = strlenW(dll->name)*sizeof(WCHAR);
+
+                    index->name_offset = name_offset;
+                    index->name_len = str.Length;
+                    index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
+                    index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
+                    index->rosterindex = i + 1;
+
+                    /* setup data */
+                    data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
+                    data->size = sizeof(*data);
+                    data->res = 0;
+                    data->name_len = versioned_len;
+                    data->name_offset = sizeof(*data);
+                    data->module_len = module_len;
+                    data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
+
+                    /* original class name */
+                    ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
+                    memcpy(ptrW, entity->u.class.name, index->name_len);
+                    ptrW[index->name_len/sizeof(WCHAR)] = 0;
+
+                    /* module name */
+                    ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
+                    memcpy(ptrW, dll->name, data->module_len);
+                    ptrW[data->module_len/sizeof(WCHAR)] = 0;
+
+                    /* versioned name */
+                    ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+                    if (entity->u.class.versioned)
+                    {
+                        get_assembly_version(assembly, ptrW);
+                        strcatW(ptrW, exclW);
+                        strcatW(ptrW, entity->u.class.name);
+                    }
+                    else
+                    {
+                        memcpy(ptrW, entity->u.class.name, index->name_len);
+                        ptrW[index->name_len/sizeof(WCHAR)] = 0;
+                    }
+
+                    name_offset += sizeof(*data);
+                    name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
+
+                    index++;
                 }
             }
         }
     }
-    return STATUS_SXS_KEY_NOT_FOUND;
+
+    *section = header;
+
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
-                            const UNICODE_STRING *section_name,
-                            DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+                                  PACTCTX_SECTION_KEYED_DATA data)
 {
-    NTSTATUS status;
+    struct string_index *iter, *index = NULL;
+    struct wndclass_redirect_data *class;
+    ULONG hash;
+    int i;
 
-    switch (section_kind)
+    if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->wndclass_section)
     {
-    case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
-        status = find_dll_redirection(actctx, section_name, data);
-        break;
-    case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
-        status = find_window_class(actctx, section_name, data);
-        break;
-    case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
-    case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
-    case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
-    case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
-    case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
-    case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
-        DPRINT1("Unsupported yet section_kind %x\n", section_kind);
-        return STATUS_SXS_SECTION_NOT_FOUND;
-    default:
-        DPRINT1("Unknown section_kind %x\n", section_kind);
-        return STATUS_SXS_SECTION_NOT_FOUND;
+        struct strsection_header *section;
+
+        NTSTATUS status = build_wndclass_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
     }
 
-    if (status != STATUS_SUCCESS) return status;
+    hash = 0;
+    RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
+    iter = get_wndclass_first_index(actctx);
 
-    if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+    for (i = 0; i < actctx->wndclass_section->count; i++)
     {
-        actctx_addref(actctx);
-        data->hActCtx = actctx;
+        if (iter->hash == hash)
+        {
+            const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
+
+            if (!strcmpW(nameW, name->Buffer))
+            {
+                index = iter;
+                break;
+            }
+            else
+                DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
+        }
+        iter++;
     }
+
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    class = get_wndclass_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = class;
+    /* full length includes string length with nulls */
+    data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
+    data->lpSectionGlobalData = NULL;
+    data->ulSectionGlobalDataLength = 0;
+    data->lpSectionBase = actctx->wndclass_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
-                          const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
 {
-    NTSTATUS status;
+    unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
+    struct guidsection_header *header;
+    ULONG module_offset, data_offset;
+    struct tlibredirect_data *data;
+    struct guid_index *index;
 
-    switch (section_kind)
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            for (k = 0; k < dll->entities.num; k++)
+            {
+                struct entity *entity = &dll->entities.base[k];
+                if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
+                {
+                    /* each entry needs index, data and string data for module name and help string */
+                    total_len += sizeof(*index);
+                    total_len += sizeof(*data);
+                    /* help string is stored separately */
+                    if (*entity->u.typelib.helpdir)
+                        total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
+
+                    /* module names are packed one after another */
+                    names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
+
+                    tlib_count++;
+                }
+            }
+        }
+    }
+
+    total_len += aligned_string_len(names_len);
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = GUIDSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = tlib_count;
+    header->index_offset = sizeof(*header) + aligned_string_len(names_len);
+    index = (struct guid_index*)((BYTE*)header + header->index_offset);
+    module_offset = sizeof(*header);
+    data_offset = header->index_offset + tlib_count*sizeof(*index);
+
+    for (i = 0; i < actctx->num_assemblies; i++)
     {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            for (k = 0; k < dll->entities.num; k++)
+            {
+                struct entity *entity = &dll->entities.base[k];
+                if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
+                {
+                    ULONG module_len, help_len;
+                    UNICODE_STRING str;
+                    WCHAR *ptrW;
+
+                    if (*entity->u.typelib.helpdir)
+                        help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
+                    else
+                        help_len = 0;
+
+                    module_len = strlenW(dll->name)*sizeof(WCHAR);
+
+                    /* setup new index entry */
+                    RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
+                    RtlGUIDFromString(&str, &index->guid);
+                    index->data_offset = data_offset;
+                    index->data_len = sizeof(*data) + aligned_string_len(help_len);
+                    index->rosterindex = i + 1;
+
+                    /* setup data */
+                    data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
+                    data->size = sizeof(*data);
+                    data->res = 0;
+                    data->name_len = module_len;
+                    data->name_offset = module_offset;
+                    /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
+                    data->langid = 0;
+                    data->flags = entity->u.typelib.flags;
+                    data->help_len = help_len;
+                    data->help_offset = sizeof(*data);
+                    data->major_version = entity->u.typelib.major;
+                    data->minor_version = entity->u.typelib.minor;
+
+                    /* module name */
+                    ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
+                    memcpy(ptrW, dll->name, data->name_len);
+                    ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+                    /* help string */
+                    if (data->help_len)
+                    {
+                        ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
+                        memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
+                        ptrW[data->help_len/sizeof(WCHAR)] = 0;
+                    }
+
+                    data_offset += sizeof(*data);
+                    if (help_len)
+                        data_offset += aligned_string_len(help_len + sizeof(WCHAR));
+
+                    module_offset += module_len + sizeof(WCHAR);
+
+                    index++;
+                }
+            }
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+    return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
+}
+
+static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+    struct guid_index *index = NULL;
+    struct tlibredirect_data *tlib;
+
+    if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->tlib_section)
+    {
+        struct guidsection_header *section;
+
+        NTSTATUS status = build_tlib_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_guid_index(actctx->tlib_section, guid);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    tlib = get_tlib_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = tlib;
+    /* full length includes string length with nulls */
+    data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
+    data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
+    data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
+    data->lpSectionBase = actctx->tlib_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
+    return STATUS_SUCCESS;
+}
+
+static void generate_uuid(ULONG *seed, GUID *guid)
+{
+    ULONG *ptr = (ULONG*)guid;
+    int i;
+
+    /* GUID is 16 bytes long */
+    for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
+        *ptr = RtlUniform(seed);
+
+    guid->Data3 &= 0x0fff;
+    guid->Data3 |= (4 << 12);
+    guid->Data4[0] &= 0x3f;
+    guid->Data4[0] |= 0x80;
+}
+
+static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
+    unsigned int *count, unsigned int *len, unsigned int *module_len)
+{
+    unsigned int i;
+
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+        {
+            /* each entry needs two index entries, extra one goes for alias GUID */
+            *len += 2*sizeof(struct guid_index);
+            /* To save some memory we don't allocated two data structures,
+               instead alias index and normal index point to the same data structure. */
+            *len += sizeof(struct comclassredirect_data);
+
+            /* for clrClass store some more */
+            if (entity->u.comclass.name)
+            {
+                unsigned int str_len;
+
+                /* all string data is stored together in aligned block */
+                str_len = strlenW(entity->u.comclass.name)+1;
+                if (entity->u.comclass.progid)
+                    str_len += strlenW(entity->u.comclass.progid)+1;
+                if (entity->u.comclass.version)
+                    str_len += strlenW(entity->u.comclass.version)+1;
+
+                *len += sizeof(struct clrclass_data);
+                *len += aligned_string_len(str_len*sizeof(WCHAR));
+
+                /* module name is forced to mscoree.dll, and stored two times with different case */
+                *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
+            }
+            else
+            {
+                /* progid string is stored separately */
+                if (entity->u.comclass.progid)
+                    *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
+
+                *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
+            }
+
+            *count += 1;
+        }
+    }
+}
+
+static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
+    const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
+    ULONG *seed, ULONG rosterindex)
+{
+    unsigned int i;
+
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+        {
+            ULONG module_len, progid_len, str_len = 0;
+            struct comclassredirect_data *data;
+            struct guid_index *alias_index;
+            struct clrclass_data *clrdata;
+            UNICODE_STRING str;
+            WCHAR *ptrW;
+
+            if (entity->u.comclass.progid)
+                progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
+            else
+                progid_len = 0;
+
+            module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
+
+            /* setup new index entry */
+            RtlInitUnicodeString(&str, entity->u.comclass.clsid);
+            RtlGUIDFromString(&str, &(*index)->guid);
+
+            (*index)->data_offset = *data_offset;
+            (*index)->data_len = sizeof(*data); /* additional length added later */
+            (*index)->rosterindex = rosterindex;
+
+            /* Setup new index entry for alias guid. Alias index records are placed after
+               normal records, so normal guids are hit first on search. Note that class count
+               is doubled. */
+            alias_index = (*index) + section->count/2;
+            generate_uuid(seed, &alias_index->guid);
+            alias_index->data_offset = (*index)->data_offset;
+            alias_index->data_len = 0;
+            alias_index->rosterindex = (*index)->rosterindex;
+
+            /* setup data */
+            data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
+            data->size = sizeof(*data);
+            data->res = 0;
+            data->res1[0] = 0;
+            data->res1[1] = 0;
+            data->model = entity->u.comclass.model;
+            data->clsid = (*index)->guid;
+            data->alias = alias_index->guid;
+            data->clsid2 = data->clsid;
+            if (entity->u.comclass.tlbid)
+            {
+                RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
+                RtlGUIDFromString(&str, &data->tlbid);
+            }
+            else
+                memset(&data->tlbid, 0, sizeof(data->tlbid));
+            data->name_len = module_len;
+            data->name_offset = *module_offset;
+            data->progid_len = progid_len;
+            data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
+            data->clrdata_len = 0; /* will be set later */
+            data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
+            data->miscstatus = entity->u.comclass.miscstatus;
+            data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
+            data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
+            data->miscstatusicon = entity->u.comclass.miscstatusicon;
+            data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
+
+            /* mask describes which misc* data is available */
+            data->miscmask = 0;
+            if (data->miscstatus)
+                data->miscmask |= MiscStatus;
+            if (data->miscstatuscontent)
+                data->miscmask |= MiscStatusContent;
+            if (data->miscstatusthumbnail)
+                data->miscmask |= MiscStatusThumbnail;
+            if (data->miscstatusicon)
+                data->miscmask |= MiscStatusIcon;
+            if (data->miscstatusdocprint)
+                data->miscmask |= MiscStatusDocPrint;
+
+            if (data->clrdata_offset)
+            {
+                clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
+
+                clrdata->size = sizeof(*clrdata);
+                clrdata->res[0] = 0;
+                clrdata->res[1] = 2; /* FIXME: unknown field */
+                clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
+                clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
+                clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
+                clrdata->name_offset = clrdata->size;
+                clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
+                clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
+                clrdata->res2[0] = 0;
+                clrdata->res2[1] = 0;
+
+                data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
+
+                /* module name */
+                ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
+                memcpy(ptrW, mscoree2W, clrdata->module_len);
+                ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
+
+                ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
+                memcpy(ptrW, mscoreeW, data->name_len);
+                ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+                /* class name */
+                ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
+                memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
+                ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
+
+                /* runtime version, optional */
+                if (clrdata->version_len)
+                {
+                    data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
+
+                    ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
+                    memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
+                    ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
+                }
+
+                if (data->progid_len)
+                    data->progid_offset += data->clrdata_len;
+                (*index)->data_len += sizeof(*clrdata);
+            }
+            else
+            {
+                clrdata = NULL;
+
+                /* module name */
+                ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
+                memcpy(ptrW, dll->name, data->name_len);
+                ptrW[data->name_len/sizeof(WCHAR)] = 0;
+            }
+
+            /* progid string */
+            if (data->progid_len)
+            {
+                ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
+                memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
+                ptrW[data->progid_len/sizeof(WCHAR)] = 0;
+            }
+
+            /* string block length */
+            str_len = 0;
+            if (clrdata)
+            {
+                str_len += clrdata->name_len + sizeof(WCHAR);
+                if (clrdata->version_len)
+                    str_len += clrdata->version_len + sizeof(WCHAR);
+            }
+            if (progid_len)
+                str_len += progid_len + sizeof(WCHAR);
+
+            (*index)->data_len += aligned_string_len(str_len);
+            alias_index->data_len = (*index)->data_len;
+
+            /* move to next data record */
+            (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
+            (*module_offset) += module_len + sizeof(WCHAR);
+
+            if (clrdata)
+            {
+                (*data_offset) += sizeof(*clrdata);
+                (*module_offset) += clrdata->module_len + sizeof(WCHAR);
+            }
+            (*index) += 1;
+        }
+    }
+}
+
+static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+    unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
+    struct guidsection_header *header;
+    ULONG module_offset, data_offset;
+    struct guid_index *index;
+    ULONG seed;
+
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
+        }
+    }
+
+    total_len += aligned_string_len(names_len);
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = GUIDSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = 2*class_count;
+    header->index_offset = sizeof(*header) + aligned_string_len(names_len);
+    index = (struct guid_index*)((BYTE*)header + header->index_offset);
+    module_offset = sizeof(*header);
+    data_offset = header->index_offset + 2*class_count*sizeof(*index);
+
+    seed = NtGetTickCount();
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+    return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
+}
+
+static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+    struct comclassredirect_data *comclass;
+    struct guid_index *index = NULL;
+
+    if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->comserver_section)
+    {
+        struct guidsection_header *section;
+
+        NTSTATUS status = build_comserver_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_guid_index(actctx->comserver_section, guid);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    comclass = get_comclass_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = comclass;
+    /* full length includes string length with nulls */
+    data->ulLength = comclass->size + comclass->clrdata_len;
+    if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
+    data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
+    data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
+    data->lpSectionBase = actctx->comserver_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
+    return STATUS_SUCCESS;
+}
+
+static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
+{
+    unsigned int i;
+
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
+        {
+            *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
+            if (entity->u.ifaceps.name)
+                *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
+            *count += 1;
+        }
+    }
+}
+
+static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
+    struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
+{
+    unsigned int i;
+
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
+        {
+            struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
+            UNICODE_STRING str;
+            ULONG name_len;
+
+            if (entity->u.ifaceps.name)
+                name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
+            else
+                name_len = 0;
+
+            /* setup index */
+            RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
+            RtlGUIDFromString(&str, &(*index)->guid);
+            (*index)->data_offset = *data_offset;
+            (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
+            (*index)->rosterindex = rosterindex;
+
+            /* setup data record */
+            data->size = sizeof(*data);
+            data->mask = entity->u.ifaceps.mask;
+
+            /* proxyStubClsid32 value is only stored for external PS,
+               if set it's used as iid, otherwise 'iid' attribute value is used */
+            if (entity->u.ifaceps.ps32)
+            {
+                RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
+                RtlGUIDFromString(&str, &data->iid);
+            }
+            else
+                data->iid = (*index)->guid;
+
+            data->nummethods = entity->u.ifaceps.nummethods;
+
+            if (entity->u.ifaceps.tlib)
+            {
+                RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
+                RtlGUIDFromString(&str, &data->tlbid);
+            }
+            else
+                memset(&data->tlbid, 0, sizeof(data->tlbid));
+
+            if (entity->u.ifaceps.base)
+            {
+                RtlInitUnicodeString(&str, entity->u.ifaceps.base);
+                RtlGUIDFromString(&str, &data->base);
+            }
+            else
+                memset(&data->base, 0, sizeof(data->base));
+
+            data->name_len = name_len;
+            data->name_offset = data->name_len ? sizeof(*data) : 0;
+
+            /* name string */
+            if (data->name_len)
+            {
+                WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+                memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
+                ptrW[data->name_len/sizeof(WCHAR)] = 0;
+            }
+
+            /* move to next record */
+            (*index) += 1;
+            *data_offset += sizeof(*data);
+            if (data->name_len)
+                *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
+        }
+    }
+}
+
+static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+    unsigned int i, j, total_len = 0, count = 0;
+    struct guidsection_header *header;
+    struct guid_index *index;
+    ULONG data_offset;
+
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+
+        get_ifaceps_datalen(&assembly->entities, &count, &total_len);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            get_ifaceps_datalen(&dll->entities, &count, &total_len);
+        }
+    }
+
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = GUIDSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = count;
+    header->index_offset = sizeof(*header);
+    index = (struct guid_index*)((BYTE*)header + header->index_offset);
+    data_offset = header->index_offset + count*sizeof(*index);
+
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+
+        add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+    return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
+}
+
+static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+    struct ifacepsredirect_data *iface;
+    struct guid_index *index = NULL;
+
+    if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->ifaceps_section)
+    {
+        struct guidsection_header *section;
+
+        NTSTATUS status = build_ifaceps_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_guid_index(actctx->ifaceps_section, guid);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    iface = get_ifaceps_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = iface;
+    data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
+    data->lpSectionGlobalData = NULL;
+    data->ulSectionGlobalDataLength = 0;
+    data->lpSectionBase = actctx->ifaceps_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+    unsigned int i, j, total_len = 0, count = 0;
+    struct guidsection_header *header;
+    struct clrsurrogate_data *data;
+    struct guid_index *index;
+    ULONG data_offset;
+
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->entities.num; j++)
+        {
+            struct entity *entity = &assembly->entities.base[j];
+            if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
+            {
+                ULONG len;
+
+                total_len += sizeof(*index) + sizeof(*data);
+                len = strlenW(entity->u.clrsurrogate.name) + 1;
+                if (entity->u.clrsurrogate.version)
+                   len += strlenW(entity->u.clrsurrogate.version) + 1;
+                total_len += aligned_string_len(len*sizeof(WCHAR));
+
+                count++;
+            }
+        }
+    }
+
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = GUIDSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = count;
+    header->index_offset = sizeof(*header);
+    index = (struct guid_index*)((BYTE*)header + header->index_offset);
+    data_offset = header->index_offset + count*sizeof(*index);
+
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+        for (j = 0; j < assembly->entities.num; j++)
+        {
+            struct entity *entity = &assembly->entities.base[j];
+            if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
+            {
+                ULONG version_len, name_len;
+                UNICODE_STRING str;
+                WCHAR *ptrW;
+
+                if (entity->u.clrsurrogate.version)
+                    version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
+                else
+                    version_len = 0;
+                name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
+
+                /* setup new index entry */
+                RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
+                RtlGUIDFromString(&str, &index->guid);
+
+                index->data_offset = data_offset;
+                index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
+                index->rosterindex = i + 1;
+
+                /* setup data */
+                data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
+                data->size = sizeof(*data);
+                data->res = 0;
+                data->clsid = index->guid;
+                data->version_offset = version_len ? data->size : 0;
+                data->version_len = version_len;
+                data->name_offset = data->size + version_len;
+                if (version_len)
+                    data->name_offset += sizeof(WCHAR);
+                data->name_len = name_len;
+
+                /* surrogate name */
+                ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+                memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
+                ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+                /* runtime version */
+                if (data->version_len)
+                {
+                    ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
+                    memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
+                    ptrW[data->version_len/sizeof(WCHAR)] = 0;
+                }
+
+                data_offset += index->data_offset;
+                index++;
+            }
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
+{
+    return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
+}
+
+static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+    struct clrsurrogate_data *surrogate;
+    struct guid_index *index = NULL;
+
+    if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->clrsurrogate_section)
+    {
+        struct guidsection_header *section;
+
+        NTSTATUS status = build_clr_surrogate_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_guid_index(actctx->clrsurrogate_section, guid);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    surrogate = get_surrogate_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = surrogate;
+    /* full length includes string length with nulls */
+    data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
+    if (surrogate->version_len)
+        data->ulLength += surrogate->version_len + sizeof(WCHAR);
+
+    data->lpSectionGlobalData = NULL;
+    data->ulSectionGlobalDataLength = 0;
+    data->lpSectionBase = actctx->clrsurrogate_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
+    return STATUS_SUCCESS;
+}
+
+static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
+{
+    unsigned int i, j, single_len;
+
+    single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+        {
+            if (entity->u.comclass.progid)
+            {
+                *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
+                *count += 1;
+            }
+
+            for (j = 0; j < entity->u.comclass.progids.num; j++)
+                *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
+
+            *total_len += single_len*entity->u.comclass.progids.num;
+            *count += entity->u.comclass.progids.num;
+        }
+    }
+}
+
+static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
+    struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
+{
+    struct progidredirect_data *data;
+    UNICODE_STRING str;
+    GUID *guid_ptr;
+    WCHAR *ptrW;
+
+    /* setup new index entry */
+
+    /* hash progid name */
+    RtlInitUnicodeString(&str, progid);
+    RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
+
+    (*index)->name_offset = *data_offset;
+    (*index)->name_len = str.Length;
+    (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
+    (*index)->data_len = sizeof(*data);
+    (*index)->rosterindex = rosterindex;
+
+    *data_offset += aligned_string_len(str.MaximumLength);
+
+    /* setup data structure */
+    data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
+    data->size = sizeof(*data);
+    data->reserved = 0;
+    data->clsid_offset = *global_offset;
+
+    /* write progid string */
+    ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
+    memcpy(ptrW, progid, (*index)->name_len);
+    ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
+
+    /* write guid to global area */
+    guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
+    *guid_ptr = *alias;
+
+    /* to next entry */
+    *global_offset += sizeof(GUID);
+    *data_offset += data->size;
+    (*index) += 1;
+}
+
+static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
+    struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < entities->num; i++)
+    {
+        struct entity *entity = &entities->base[i];
+        if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+        {
+            const struct progids *progids = &entity->u.comclass.progids;
+            struct comclassredirect_data *comclass;
+            struct guid_index *guid_index;
+            UNICODE_STRING str;
+            GUID clsid;
+
+            RtlInitUnicodeString(&str, entity->u.comclass.clsid);
+            RtlGUIDFromString(&str, &clsid);
+
+            guid_index = find_guid_index(actctx->comserver_section, &clsid);
+            comclass = get_comclass_data(actctx, guid_index);
+
+            if (entity->u.comclass.progid)
+                write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
+                     index, data_offset, global_offset, rosterindex);
+
+            for (j = 0; j < progids->num; j++)
+                write_progid_record(section, progids->progids[j], &comclass->alias,
+                     index, data_offset, global_offset, rosterindex);
+        }
+    }
+}
+
+static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
+{
+    unsigned int i, j, total_len = 0, count = 0;
+    struct strsection_header *header;
+    ULONG data_offset, global_offset;
+    struct string_index *index;
+
+    /* compute section length */
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+
+        get_progid_datalen(&assembly->entities, &count, &total_len);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            get_progid_datalen(&dll->entities, &count, &total_len);
+        }
+    }
+
+    total_len += sizeof(*header);
+
+    header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+    if (!header) return STATUS_NO_MEMORY;
+
+    memset(header, 0, sizeof(*header));
+    header->magic = STRSECTION_MAGIC;
+    header->size  = sizeof(*header);
+    header->count = count;
+    header->global_offset = header->size;
+    header->global_len = count*sizeof(GUID);
+    header->index_offset = header->size + header->global_len;
+
+    index = (struct string_index*)((BYTE*)header + header->index_offset);
+    data_offset = header->index_offset + count*sizeof(*index);
+    global_offset = header->global_offset;
+
+    for (i = 0; i < actctx->num_assemblies; i++)
+    {
+        struct assembly *assembly = &actctx->assemblies[i];
+
+        add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
+        for (j = 0; j < assembly->num_dlls; j++)
+        {
+            struct dll_redirect *dll = &assembly->dlls[j];
+            add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
+        }
+    }
+
+    *section = header;
+
+    return STATUS_SUCCESS;
+}
+
+static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
+{
+    return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
+}
+
+static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+                                     PACTCTX_SECTION_KEYED_DATA data)
+{
+    struct progidredirect_data *progid;
+    struct string_index *index;
+
+    if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+    if (!actctx->comserver_section)
+    {
+        struct guidsection_header *section;
+
+        NTSTATUS status = build_comserver_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    if (!actctx->progid_section)
+    {
+        struct strsection_header *section;
+
+        NTSTATUS status = build_progid_section(actctx, &section);
+        if (status) return status;
+
+        if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
+            RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+    }
+
+    index = find_string_index(actctx->progid_section, name);
+    if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+    progid = get_progid_data(actctx, index);
+
+    data->ulDataFormatVersion = 1;
+    data->lpData = progid;
+    data->ulLength = progid->size;
+    data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
+    data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
+    data->lpSectionBase = actctx->progid_section;
+    data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
+    data->hActCtx = NULL;
+
+    if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+        data->ulAssemblyRosterIndex = index->rosterindex;
+
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+                            const UNICODE_STRING *section_name,
+                            DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+    NTSTATUS status;
+
+    switch (section_kind)
+    {
+    case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
+        status = find_dll_redirection(actctx, section_name, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
+        status = find_window_class(actctx, section_name, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
+        status = find_progid_redirection(actctx, section_name, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
+        DPRINT1("Unsupported yet section_kind %x\n", section_kind);
+        return STATUS_SXS_SECTION_NOT_FOUND;
+    default:
+        DPRINT1("Unknown section_kind %x\n", section_kind);
+        return STATUS_SXS_SECTION_NOT_FOUND;
+    }
+
+    if (status != STATUS_SUCCESS) return status;
+
+    if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+    {
+        actctx_addref(actctx);
+        data->hActCtx = actctx;
+    }
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+                          const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+    NTSTATUS status;
+
+    switch (section_kind)
+    {
+    case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
+        status = find_tlib_redirection(actctx, guid, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
+        status = find_comserver_redirection(actctx, guid, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
+        status = find_cominterface_redirection(actctx, guid, data);
+        break;
+    case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
+        status = find_clr_surrogate(actctx, guid, data);
+        break;
     default:
         DPRINT("Unknown section_kind %x\n", section_kind);
         return STATUS_SXS_SECTION_NOT_FOUND;
@@ -2946,10 +5127,10 @@ RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
 NTSTATUS
 NTAPI
 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
-                                                  UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
+                                                  const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
 {
     /* Check general parameter combinations */
-    if (!section_name ||
+    if (!section_name ||  !section_name->Buffer || 
         (flags & ~FIND_ACTCTX_VALID_MASK) ||
         ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
         (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
@@ -2972,7 +5153,7 @@ RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid,
 NTSTATUS
 NTAPI
 RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
-                                       UNICODE_STRING *section_name, PVOID ptr )
+                                       const UNICODE_STRING *section_name, PVOID ptr )
 {
     PACTCTX_SECTION_KEYED_DATA data = ptr;
     NTSTATUS status;
index 49a8fa1..ee892a0 100644 (file)
@@ -31,13 +31,12 @@ BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */
 PWCHAR NlsOemToUnicodeTable = NULL;
 PCHAR NlsUnicodeToOemTable =NULL;
 PWCHAR NlsDbcsUnicodeToOemTable = NULL;
-PUSHORT _NlsOemLeadByteInfo = NULL; /* exported */
+PUSHORT NlsOemLeadByteInfo = NULL; /* exported */
 
 USHORT NlsOemDefaultChar = '\0';
 USHORT NlsUnicodeDefaultChar = 0;
 
 
-#define NlsOemLeadByteInfo              _NlsOemLeadByteInfo
 #define INIT_FUNCTION
 
 /* FUNCTIONS *****************************************************************/
index 634357b..b9429af 100644 (file)
@@ -125,6 +125,11 @@ RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame,
 #define RtlpAllocateStringMemory RtlpAllocateMemory
 #define RtlpFreeStringMemory     RtlpFreeMemory
 
+ULONG
+NTAPI
+RtlGetTickCount(VOID);
+#define NtGetTickCount RtlGetTickCount
+
 BOOLEAN
 NTAPI
 RtlpSetInDbgPrint(
index ae741c5..526caa6 100644 (file)
@@ -13,4 +13,7 @@ DEFINE_ALIAS ??_L@YAXPEAX_KHP6AX0@Z2@Z, ?MSVCRTEX_eh_vector_constructor_iterator
 ; void __cdecl `eh vector destructor iterator'(void *,unsigned __int64,int,void (__cdecl*)(void *))
 DEFINE_ALIAS ??_M@YAXPEAX_KHP6AX0@Z@Z, ?MSVCRTEX_eh_vector_destructor_iterator@@YAXPEAX_KHP6AX0@Z@Z
 
+; These are the same
+DEFINE_ALIAS __CxxFrameHandler3, __CxxFrameHandler
+
 END
index ad948fe..ec5c930 100644 (file)
@@ -11,10 +11,12 @@ void _invalid_parameter(
    uintptr_t pReserved);
 
 #ifndef _LIBCNT_
-#define MSVCRT_INVALID_PMT(x) _invalid_parameter(NULL, NULL, NULL, 0, 0)
-#define MSVCRT_CHECK_PMT(x)   ((x) || (MSVCRT_INVALID_PMT(0),0))
+#define MSVCRT_INVALID_PMT(x,err)   (*_errno() = (err), _invalid_parameter(NULL, NULL, NULL, 0, 0))
+#define MSVCRT_CHECK_PMT_ERR(x,err) ((x) || (MSVCRT_INVALID_PMT( 0, (err) ), 0))
+#define MSVCRT_CHECK_PMT(x)         MSVCRT_CHECK_PMT_ERR((x), EINVAL)
 #else
 /* disable secure crt parameter checks */
-#define MSVCRT_CHECK_PMT
-#define MSVCRT_INVALID_PMT
+#define MSVCRT_INVALID_PMT(x,err)
+#define MSVCRT_CHECK_PMT_ERR(x,err)
+#define MSVCRT_CHECK_PMT(x) (x)
 #endif
index 57d7f4f..4666719 100644 (file)
@@ -104,7 +104,7 @@ _sxprintf(
         if (count != _TRUNCATE)
         {
             /* We can't, invoke invalid parameter handler */
-            MSVCRT_INVALID_PMT("Buffer is too small");
+            MSVCRT_INVALID_PMT("Buffer is too small", ERANGE);
 
             /* If we came back, set the buffer to an empty string */
             *buffer = 0;
index 52e7f09..0c7533e 100644 (file)
 int *__p__fmode(void);
 int *__p___mb_cur_max(void);
 
+extern int _commode;
+
+#ifndef _IOCOMMIT
+#define _IOCOMMIT 0x4000
+#endif
+
 #ifdef feof
 #undef feof
 #endif
@@ -83,21 +89,33 @@ int *__p___mb_cur_max(void);
 /* values for wxflag in file descriptor */
 #define WX_OPEN           0x01
 #define WX_ATEOF          0x02
+#define WX_READNL         0x04  /* read started with \n */
 #define WX_READEOF        0x04  /* like ATEOF, but for underlying file rather than buffer */
+#define WX_PIPE           0x08
 #define WX_READCR         0x08  /* underlying file is at \r */
 #define WX_DONTINHERIT    0x10
 #define WX_APPEND         0x20
+#define WX_NOSEEK         0x40
 #define WX_TEXT           0x80
 
+/* values for exflag - it's used differently in msvcr90.dll*/
+#define EF_UTF8           0x01
+#define EF_UTF16          0x02
+#define EF_UNK_UNICODE    0x08
+
+static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
+static char utf16_bom[2] = { 0xff, 0xfe };
+
 /* FIXME: this should be allocated dynamically */
 #define MAX_FILES 2048
 #define FD_BLOCK_SIZE 64
 
+/* ioinfo structure size is different in msvcrXX.dll's */
 typedef struct {
     HANDLE              handle;
     unsigned char       wxflag;
-    char                unk1;
-    BOOL                crit_init;
+    char                lookahead[3];
+    int                 exflag;
     CRITICAL_SECTION    crit;
 } ioinfo;
 
@@ -245,7 +263,7 @@ static void free_fd(int fd)
 
 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
 /* caller must hold the files lock */
-static int alloc_fd_from(HANDLE hand, int flag, int fd)
+static int set_fd(HANDLE hand, int flag, int fd)
 {
   ioinfo *fdinfo;
 
@@ -274,7 +292,11 @@ static int alloc_fd_from(HANDLE hand, int flag, int fd)
   }
 
   fdinfo->handle = hand;
-  fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT));
+  fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_NOSEEK));
+  fdinfo->lookahead[0] = '\n';
+  fdinfo->lookahead[1] = '\n';
+  fdinfo->lookahead[2] = '\n';
+  fdinfo->exflag = 0;
 
   /* locate next free slot */
   if (fd == fdstart && fd == fdend)
@@ -305,7 +327,7 @@ static int alloc_fd_from(HANDLE hand, int flag, int fd)
 
   LOCK_FILES();
   TRACE(":handle (%p) allocating fd (%d)\n",hand,fdstart);
-  ret = alloc_fd_from(hand, flag, fdstart);
+  ret = set_fd(hand, flag, fdstart);
   UNLOCK_FILES();
   return ret;
 }
@@ -425,7 +447,7 @@ void msvcrt_init_io(void)
     for (i = 0; i < count; i++)
     {
       if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
-        alloc_fd_from(*handle_ptr, *wxflag_ptr, i);
+        set_fd(*handle_ptr, *wxflag_ptr, i);
 
       wxflag_ptr++; handle_ptr++;
     }
@@ -435,7 +457,7 @@ void msvcrt_init_io(void)
   }
 
   if(!__pioinfo[0])
-      alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3);
+      set_fd(INVALID_HANDLE_VALUE, 0, 3);
 
   fdinfo = get_ioinfo(0);
   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
@@ -877,7 +899,7 @@ int CDECL _dup2(int od, int nd)
 
       if (is_valid_fd(nd))
         _close(nd);
-      ret = alloc_fd_from(handle, wxflag, nd);
+      ret = set_fd(handle, wxflag, nd);
       if (ret == -1)
       {
         CloseHandle(handle);
@@ -1238,6 +1260,10 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
 {
   int plus = strchrW(mode, '+') != NULL;
 
+  TRACE("%s\n", debugstr_w(mode));
+
+  while(*mode == ' ') mode++;
+
   switch(*mode++)
   {
   case 'R': case 'r':
@@ -1253,12 +1279,13 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
     *stream_flags = plus ? _IORW : _IOWRT;
     break;
   default:
-    _invalid_parameter(NULL, NULL, NULL, 0, 0);
-    *_errno() = EINVAL;
+    MSVCRT_INVALID_PMT(0, EINVAL);
     return -1;
   }
 
-  while (*mode)
+  *stream_flags |= _commode;
+
+  while (*mode && *mode!=',')
     switch (*mode++)
     {
     case 'B': case 'b':
@@ -1269,12 +1296,79 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
       *open_flags |=  _O_TEXT;
       *open_flags &= ~_O_BINARY;
       break;
+    case 'D':
+      *open_flags |= _O_TEMPORARY;
+      break;
+    case 'T':
+      *open_flags |= _O_SHORT_LIVED;
+      break;
+    case 'c':
+      *stream_flags |= _IOCOMMIT;
+      break;
+    case 'n':
+      *stream_flags &= ~_IOCOMMIT;
+      break;
+    case 'N':
+      *open_flags |= _O_NOINHERIT;
+      break;
     case '+':
     case ' ':
+    case 'a':
+    case 'w':
+      break;
+    case 'S':
+    case 'R':
+      FIXME("ignoring cache optimization flag: %c\n", mode[-1]);
       break;
     default:
-      FIXME(":unknown flag %c not supported\n",mode[-1]);
+      ERR("incorrect mode flag: %c\n", mode[-1]);
+      break;
+    }
+
+  if(*mode == ',')
+  {
+    static const WCHAR ccs[] = {'c','c','s'};
+    static const WCHAR utf8[] = {'u','t','f','-','8'};
+    static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'};
+    static const WCHAR unicode[] = {'u','n','i','c','o','d','e'};
+
+    mode++;
+    while(*mode == ' ') mode++;
+    if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0]))))
+      return -1;
+    mode += sizeof(ccs)/sizeof(ccs[0]);
+    while(*mode == ' ') mode++;
+    if(!MSVCRT_CHECK_PMT(*mode == '='))
+        return -1;
+    mode++;
+    while(*mode == ' ') mode++;
+
+    if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0])))
+    {
+      *open_flags |= _O_U8TEXT;
+      mode += sizeof(utf8)/sizeof(utf8[0]);
+    }
+    else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0])))
+    {
+      *open_flags |= _O_U16TEXT;
+      mode += sizeof(utf16le)/sizeof(utf16le[0]);
     }
+    else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0])))
+    {
+      *open_flags |= _O_WTEXT;
+      mode += sizeof(unicode)/sizeof(unicode[0]);
+    }
+    else
+    {
+      MSVCRT_INVALID_PMT(0, EINVAL);
+      return -1;
+    }
+
+    while(*mode == ' ') mode++;
+  }
+
+  if(!MSVCRT_CHECK_PMT(*mode == 0))
+    return -1;
   return 0;
 }
 
@@ -1400,9 +1494,12 @@ char * CDECL _mktemp(char *pattern)
   int id;
   char letter = 'a';
 
+  if(!pattern)
+      return NULL;
+
   while(*pattern)
     numX = (*pattern++ == 'X')? numX + 1 : 0;
-  if (numX < 5)
+  if (numX < 6)
     return NULL;
   pattern--;
   id = GetCurrentProcessId();
@@ -1417,8 +1514,7 @@ char * CDECL _mktemp(char *pattern)
   do
   {
     *pattern = letter++;
-    if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES &&
-        GetLastError() == ERROR_FILE_NOT_FOUND)
+    if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES)
       return retVal;
   } while(letter <= 'z');
   return NULL;
@@ -1537,26 +1633,44 @@ int CDECL _pipe(int *pfds, unsigned int psize, int textmode)
   return ret;
 }
 
+static int check_bom(HANDLE h, int oflags, BOOL seek)
+{
+    char bom[sizeof(utf8_bom)];
+    DWORD r;
+
+    oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
+
+    if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
+        return oflags;
+
+    if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
+        oflags |= _O_U8TEXT;
+    }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
+        if (seek && r>2)
+            SetFilePointer(h, 2, NULL, FILE_BEGIN);
+        oflags |= _O_U16TEXT;
+    }else if (seek) {
+        SetFilePointer(h, 0, NULL, FILE_BEGIN);
+    }
+
+    return oflags;
+}
+
 /*********************************************************************
- *              _sopen_s (MSVCRT.@)
+ *              _wsopen_s (MSVCRT.@)
  */
-int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
+int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode )
 {
   DWORD access = 0, creation = 0, attrib;
+  SECURITY_ATTRIBUTES sa;
   DWORD sharing;
   int wxflag;
   HANDLE hand;
-  SECURITY_ATTRIBUTES sa;
 
-  TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
-        fd, path, oflags, shflags, pmode);
+  TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
+        fd, debugstr_w(path), oflags, shflags, pmode);
 
-  if (!fd)
-  {
-    MSVCRT_INVALID_PMT("null out fd pointer");
-    *_errno() = EINVAL;
-    return EINVAL;
-  }
+  if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL;
 
   *fd = -1;
   wxflag = split_oflags(oflags);
@@ -1618,25 +1732,89 @@ int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmod
 
   sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
   sa.lpSecurityDescriptor = NULL;
-  sa.bInheritHandle       = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
+  sa.bInheritHandle       = !(oflags & _O_NOINHERIT);
 
-  hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
+  if ((oflags&(_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
+          && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
+          && !(access&GENERIC_READ))
+  {
+      hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+              &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+      if (hand != INVALID_HANDLE_VALUE)
+      {
+          oflags = check_bom(hand, oflags, FALSE);
+          CloseHandle(hand);
+      }
+      else
+          oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
+  }
+
+  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
   if (hand == INVALID_HANDLE_VALUE)  {
-    WARN(":failed-last error (%d)\n", GetLastError());
+    WARN(":failed-last error (%d)\n",GetLastError());
     _dosmaperr(GetLastError());
     return *_errno();
   }
 
+  if (oflags & (_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
+  {
+      if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
+                  || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
+                  || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
+      {
+          if (oflags & _O_U8TEXT)
+          {
+              DWORD written = 0, tmp;
+
+              while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
+                          sizeof(utf8_bom)-written, &tmp, NULL))
+                  written += tmp;
+              if (written != sizeof(utf8_bom)) {
+                  WARN("error writing BOM\n");
+                  CloseHandle(hand);
+                  _dosmaperr(GetLastError());
+                  return *_errno();
+              }
+          }
+          else
+          {
+              DWORD written = 0, tmp;
+
+              while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
+                          sizeof(utf16_bom)-written, &tmp, NULL))
+                  written += tmp;
+              if (written != sizeof(utf16_bom))
+              {
+                  WARN("error writing BOM\n");
+                  CloseHandle(hand);
+                  _dosmaperr(GetLastError());
+                  return *_errno();
+              }
+          }
+      }
+      else if (access & GENERIC_READ)
+          oflags = check_bom(hand, oflags, TRUE);
+  }
+
   *fd = alloc_fd(hand, wxflag);
+  if (*fd == -1)
+      return *_errno();
+
+  if (oflags & _O_WTEXT)
+      get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
+  else if (oflags & _O_U16TEXT)
+      get_ioinfo(*fd)->exflag |= EF_UTF16;
+  else if (oflags & _O_U8TEXT)
+      get_ioinfo(*fd)->exflag |= EF_UTF8;
 
   TRACE(":fd (%d) handle (%p)\n", *fd, hand);
   return 0;
 }
 
 /*********************************************************************
- *              _sopen (MSVCRT.@)
+ *              _wsopen (MSVCRT.@)
  */
-int CDECL _sopen( const char *path, int oflags, int shflags, ... )
+int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
 {
   int pmode;
   int fd;
@@ -1652,28 +1830,27 @@ int CDECL _sopen( const char *path, int oflags, int shflags, ... )
   else
     pmode = 0;
 
-  _sopen_s(&fd, path, oflags, shflags, pmode);
+  _wsopen_s(&fd, path, oflags, shflags, pmode);
   return fd;
 }
 
 /*********************************************************************
- *              _wsopen_s (MSVCRT.@)
+ *              _sopen_s (MSVCRT.@)
  */
-int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode )
+int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
 {
   DWORD access = 0, creation = 0, attrib;
-  SECURITY_ATTRIBUTES sa;
   DWORD sharing;
   int wxflag;
   HANDLE hand;
+  SECURITY_ATTRIBUTES sa;
 
-  TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
-        fd, debugstr_w(path), oflags, shflags, pmode);
+  TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
+        fd, path, oflags, shflags, pmode);
 
   if (!fd)
   {
-    MSVCRT_INVALID_PMT("null out fd pointer");
-    *_errno() = EINVAL;
+    MSVCRT_INVALID_PMT("null out fd pointer", EINVAL);
     return EINVAL;
   }
 
@@ -1739,10 +1916,9 @@ int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int
   sa.lpSecurityDescriptor = NULL;
   sa.bInheritHandle       = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
 
-  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
-
+  hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
   if (hand == INVALID_HANDLE_VALUE)  {
-    WARN(":failed-last error (%d)\n",GetLastError());
+    WARN(":failed-last error (%d)\n", GetLastError());
     _dosmaperr(GetLastError());
     return *_errno();
   }
@@ -1754,9 +1930,9 @@ int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int
 }
 
 /*********************************************************************
- *              _wsopen (MSVCRT.@)
+ *              _sopen (MSVCRT.@)
  */
-int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
+int CDECL _sopen( const char *path, int oflags, int shflags, ... )
 {
   int pmode;
   int fd;
@@ -1772,7 +1948,7 @@ int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
   else
     pmode = 0;
 
-  _wsopen_s(&fd, path, oflags, shflags, pmode);
+  _sopen_s(&fd, path, oflags, shflags, pmode);
   return fd;
 }
 
@@ -1837,6 +2013,7 @@ int CDECL _wcreat(const wchar_t *path, int flags)
  */
 int CDECL _open_osfhandle(intptr_t handle, int oflags)
 {
+  DWORD flags;
   int fd;
 
   /* _O_RDONLY (0) always matches, so set the read flag
@@ -1848,8 +2025,23 @@ int CDECL _open_osfhandle(intptr_t handle, int oflags)
   if (!(oflags & (_O_BINARY | _O_TEXT)))
       oflags |= _O_BINARY;
 
-  fd = alloc_fd((HANDLE)handle, split_oflags(oflags));
-  TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags);
+  flags = GetFileType((HANDLE)handle);
+  if (flags==FILE_TYPE_UNKNOWN && GetLastError()!=NO_ERROR)
+  {
+    _dosmaperr(GetLastError());
+    return -1;
+  }
+
+  if (flags == FILE_TYPE_CHAR)
+    flags = WX_NOSEEK;
+  else if (flags == FILE_TYPE_PIPE)
+    flags = WX_PIPE;
+  else
+    flags = 0;
+  flags |= split_oflags(oflags);
+
+  fd = alloc_fd((HANDLE)handle, flags);
+  TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, flags);
   return fd;
 }
 
@@ -1989,14 +2181,32 @@ int CDECL _read(int fd, void *buf, unsigned int count)
  */
 int CDECL _setmode(int fd,int mode)
 {
-  int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
-  if (mode & (~(_O_TEXT|_O_BINARY)))
-    FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode);
-  if ((mode & _O_TEXT) == _O_TEXT)
+    int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
+    if(ret==_O_TEXT && (get_ioinfo(fd)->exflag & (EF_UTF8|EF_UTF16)))
+        ret = _O_WTEXT;
+
+    if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT
+                && mode!=_O_U16TEXT && mode!=_O_U8TEXT) {
+        *_errno() = EINVAL;
+        return -1;
+    }
+
+    if(mode == _O_BINARY) {
+        get_ioinfo(fd)->wxflag &= ~WX_TEXT;
+        get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
+        return ret;
+    }
+
     get_ioinfo(fd)->wxflag |= WX_TEXT;
-  else
-    get_ioinfo(fd)->wxflag &= ~WX_TEXT;
-  return ret;
+    if(mode == _O_TEXT)
+        get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
+    else if(mode == _O_U8TEXT)
+        get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF16) | EF_UTF8;
+    else
+        get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF8) | EF_UTF16;
+
+    return ret;
+
 }
 
 /*********************************************************************
@@ -2070,89 +2280,170 @@ int CDECL _umask(int umask)
  */
 int CDECL _write(int fd, const void* buf, unsigned int count)
 {
-  DWORD num_written;
-  HANDLE hand = fdtoh(fd);
+    DWORD num_written;
+    ioinfo *info = get_ioinfo(fd);
+    HANDLE hand = info->handle;
 
-  /* Don't trace small writes, it gets *very* annoying */
+    /* Don't trace small writes, it gets *very* annoying */
 #if 0
-  if (count > 32)
-    TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
+    if (count > 32)
+        TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
 #endif
-  if (hand == INVALID_HANDLE_VALUE)
+    if (hand == INVALID_HANDLE_VALUE)
     {
-      *_errno() = EBADF;
-      return -1;
+        *_errno() = EBADF;
+        return -1;
     }
 
-  /* If appending, go to EOF */
-  if (get_ioinfo(fd)->wxflag & WX_APPEND)
-    _lseek(fd, 0, FILE_END);
+    if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
+    {
+        *_errno() = EINVAL;
+        return -1;
+    }
 
-  if (!(get_ioinfo(fd)->wxflag & WX_TEXT))
+    /* If appending, go to EOF */
+    if (info->wxflag & WX_APPEND)
+        _lseek(fd, 0, FILE_END);
+
+    if (!(info->wxflag & WX_TEXT))
     {
-      if (WriteFile(hand, buf, count, &num_written, NULL)
-         &&  (num_written == count))
-       return num_written;
-      TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
-       hand, GetLastError());
-      *_errno() = ENOSPC;
+        if (WriteFile(hand, buf, count, &num_written, NULL)
+                &&  (num_written == count))
+            return num_written;
+        TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
+                hand, GetLastError());
+        *_errno() = ENOSPC;
     }
-  else
-  {
-      unsigned int i, j, nr_lf;
-      char *p = NULL;
-      const char *q;
-      const char *s = buf, *buf_start = buf;
-      /* find number of \n ( without preceding \r ) */
-      for ( nr_lf=0,i = 0; i <count; i++)
-      {
-          if (s[i]== '\n')
-          {
-              nr_lf++;
-              /*if ((i >1) && (s[i-1] == '\r'))        nr_lf--; */
-          }
-      }
-      if (nr_lf)
-      {
-          if ((q = p = malloc(count + nr_lf)))
-          {
-              for (s = buf, i = 0, j = 0; i < count; i++)
-              {
-                  if (s[i]== '\n')
-                  {
-                      p[j++] = '\r';
-                      /*if ((i >1) && (s[i-1] == '\r'))j--;*/
-                  }
-                  p[j++] = s[i];
-              }
-          }
-          else
-          {
-              FIXME("Malloc failed\n");
-              nr_lf =0;
-              q = buf;
-          }
-      }
-      else
-          q = buf;
+    else
+    {
+        unsigned int i, j, nr_lf, size;
+        char *p = NULL;
+        const char *q;
+        const char *s = buf, *buf_start = buf;
 
-      if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf))
-      {
-          TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
-           fd, hand, GetLastError(), num_written);
-          *_errno() = ENOSPC;
-          if(nr_lf)
-              free(p);
-          return s - buf_start;
-      }
-      else
-      {
-          if(nr_lf)
-              free(p);
-          return count;
-      }
-  }
-  return -1;
+        if (!(info->exflag & (EF_UTF8|EF_UTF16)))
+        {
+            /* find number of \n */
+            for (nr_lf=0, i=0; i<count; i++)
+                if (s[i] == '\n')
+                    nr_lf++;
+            if (nr_lf)
+            {
+                size = count+nr_lf;
+                if ((q = p = malloc(size)))
+                {
+                    for (s = buf, i = 0, j = 0; i < count; i++)
+                    {
+                        if (s[i] == '\n')
+                            p[j++] = '\r';
+                        p[j++] = s[i];
+                    }
+                }
+                else
+                {
+                    FIXME("Malloc failed\n");
+                    nr_lf = 0;
+                    size = count;
+                    q = buf;
+                }
+            }
+            else
+            {
+                size = count;
+                q = buf;
+            }
+        }
+        else if (info->exflag & EF_UTF16)
+        {
+            for (nr_lf=0, i=0; i<count; i+=2)
+                if (s[i]=='\n' && s[i+1]==0)
+                    nr_lf += 2;
+            if (nr_lf)
+            {
+                size = count+nr_lf;
+                if ((q = p = malloc(size)))
+                {
+                    for (s=buf, i=0, j=0; i<count; i++)
+                    {
+                        if (s[i]=='\n' && s[i+1]==0)
+                        {
+                            p[j++] = '\r';
+                            p[j++] = 0;
+                        }
+                        p[j++] = s[i++];
+                        p[j++] = s[i];
+                    }
+                }
+                else
+                {
+                    FIXME("Malloc failed\n");
+                    nr_lf = 0;
+                    size = count;
+                    q = buf;
+                }
+            }
+            else
+            {
+                size = count;
+                q = buf;
+            }
+        }
+        else
+        {
+            DWORD conv_len;
+
+            for(nr_lf=0, i=0; i<count; i+=2)
+                if (s[i]=='\n' && s[i+1]==0)
+                    nr_lf++;
+
+            conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
+            if(!conv_len) {
+                _dosmaperr(GetLastError());
+                free(p);
+                return -1;
+            }
+
+            size = conv_len+nr_lf;
+            if((p = malloc(count+nr_lf*2+size)))
+            {
+                for (s=buf, i=0, j=0; i<count; i++)
+                {
+                    if (s[i]=='\n' && s[i+1]==0)
+                    {
+                        p[j++] = '\r';
+                        p[j++] = 0;
+                    }
+                    p[j++] = s[i++];
+                    p[j++] = s[i];
+                }
+                q = p+count+nr_lf*2;
+                WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
+                        p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
+            }
+            else
+            {
+                FIXME("Malloc failed\n");
+                nr_lf = 0;
+                size = count;
+                q = buf;
+            }
+        }
+
+        if (!WriteFile(hand, q, size, &num_written, NULL))
+            num_written = -1;
+        if(p)
+            free(p);
+        if (num_written != size)
+        {
+            TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
+                    fd, hand, GetLastError(), num_written);
+            *_errno() = ENOSPC;
+            return s - buf_start;
+        }
+        return count;
+    }
+
+    return -1;
 }
 
 /*********************************************************************
@@ -2213,13 +2504,7 @@ int CDECL fclose(FILE* file)
  */
 int CDECL feof(FILE* file)
 {
-    int ret;
-
-    _lock_file(file);
-    ret = file->_flag & _IOEOF;
-    _unlock_file(file);
-
-    return ret;
+    return file->_flag & _IOEOF;
 }
 
 /*********************************************************************
@@ -2227,13 +2512,7 @@ int CDECL feof(FILE* file)
  */
 int CDECL ferror(FILE* file)
 {
-    int ret;
-
-    _lock_file(file);
-    ret = file->_flag & _IOERR;
-    _unlock_file(file);
-
-    return ret;
+    return file->_flag & _IOERR;
 }
 
 /*********************************************************************
@@ -2244,6 +2523,11 @@ int CDECL _filbuf(FILE* file)
     unsigned char c;
     _lock_file(file);
 
+    if(file->_flag & _IOSTRG) {
+        _unlock_file(file);
+        return EOF;
+    }
+
     /* Allocate buffer if needed */
     if(file->_bufsiz == 0 && !(file->_flag & _IONBF))
         alloc_buffer(file);
@@ -2494,33 +2778,36 @@ size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file)
         return 0;
 
     _lock_file(file);
-    if(file->_cnt) {
-        int pcnt=((unsigned)file->_cnt>wrcnt)? wrcnt: file->_cnt;
-        memcpy(file->_ptr, ptr, pcnt);
-        file->_cnt -= pcnt;
-        file->_ptr += pcnt;
-        written = pcnt;
-        wrcnt -= pcnt;
-        ptr = (const char*)ptr + pcnt;
-    } else if(!(file->_flag & _IOWRT)) {
-        if(file->_flag & _IORW) {
-            file->_flag |= _IOWRT;
-        } else {
-            _unlock_file(file);
-            return 0;
-        }
-    }
-    if(wrcnt) {
-        /* Flush buffer */
-        int res=flush_buffer(file);
-        if(!res) {
-            int pwritten = _write(file->_file, ptr, wrcnt);
-            if (pwritten <= 0)
-            {
+
+    while(wrcnt) {
+        if(file->_cnt) {
+            int pcnt=((unsigned)file->_cnt>wrcnt)? wrcnt: file->_cnt;
+            memcpy(file->_ptr, ptr, pcnt);
+            file->_cnt -= pcnt;
+            file->_ptr += pcnt;
+            written += pcnt;
+            wrcnt -= pcnt;
+            ptr = (const char*)ptr + pcnt;
+        } else if(!file->_bufsiz && (file->_flag & _IONBF)) {
+            if(!(file->_flag & _IOWRT)) {
+                if(file->_flag & _IORW)
+                    file->_flag |= _IOWRT;
+                else
+                    break;
+            }
+
+            if(_write(file->_file, ptr, wrcnt) <= 0) {
                 file->_flag |= _IOERR;
-                pwritten=0;
+                break;
             }
-            written += pwritten;
+            written += wrcnt;
+            wrcnt = 0;
+        } else {
+            if(_flsbuf(*(const char*)ptr, file) == EOF)
+                break;
+            written++;
+            wrcnt--;
+            ptr = (const char*)ptr + 1;
         }
     }
 
@@ -2896,8 +3183,6 @@ int CDECL fsetpos(FILE* file, const fpos_t *pos)
  */
 __int64 CDECL _ftelli64(FILE* file)
 {
-    /* TODO: just call fgetpos and return lower half of result */
-    int off=0;
     __int64 pos;
 
     _lock_file(file);
@@ -2907,26 +3192,50 @@ __int64 CDECL _ftelli64(FILE* file)
         return -1;
     }
     if(file->_bufsiz)  {
-        if( file->_flag & _IOWRT ) {
-            off = file->_ptr - file->_base;
+        if(file->_flag & _IOWRT) {
+            pos += file->_ptr - file->_base;
+
+            if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
+                char *p;
+
+                for(p=file->_base; p<file->_ptr; p++)
+                    if(*p == '\n')
+                        pos++;
+            }
+        } else if(!file->_cnt) { /* nothing to do */
+        } else if(_lseeki64(file->_file, 0, SEEK_END)==pos) {
+            int i;
+
+            pos -= file->_cnt;
+            if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
+                for(i=0; i<file->_cnt; i++)
+                    if(file->_ptr[i] == '\n')
+                        pos--;
+            }
         } else {
-            off = -file->_cnt;
-            if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
-                /* Black magic correction for CR removal */
-                int i;
-                for (i=0; i<file->_cnt; i++) {
-                    if (file->_ptr[i] == '\n')
-                        off--;
-                }
-                /* Black magic when reading CR at buffer boundary*/
-                if(get_ioinfo(file->_file)->wxflag & WX_READCR)
-                    off--;
+            char *p;
+
+            if(_lseeki64(file->_file, pos, SEEK_SET) != pos) {
+                _unlock_file(file);
+                return -1;
+            }
+
+            pos -= file->_bufsiz;
+            pos += file->_ptr - file->_base;
+
+            if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
+                if(get_ioinfo(file->_file)->wxflag & WX_READNL)
+                    pos--;
+
+                for(p=file->_base; p<file->_ptr; p++)
+                    if(*p == '\n')
+                        pos++;
             }
         }
     }
 
     _unlock_file(file);
-    return off + pos;
+    return pos;
 }
 
 /*********************************************************************
@@ -3300,16 +3609,20 @@ FILE* CDECL tmpfile(void)
   FILE* file = NULL;
 
   LOCK_FILES();
-  fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY);
+  fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY,
+          _S_IREAD | _S_IWRITE);
   if (fd != -1 && (file = alloc_fp()))
   {
-    if (init_fp(file, fd, _O_RDWR) == -1)
+    if (init_fp(file, fd, _IORW) == -1)
     {
         file->_flag = 0;
         file = NULL;
     }
     else file->_tmpfname = _strdup(filename);
   }
+
+  if(fd != -1 && !file)
+      _close(fd);
   UNLOCK_FILES();
   return file;
 }
index 55e5c8f..41340bb 100644 (file)
@@ -27,14 +27,25 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf)
   DWORD dw;
   WIN32_FILE_ATTRIBUTE_DATA hfi;
   unsigned short mode = ALL_S_IREAD;
-  size_t plen;
+  int plen;
 
   TRACE(":file (%s) buf(%p)\n",path,buf);
 
+  plen = _tcslen(path);
+  while (plen && path[plen-1]==' ')
+    plen--;
+
+  if (plen && (plen<2 || path[plen-2]!=':') &&
+          (path[plen-1]==':' || path[plen-1]=='\\' || path[plen-1]=='/'))
+  {
+    *_errno() = ENOENT;
+    return -1;
+  }
+
   if (!GetFileAttributesEx(path, GetFileExInfoStandard, &hfi))
   {
       TRACE("failed (%d)\n",GetLastError());
-      _dosmaperr(ERROR_FILE_NOT_FOUND);
+      *_errno() = ENOENT;
       return -1;
   }
 
@@ -45,16 +56,13 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf)
                  Also a letter as first char isn't enough to be classified
                 as a drive letter
   */
-  if (isalpha((unsigned char)*path)&& (*(path+1)==':'))
-    buf->st_dev = buf->st_rdev = _totupper(*path) - 'A'; /* drive num */
+  if (isalpha(*path)&& (*(path+1)==':'))
+    buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
   else
     buf->st_dev = buf->st_rdev = _getdrive() - 1;
 
-  plen = _tcslen(path);
-
   /* Dir, or regular file? */
-  if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
-      (path[plen-1] == '\\'))
+  if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     mode |= (_S_IFDIR | ALL_S_IEXEC);
   else
   {
@@ -62,8 +70,8 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf)
     /* executable? */
     if (plen > 6 && path[plen-4] == '.')  /* shortest exe: "\x.exe" */
     {
-      TCHAR4 ext = _totlower(path[plen-1]) | (_totlower(path[plen-2]) << TCSIZE) |
-                                 (_totlower(path[plen-3]) << (2*TCSIZE));
+      unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) |
+                                 (tolower(path[plen-3]) << 16);
       if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
           mode |= ALL_S_IEXEC;
     }
@@ -79,9 +87,9 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf)
   buf->st_atime = dw;
   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
   buf->st_mtime = buf->st_ctime = dw;
-  TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf->st_mode,buf->st_nlink,
-        (long)(buf->st_size >> 32),(long)buf->st_size,
-        (long)buf->st_atime,(long)buf->st_mtime,(long)buf->st_ctime);
+  TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
+        (int)(buf->st_size >> 32),(int)buf->st_size,
+        (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
   return 0;
 }
 
index a56c0dd..049ad2c 100644 (file)
 
 static _invalid_parameter_handler invalid_parameter_handler = NULL;
 
-/*
- * @implemented
+/*********************************************************************
+ *             _errno (MSVCRT.@)
  */
-unsigned long* CDECL __doserrno(void)
+int CDECL *_errno(void)
 {
-    return &(msvcrt_get_thread_data()->thread_doserrno);
+    return &(msvcrt_get_thread_data()->thread_errno);
 }
 
-/*
- * @implemented
+/*********************************************************************
+ *             __doserrno (MSVCRT.@)
  */
-int CDECL *_errno(void)
+unsigned long* CDECL __doserrno(void)
 {
-    return &(msvcrt_get_thread_data()->thread_errno);
+    return &(msvcrt_get_thread_data()->thread_doserrno);
 }
 
-/*
- * @implemented
+/*********************************************************************
+ *             _get_errno (MSVCRT.@)
  */
-errno_t CDECL _get_doserrno(unsigned long *pValue)
+errno_t CDECL _get_errno(int *pValue)
 {
     if (!pValue)
         return EINVAL;
 
-    *pValue = *__doserrno();
+    *pValue = *_errno();
     return 0;
 }
 
-/*
- * @implemented
+/*********************************************************************
+ *             _get_doserrno (MSVCRT.@)
  */
-errno_t CDECL _set_doserrno(unsigned long error)
+errno_t CDECL _get_doserrno(unsigned long *pValue)
 {
-    *__doserrno() = error;
+    if (!pValue)
+        return EINVAL;
+
+    *pValue = *__doserrno();
     return 0;
 }
 
-/*
- * @implemented
+/*********************************************************************
+ *             _set_errno (MSVCRT.@)
  */
-errno_t CDECL _get_errno(int *pValue)
+errno_t CDECL _set_errno(int value)
 {
-    if (!pValue)
-        return EINVAL;
-
-    *pValue = *_errno();
+    *_errno() = value;
     return 0;
 }
 
-/*
- * @implemented
+/*********************************************************************
+ *             _set_doserrno (MSVCRT.@)
  */
-int CDECL _set_errno(int error)
+errno_t CDECL _set_doserrno(unsigned long value)
 {
-    *_errno() = error;
+    *__doserrno() = value;
     return 0;
 }
 
@@ -124,8 +124,8 @@ int CDECL _set_error_mode(int mode)
 }
 
 /******************************************************************************
-             _seterrormode (MSVCRT.@)
-*/
+ *             _seterrormode (MSVCRT.@)
+ */
 void CDECL _seterrormode(int mode)
 {
     SetErrorMode( mode );
@@ -134,8 +134,8 @@ void CDECL _seterrormode(int mode)
 /******************************************************************************
  *             _invalid_parameter (MSVCRT.@)
  */
-void CDECL _invalid_parameter(const wchar_t *expr, const wchar_t *func,
-                                       const wchar_t *file, unsigned int line, uintptr_t arg)
+void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func,
+                                const wchar_t *file, unsigned int line, uintptr_t arg)
 {
     if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
     else
@@ -163,4 +163,3 @@ _invalid_parameter_handler CDECL _set_invalid_parameter_handler(
     invalid_parameter_handler = handler;
     return old;
 }
-/* EOF */
index a7a4543..ea7cafd 100644 (file)
@@ -109,8 +109,7 @@ int _tsearchenv_s(const _TCHAR* file, const _TCHAR* env, _TCHAR *buf, size_t cou
     {
       if (_tcslen(curPath) + 1 > count)
       {
-          MSVCRT_INVALID_PMT("buf[count] is too small");
-          *_errno() = ERANGE;
+          MSVCRT_INVALID_PMT("buf[count] is too small", ERANGE);
           return ERANGE;
       }
       _tcscpy(buf, curPath);
index 76473c9..c8c89e4 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <precomp.h>
 #include <tchar.h>
+#include <mbctype.h>
 
 #if IS_SECAPI
 #define _FAILURE -1
@@ -99,12 +100,24 @@ _tsplitpath_x(
             drive[2] = '\0';
         }
         path += 2;
-       }
+    }
 
     /* Scan the rest of the string */
     dir_start = path;
     while (*path != '\0')
     {
+#if !defined(_UNICODE) && !defined(_LIBCNT_)
+        /* Check for multibyte lead bytes */
+        if (_ismbblead((unsigned char)*path))
+        {
+            /* Check for unexpected end of string */
+            if (path[1] == 0) break;
+
+            /* Skip the lead byte and the following byte */
+            path += 2;
+            continue;
+        }
+#endif
         /* Remember last path separator and last dot */
         if ((*path == '\\') || (*path == '/')) file_start = path + 1;
         if (*path == '.') ext_start = path;
@@ -114,14 +127,14 @@ _tsplitpath_x(
     /* Check if we got a file name / extension */
     if (!file_start)
         file_start = dir_start;
-    if (!ext_start || ext_start < file_start)
+    if (!ext_start || (ext_start < file_start))
         ext_start = path;
 
     if (dir)
     {
         src = dir_start;
         count = dir_size - 1;
-        while (src < file_start && count--) *dir++ = *src++;
+        while ((src < file_start) && count--) *dir++ = *src++;
         *dir = '\0';
     }
 
index e2f5918..0d6e0e5 100644 (file)
@@ -113,10 +113,7 @@ int CDECL _i64toa_s(__int64 value, char *str, size_t size, int radix)
             *p++ = *pos--;
 
         str[0] = '\0';
-        MSVCRT_INVALID_PMT("str[size] is too small");
-#ifndef _LIBCNT_
-        *_errno() = ERANGE;
-#endif
+        MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
         return ERANGE;
     }
 
@@ -182,10 +179,7 @@ int CDECL _ui64toa_s(unsigned __int64 value, char *str,
     }while(value != 0);
 
     if((unsigned)(buffer-pos+65) > size) {
-        MSVCRT_INVALID_PMT("str[size] is too small");
-#ifndef _LIBCNT_
-        *_errno() = EINVAL;
-#endif
+        MSVCRT_INVALID_PMT("str[size] is too small", EINVAL);
         return EINVAL;
     }
 
@@ -322,10 +316,7 @@ int CDECL _ltoa_s(long value, char *str, size_t size, int radix)
             *p++ = *pos--;
 
         str[0] = '\0';
-        MSVCRT_INVALID_PMT("str[size] is too small");
-#ifndef _LIBCNT_
-        *_errno() = EINVAL;
-#endif
+        MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
         return ERANGE;
     }
 
index c18b679..204bcf7 100644 (file)
@@ -123,11 +123,8 @@ _i64tow_s(__int64 value, wchar_t *str, size_t size, int radix)
         for (pos = buffer + 63, i = 0; i < size; i++)
             *p++ = *pos--;
 
-        MSVCRT_INVALID_PMT("str[size] is too small");
+        MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
         str[0] = '\0';
-#ifndef _LIBCNT_
-        *_errno() = ERANGE;
-#endif
         return ERANGE;
     }
 
@@ -195,10 +192,7 @@ _ui64tow_s( unsigned __int64 value, wchar_t *str,
     } while (value != 0);
 
     if((size_t)(buffer-pos+65) > size) {
-        MSVCRT_INVALID_PMT("str[size] is too small");
-#ifndef _LIBCNT_
-        *_errno() = EINVAL;
-#endif
+        MSVCRT_INVALID_PMT("str[size] is too small", EINVAL);
         return EINVAL;
     }
 
@@ -338,11 +332,8 @@ _ltow_s(long value, wchar_t *str, size_t size, int radix)
         for (pos = buffer + 31, i = 0; i < size; i++)
             *p++ = *pos--;
 
-        MSVCRT_INVALID_PMT("str[size] is too small");
+        MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
         str[0] = '\0';
-#ifndef _LIBCNT_
-        *_errno() = ERANGE;
-#endif
         return ERANGE;
     }
 
index 8d0eced..a583c22 100644 (file)
@@ -204,8 +204,7 @@ int CDECL __wcserror_s(wchar_t* buffer, size_t nc, const wchar_t* str)
     if (str && *str) len += lstrlenW(str) + 2 /* ': ' */;
     if (len > nc)
     {
-        MSVCRT_INVALID_PMT("buffer[nc] is too small");
-        _set_errno(ERANGE);
+        MSVCRT_INVALID_PMT("buffer[nc] is too small", ERANGE);
         return ERANGE;
     }
     if (str && *str)
index 846179a..81adfdb 100644 (file)
@@ -432,7 +432,7 @@ INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
     }
     if (dststart == elem)
     {
-        MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n");
+        MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
         return EINVAL;
     }
 
@@ -453,7 +453,7 @@ INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
         dst[dststart+srclen] = '\0';
         return ret;
     }
-    MSVCRT_INVALID_PMT("dst[elem] is too small");
+    MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
     dst[0] = '\0';
     return ERANGE;
 }
index ad4eafb..314811a 100644 (file)
@@ -126,15 +126,13 @@ _gmtime64_s(
     __time64_t time = *ptime;
     if (!ptm)
     {
-        _set_errno(ERROR_BAD_COMMAND);
-        MSVCRT_INVALID_PMT("ptm == NULL");
+        MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND);
         return ERROR_BAD_COMMAND;
     }
 
     if (!ptime)
     {
-        _set_errno(ERROR_BAD_COMMAND);
-        MSVCRT_INVALID_PMT("ptime == NULL");
+        MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND);
         return ERROR_BAD_COMMAND;
     }
 
@@ -167,15 +165,13 @@ _gmtime32_s(
     __time64_t time = *ptime;
     if (!ptm)
     {
-        _set_errno(ERROR_BAD_COMMAND);
-        MSVCRT_INVALID_PMT("ptm == NULL");
+        MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND);
         return ERROR_BAD_COMMAND;
     }
 
     if (!ptime)
     {
-        _set_errno(ERROR_BAD_COMMAND);
-        MSVCRT_INVALID_PMT("ptime == NULL");
+        MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND);
         return ERROR_BAD_COMMAND;
     }
 
index b72f63f..8ee2d1b 100644 (file)
@@ -603,8 +603,7 @@ int CDECL strncpy_s(char *dest, size_t numberOfElements,
         return 0;
     }
 
-    MSVCRT_INVALID_PMT("dest[numberOfElements] is too small");
+    MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", EINVAL);
     dest[0] = '\0';
-    *_errno() = EINVAL;
     return EINVAL;
 }
index ec4763a..b88a56e 100644 (file)
@@ -258,7 +258,7 @@ gdi32 -
   reactos/dll/win32/gdi32/objects/linedda.c     # Synced at 20090410
 
 kernel32 -
-  reactos/dll/win32/kernel32/wine/actctx.c               # Partly synced
+  reactos/dll/win32/kernel32/wine/actctx.c               # Partly synced with Wine 1.7.17
   reactos/dll/win32/kernel32/wine/comm.c                 # Synced in r52754
   reactos/dll/win32/kernel32/wine/lzexpand.c             # Synced in r52754
   reactos/dll/win32/kernel32/wine/profile.c              # Synced in r52754
index 9841771..b197c0e 100644 (file)
Binary files a/media/inf/audio.inf and b/media/inf/audio.inf differ
index cb5ae49..55b259d 100644 (file)
Binary files a/media/inf/battery.inf and b/media/inf/battery.inf differ
index 4a61fae..bff8acc 100644 (file)
Binary files a/media/inf/bth.inf and b/media/inf/bth.inf differ
index 967b5ff..7e50b19 100644 (file)
Binary files a/media/inf/cdrom.inf and b/media/inf/cdrom.inf differ
index 7650e5f..e580e93 100644 (file)
Binary files a/media/inf/disk.inf and b/media/inf/disk.inf differ
index c9fa74f..abff970 100644 (file)
Binary files a/media/inf/display.inf and b/media/inf/display.inf differ
index 6a1aeeb..a6e0177 100644 (file)
Binary files a/media/inf/flpydisk.inf and b/media/inf/flpydisk.inf differ
index 25f902d..2686870 100644 (file)
Binary files a/media/inf/hal.inf and b/media/inf/hal.inf differ
index d72b07f..98738eb 100644 (file)
Binary files a/media/inf/hdc.inf and b/media/inf/hdc.inf differ
index f1e79d1..789bef3 100644 (file)
Binary files a/media/inf/input.inf and b/media/inf/input.inf differ
index 93d08dc..8fe2e0b 100644 (file)
Binary files a/media/inf/keyboard.inf and b/media/inf/keyboard.inf differ
index f2296d1..a30b2da 100644 (file)
Binary files a/media/inf/legcydrv.inf and b/media/inf/legcydrv.inf differ
index e64177f..8938bd8 100644 (file)
Binary files a/media/inf/machine.inf and b/media/inf/machine.inf differ
index 4916939..4415a11 100644 (file)
Binary files a/media/inf/monitor.inf and b/media/inf/monitor.inf differ
index 013a54e..8d7ff54 100644 (file)
Binary files a/media/inf/shortcuts.inf and b/media/inf/shortcuts.inf differ
index 6a32d97..9bc33ce 100644 (file)
Binary files a/media/inf/unknown.inf and b/media/inf/unknown.inf differ
index 75b348c..e7e701f 100644 (file)
Binary files a/media/inf/usb.inf and b/media/inf/usb.inf differ
index 4238a82..26cbda9 100644 (file)
@@ -19,7 +19,7 @@
 
 /* GLOBALS *******************************************************************/
 
-POBJECT_TYPE _ExEventObjectType = NULL;
+POBJECT_TYPE ExEventObjectType = NULL;
 
 GENERIC_MAPPING ExpEventMapping =
 {
index 7b07b90..9846468 100644 (file)
@@ -19,7 +19,7 @@
 
 /* GLOBALS ******************************************************************/
 
-POBJECT_TYPE _ExSemaphoreObjectType;
+POBJECT_TYPE ExSemaphoreObjectType;
 
 GENERIC_MAPPING ExSemaphoreMapping =
 {
index 0fa37b6..88178ad 100644 (file)
@@ -1964,7 +1964,7 @@ QSI_DEF(SystemLookasideInformation)
     }
 
     /* Acquire spinlock for ExpNonPagedLookasideListHead */
-    OldIrql = KfAcquireSpinLock(&ExpNonPagedLookasideListLock);
+    KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
 
     /* Copy info from non-paged lookaside lists */
     ExpCopyLookasideInformation(&Info,
@@ -1973,7 +1973,7 @@ QSI_DEF(SystemLookasideInformation)
                                 TRUE);
 
     /* Release spinlock for ExpNonPagedLookasideListHead */
-    KfReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+    KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
 
     if (Remaining == 0)
     {
@@ -1981,7 +1981,7 @@ QSI_DEF(SystemLookasideInformation)
     }
 
     /* Acquire spinlock for ExpPagedLookasideListHead */
-    OldIrql = KfAcquireSpinLock(&ExpPagedLookasideListLock);
+    KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
 
     /* Copy info from paged lookaside lists */
     ExpCopyLookasideInformation(&Info,
@@ -1990,7 +1990,7 @@ QSI_DEF(SystemLookasideInformation)
                                 TRUE);
 
     /* Release spinlock for ExpPagedLookasideListHead */
-    KfReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+    KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
 
 Leave:
 
index b5a68a4..0150a55 100644 (file)
@@ -18,7 +18,7 @@ PERESOURCE FsRtlPagingIoResources;
 ULONG FsRtlPagingIoResourceSelector;
 NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread(VOID);
 
-static UCHAR LegalAnsiCharacterArray[] =
+static const UCHAR LegalAnsiCharacterArray[] =
 {
   0,                                                        /* CTRL+@, 0x00 */
   0,                                                        /* CTRL+A, 0x01 */
@@ -150,7 +150,7 @@ static UCHAR LegalAnsiCharacterArray[] =
   FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL     /*         0x7f */
 };
 
-PUCHAR FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray;
+const UCHAR * const FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray;
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
index 0021a05..0904914 100644 (file)
@@ -296,7 +296,7 @@ MI_IS_MAPPED_PTE(PMMPTE PointerPte)
 {
     /// FIXME
     __debugbreak();
-    return (PointerPte->u.Long & 0xFFFFFC01 != 0);
+    return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
 }
 
 VOID
index cca4e8f..86ce04e 100644 (file)
@@ -133,5 +133,4 @@ FsRtlInitSystem(
 // Global data inside the File System Runtime Library
 //
 extern PERESOURCE FsRtlPagingIoResources;
-extern PUCHAR _FsRtlLegalAnsiCharacterArray;
 extern PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList;
index 0943e54..3bb0dc3 100644 (file)
@@ -2,18 +2,11 @@
 
 #include <cportlib/cportlib.h>
 
-#ifdef _M_PPC
-#define KdDebuggerEnabled _KdDebuggerEnabled
-#define KdDebuggerNotPresent _KdDebuggerNotPresent
-#endif
-
 //
 // Kernel Debugger Port Definition
 //
 struct _KD_DISPATCH_TABLE;
 extern CPPORT GdbPortInfo;
-extern BOOLEAN _KdDebuggerEnabled;
-extern BOOLEAN _KdDebuggerNotPresent;
 extern BOOLEAN KdBreakAfterSymbolLoad;
 extern BOOLEAN KdPitchDebugger;
 extern BOOLEAN KdIgnoreUmExceptions;
index 444afbb..9cae4fa 100644 (file)
@@ -494,8 +494,6 @@ extern PKDEBUG_ROUTINE KiDebugRoutine;
 extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
 extern BOOLEAN KdBreakAfterSymbolLoad;
 extern BOOLEAN KdPitchDebugger;
-extern BOOLEAN _KdDebuggerNotPresent;
-extern BOOLEAN _KdDebuggerEnabled;
 extern BOOLEAN KdAutoEnableOnEvent;
 extern BOOLEAN KdBlockEnable;
 extern BOOLEAN KdIgnoreUmExceptions;
index 9e7f37d..dc5772c 100644 (file)
 //
 // Define the internal versions of external and public global data
 //
-#define IoFileObjectType                _IoFileObjectType
-#define PsThreadType                    _PsThreadType
-#define PsProcessType                   _PsProcessType
-#define ExEventObjectType               _ExEventObjectType
-#define ExSemaphoreObjectType           _ExSemaphoreObjectType
-#define KdDebuggerEnabled               _KdDebuggerEnabled
-#define KdDebuggerNotPresent            _KdDebuggerNotPresent
-#define NlsOemLeadByteInfo              _NlsOemLeadByteInfo
-extern PUSHORT _NlsOemLeadByteInfo;
 #define KeNumberProcessors              _KeNumberProcessors
 extern UCHAR _KeNumberProcessors;
-#define FsRtlLegalAnsiCharacterArray    _FsRtlLegalAnsiCharacterArray
-#undef LEGAL_ANSI_CHARACTER_ARRAY
-#undef NLS_MB_CODE_PAGE_TAG
-#undef NLS_OEM_LEAD_BYTE_INFO
-#define LEGAL_ANSI_CHARACTER_ARRAY      FsRtlLegalAnsiCharacterArray
-#define NLS_MB_CODE_PAGE_TAG            NlsMbOemCodePageTag
-#define NLS_OEM_LEAD_BYTE_INFO          _NlsOemLeadByteInfo
-#undef KD_DEBUGGER_ENABLED
-#undef KD_DEBUGGER_NOT_PRESENT
-#define KD_DEBUGGER_ENABLED             KdDebuggerEnabled
-#define KD_DEBUGGER_NOT_PRESENT         KdDebuggerNotPresent
-#define HalDispatchTable                _HalDispatchTable
-#undef HALDISPATCH
-#define HALDISPATCH                     (&HalDispatchTable)
 #define ExRaiseStatus RtlRaiseStatus
 
 /* Internal Headers */
index c0a1650..5ea8641 100644 (file)
@@ -1903,9 +1903,7 @@ KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
 
             /* We are disabled now */
             KdDebuggerEnabled = FALSE;
-#undef KdDebuggerEnabled
             SharedUserData->KdDebuggerEnabled = FALSE;
-#define KdDebuggerEnabled _KdDebuggerEnabled
         }
      }
 
index d6b0107..5a1e10e 100644 (file)
@@ -79,8 +79,8 @@ PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
 //
 BOOLEAN KdBreakAfterSymbolLoad;
 BOOLEAN KdPitchDebugger;
-BOOLEAN _KdDebuggerNotPresent;
-BOOLEAN _KdDebuggerEnabled;
+BOOLEAN KdDebuggerNotPresent;
+BOOLEAN KdDebuggerEnabled;
 BOOLEAN KdAutoEnableOnEvent;
 BOOLEAN KdBlockEnable;
 BOOLEAN KdIgnoreUmExceptions;
index 89d57fb..723a18c 100644 (file)
@@ -310,9 +310,7 @@ KdInitSystem(IN ULONG BootPhase,
         KdDebuggerEnabled = TRUE;
 
         /* Let user-mode know that it's enabled as well */
-#undef KdDebuggerEnabled
         SharedUserData->KdDebuggerEnabled = TRUE;
-#define KdDebuggerEnabled _KdDebuggerEnabled
 
         /* Check if the debugger should be disabled initially */
         if (DisableKdAfterInit)
index 76b1253..f54b925 100644 (file)
@@ -78,6 +78,9 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
         /* Increase interrupt count and end the interrupt */
         Prcb->InterruptCount++;
         KiEndInterrupt(Irql, TrapFrame);
+
+        /* Note: non-x86 return back to the caller! */
+        return;
     }
 
     /* Add the increment time to the shared data */
index ec3b094..af87192 100644 (file)
@@ -280,7 +280,14 @@ l_ReadHeaderFromFile:
         nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize);
 
         if(!NT_SUCCESS(nStatus))
-            DIE(("ReadFile failed, status %08X\n", nStatus));
+        {
+            NTSTATUS ReturnedStatus = nStatus;
+
+            /* If it attempted to read past the end of the file, it means e_lfanew is invalid */
+            if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT;
+
+            DIE(("ReadFile failed, status %08X\n", ReturnedStatus));
+        }
 
         ASSERT(pData);
         ASSERT(pBuffer);
index e5d8eee..5f7a072 100644 (file)
@@ -82,7 +82,7 @@
 @ stdcall ExEnterCriticalRegionAndAcquireResourceShared(ptr)
 @ stdcall ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(ptr)
 @ stdcall ExEnumHandleTable(ptr ptr ptr ptr)
-@ extern ExEventObjectType _ExEventObjectType
+@ extern ExEventObjectType
 @ stdcall ExExtendZone(ptr ptr long)
 @ stdcall ExFreeCacheAwareRundownProtection(ptr)
 @ stdcall ExFreePool(ptr)
 @ fastcall ExReleaseRundownProtectionEx(ptr long) ExfReleaseRundownProtectionEx
 @ fastcall ExRundownCompleted(ptr) ExfRundownCompleted
 @ fastcall ExRundownCompletedCacheAware(ptr) ExfRundownCompletedCacheAware
-@ extern ExSemaphoreObjectType _ExSemaphoreObjectType
+@ extern ExSemaphoreObjectType
 @ stdcall ExSetResourceOwnerPointer(ptr ptr)
 @ stdcall ExSetTimerResolution(long long)
 @ stdcall ExSizeOfRundownProtectionCacheAware()
 @ stdcall FsRtlIsNtstatusExpected(long)
 @ stdcall FsRtlIsPagingFile(ptr)
 @ stdcall FsRtlIsTotalDeviceFailure(ptr)
-@ extern FsRtlLegalAnsiCharacterArray _FsRtlLegalAnsiCharacterArray
+@ extern FsRtlLegalAnsiCharacterArray
 @ stdcall FsRtlLookupBaseMcbEntry(ptr long long ptr ptr ptr ptr ptr)
 @ stdcall FsRtlLookupLargeMcbEntry(ptr long long ptr ptr ptr ptr ptr)
 @ stdcall FsRtlLookupLastBaseMcbEntry(ptr ptr ptr)
 @ stdcall FsRtlUninitializeLargeMcb(ptr)
 @ stdcall FsRtlUninitializeMcb(ptr)
 @ stdcall FsRtlUninitializeOplock(ptr)
-@ extern HalDispatchTable _HalDispatchTable
+@ extern HalDispatchTable
 @ fastcall HalExamineMBR(ptr long long ptr)
 @ extern HalPrivateDispatchTable
 @ stdcall HeadlessDispatch(long ptr long ptr ptr)
 @ stdcall IoEnumerateDeviceObjectList(ptr ptr long ptr)
 @ stdcall IoEnumerateRegisteredFiltersList(ptr long ptr)
 @ stdcall IoFastQueryNetworkAttributes(ptr long long ptr ptr)
-@ extern IoFileObjectType _IoFileObjectType
+@ extern IoFileObjectType
 @ stdcall IoForwardAndCatchIrp(ptr ptr) IoForwardIrpSynchronously
 @ stdcall IoForwardIrpSynchronously(ptr ptr)
 @ stdcall IoFreeController(ptr)
 @ fastcall IofCallDriver(ptr ptr)
 @ fastcall IofCompleteRequest(ptr long)
 @ stdcall KdChangeOption(long long ptr long ptr ptr)
-@ extern KdDebuggerEnabled _KdDebuggerEnabled
-@ extern KdDebuggerNotPresent _KdDebuggerNotPresent
+@ extern KdDebuggerEnabled
+@ extern KdDebuggerNotPresent
 @ stdcall KdDisableDebugger()
 @ stdcall KdEnableDebugger()
 @ extern KdEnteredDebugger
 @ extern NlsMbCodePageTag
 @ extern NlsMbOemCodePageTag
 @ extern NlsOemCodePage
-@ extern NlsOemLeadByteInfo _NlsOemLeadByteInfo
+@ extern NlsOemLeadByteInfo
 @ stdcall NtAddAtom(wstr long ptr)
 @ stdcall NtAdjustPrivilegesToken(ptr long ptr long ptr ptr)
 @ stdcall -arch=i386,arm NtAlertThread(ptr)
 @ stdcall PsLookupProcessByProcessId(ptr ptr)
 @ stdcall PsLookupProcessThreadByCid(ptr ptr ptr)
 @ stdcall PsLookupThreadByThreadId(ptr ptr)
-@ extern PsProcessType _PsProcessType
+@ extern PsProcessType
 @ stdcall PsReferenceImpersonationToken(ptr ptr ptr ptr)
 @ stdcall PsReferencePrimaryToken(ptr)
 @ stdcall PsRemoveCreateThreadNotifyRoutine(ptr)
 @ stdcall PsSetThreadHardErrorsAreDisabled(ptr long)
 @ stdcall PsSetThreadWin32Thread(ptr ptr ptr)
 @ stdcall PsTerminateSystemThread(long)
-@ extern PsThreadType _PsThreadType
+@ extern PsThreadType
 ;PsWrapApcWow64Thread
 @ stdcall -arch=i386,arm READ_REGISTER_BUFFER_UCHAR(ptr ptr long)
 @ stdcall -arch=i386,arm READ_REGISTER_BUFFER_ULONG(ptr ptr long)
index 42899dd..beba4d0 100644 (file)
@@ -132,9 +132,9 @@ PspInsertQuotaBlock(
 {
     KIRQL OldIrql;
 
-    OldIrql = KfAcquireSpinLock(&PspQuotaLock);
+    KeAcquireSpinLock(&PspQuotaLock, &OldIrql);
     InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList);
-    KfReleaseSpinLock(&PspQuotaLock, OldIrql);
+    KeReleaseSpinLock(&PspQuotaLock, OldIrql);
 }
 
 VOID
@@ -147,9 +147,9 @@ PspDestroyQuotaBlock(PEPROCESS Process)
     if (QuotaBlock != &PspDefaultQuotaBlock &&
         InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0)
     {
-        OldIrql = KfAcquireSpinLock(&PspQuotaLock);
+        KeAcquireSpinLock(&PspQuotaLock, &OldIrql);
         RemoveEntryList(&QuotaBlock->QuotaList);
-        KfReleaseSpinLock(&PspQuotaLock, OldIrql);
+        KeReleaseSpinLock(&PspQuotaLock, OldIrql);
         ExFreePool(QuotaBlock);
     }
 }
index 52d10bc..230e58c 100644 (file)
@@ -1,6 +1,4 @@
 
-if(ARCH STREQUAL "i386")
-   add_subdirectory(ntvdm)
-endif()
+add_subdirectory(ntvdm)
 add_subdirectory(win)
 add_subdirectory(win32)
index 7a1c6aa..2ee9f55 100644 (file)
@@ -1,11 +1,43 @@
 
-include_directories(.)
+include_directories(
+    ${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486
+    ntvdm)
 
-add_executable(ntvdm
+spec2def(ntvdm.exe ntvdm.spec)
+
+list(APPEND SOURCE
+    bios/bios32/bios32.c
+    bios/bios32/kbdbios32.c
+    bios/bios32/vidbios32.c
+    bios/bios.c
+    bios/kbdbios.c
+    bios/rom.c
+    bios/vidbios.c
+    hardware/cmos.c
+    hardware/pic.c
+    hardware/ps2.c
+    hardware/speaker.c
+    hardware/timer.c
+    hardware/vga.c
+    dos/dos32krnl/bios.c
+    dos/dos32krnl/dos.c
+    dos/dos32krnl/dosfiles.c
+    dos/dem.c
+    bop.c
+    callback.c
+    clock.c
+    emulator.c
+    io.c
+    registers.c
+    utils.c
+    vddsup.c
     ntvdm.c
-    ntvdm.rc)
+    ntvdm.rc
+    ${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def)
 
-set_module_type(ntvdm win32cui)
-add_importlibs(ntvdm ntdll user32 gdi32 advapi32 msvcrt kernel32)
-add_dependencies(ntvdm ndk bugcodes)
+add_executable(ntvdm ${SOURCE})
+set_module_type(ntvdm win32cui UNICODE)
+set_image_base(ntvdm 0x0F000000)
+target_link_libraries(ntvdm fast486)
+add_importlibs(ntvdm user32 gdi32 advapi32 msvcrt kernel32 ntdll)
 add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all)
diff --git a/subsystems/ntvdm/bios/bios.c b/subsystems/ntvdm/bios/bios.c
new file mode 100644 (file)
index 0000000..12066b5
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bios.c
+ * PURPOSE:         VDM BIOS Support Library
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+#include "bop.h"
+
+#include "bios.h"
+#include "bios32/bios32.h"
+
+#include "rom.h"
+
+#include "io.h"
+#include "hardware/cmos.h"
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define BOP_BIOSINIT    0x00    // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
+                                // to let the virtual machine initialize itself
+                                // the IVT and its hardware.
+#define BOP_EQUIPLIST   0x11
+#define BOP_GETMEMSIZE  0x12
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BOOLEAN Bios32Loaded = FALSE;
+
+static CALLBACK16 __BiosContext;
+PBIOS_DATA_AREA Bda;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static VOID WINAPI BiosInitBop(LPWORD Stack)
+{
+    BOOLEAN Success;
+
+    /* Load the second part of the Windows NTVDM BIOS image */
+    LPCSTR BiosFileName = "bios1.rom";
+    PVOID  BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
+    DWORD  BiosSize = 0;
+
+    /* Disable interrupts */
+    setIF(0);
+
+    DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
+
+    /* Initialize a private callback context */
+    InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
+
+    Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
+    DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    if (Success == FALSE)
+    {
+        /* Stop the VDM */
+        EmulatorTerminate();
+        return;
+    }
+
+    // DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
+                       // L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
+        // BiosLocation,
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
+
+         // (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
+        // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
+
+    /* Initialize IVT and hardware */
+
+    /* Initialize the Keyboard and Video BIOS */
+    if (!KbdBiosInitialize() || !VidBiosInitialize())
+    {
+        /* Stop the VDM */
+        EmulatorTerminate();
+        return;
+    }
+
+    /* Load VGA BIOS */
+    // Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
+    // DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    /* Enable interrupts */
+    setIF(1);
+
+    ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
+
+    /* Load some ROMs */
+    // Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
+    // DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    SearchAndInitRoms(&__BiosContext);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID WINAPI BiosEquipmentService(LPWORD Stack)
+{
+    /* Return the equipment list */
+    setAX(Bda->EquipmentList);
+}
+
+VOID WINAPI BiosGetMemorySize(LPWORD Stack)
+{
+    /* Return the conventional memory size in kB, typically 640 kB */
+    setAX(Bda->MemorySize);
+}
+
+BOOLEAN
+BiosInitialize(IN LPCSTR BiosFileName)
+{
+    BOOLEAN Success = FALSE;
+
+    /* Disable interrupts */
+    setIF(0);
+
+    /* Initialize the BDA pointer */
+    Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
+
+    /* Register the BIOS support BOPs */
+    RegisterBop(BOP_BIOSINIT  , BiosInitBop);
+    RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
+    RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
+
+    if (BiosFileName)
+    {
+        PVOID BiosLocation = NULL;
+        DWORD BiosSize = 0;
+
+        Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
+        DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+        if (!Success) return FALSE;
+
+        DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
+                       L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
+            BiosLocation,
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
+
+             (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
+            *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
+
+        DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
+                       TO_LINEAR(getCS(), getIP()),
+                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0),
+                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1),
+                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2),
+                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3),
+                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4));
+
+        /* Boot it up */
+
+        /*
+         * The CPU is already in reset-mode so that
+         * CS:IP points to F000:FFF0 as required.
+         */
+        DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP());
+        // setCS(0xF000);
+        // setIP(0xFFF0);
+
+        Success = TRUE;
+    }
+    else
+    {
+        Success = Bios32Loaded = Bios32Initialize();
+    }
+
+    /* Enable interrupts */
+    setIF(1);
+
+    return Success;
+}
+
+VOID
+BiosCleanup(VOID)
+{
+    if (Bios32Loaded) Bios32Cleanup();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios.h b/subsystems/ntvdm/bios/bios.h
new file mode 100644 (file)
index 0000000..cc1bb94
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bios.h
+ * PURPOSE:         VDM BIOS Support Library
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _BIOS_H_
+#define _BIOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include "kbdbios.h"
+#include "vidbios.h"
+
+/* DEFINES ********************************************************************/
+
+#define BDA_SEGMENT     0x40
+#define BIOS_SEGMENT    0xF000
+
+#define BIOS_EQUIPMENT_LIST     0x2C // HACK: Disable FPU for now
+
+/*
+ * BIOS Data Area at 0040:XXXX
+ *
+ * See: http://webpages.charter.net/danrollins/techhelp/0093.HTM
+ * and: http://www.bioscentral.com/misc/bda.htm
+ * for more information.
+ */
+#pragma pack(push, 1)
+typedef struct
+{
+    WORD SerialPorts[4];                        // 0x00
+    WORD ParallelPorts[3];                      // 0x08
+    WORD EbdaSegment;                           // 0x0e - ParallelPort in PC/XT
+    WORD EquipmentList;                         // 0x10
+    BYTE Reserved0;                             // 0x12 - Errors in PCjr infrared keyboard link
+    WORD MemorySize;                            // 0x13
+    WORD Reserved1;                             // 0x15 - Scratch pad for manufacturing error tests
+    WORD KeybdShiftFlags;                       // 0x17
+    BYTE AlternateKeypad;                       // 0x19
+    WORD KeybdBufferHead;                       // 0x1a
+    WORD KeybdBufferTail;                       // 0x1c
+    WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE];     // 0x1e
+    BYTE DriveRecalibrate;                      // 0x3e
+    BYTE DriveMotorStatus;                      // 0x3f
+    BYTE MotorShutdownCounter;                  // 0x40
+    BYTE LastDisketteOperation;                 // 0x41
+    BYTE Reserved2[7];                          // 0x42
+    BYTE VideoMode;                             // 0x49
+    WORD ScreenColumns;                         // 0x4a
+    WORD VideoPageSize;                         // 0x4c
+    WORD VideoPageOffset;                       // 0x4e
+    WORD CursorPosition[BIOS_MAX_PAGES];        // 0x50
+    BYTE CursorEndLine;                         // 0x60
+    BYTE CursorStartLine;                       // 0x61
+    BYTE VideoPage;                             // 0x62
+    WORD CrtBasePort;                           // 0x63
+    BYTE CrtModeControl;                        // 0x65
+    BYTE CrtColorPaletteMask;                   // 0x66
+    BYTE CassetteData[5];                       // 0x67
+    DWORD TickCounter;                          // 0x6c
+    BYTE MidnightPassed;                        // 0x70
+    BYTE BreakFlag;                             // 0x71
+    WORD SoftReset;                             // 0x72
+    BYTE LastDiskOperation;                     // 0x74
+    BYTE NumDisks;                              // 0x75
+    BYTE DriveControlByte;                      // 0x76
+    BYTE DiskPortOffset;                        // 0x77
+    BYTE LptTimeOut[4];                         // 0x78
+    BYTE ComTimeOut[4];                         // 0x7c
+    WORD KeybdBufferStart;                      // 0x80
+    WORD KeybdBufferEnd;                        // 0x82
+    BYTE ScreenRows;                            // 0x84
+    WORD CharacterHeight;                       // 0x85
+    BYTE EGAFlags[2];                           // 0x87
+    BYTE VGAFlags[2];                           // 0x89
+    DWORD Reserved3;                            // 0x8b
+    BYTE Reserved4;                             // 0x8f
+    BYTE Reserved5[2];                          // 0x90
+    BYTE Reserved6[2];                          // 0x92
+    BYTE Reserved7[2];                          // 0x94
+    WORD Reserved8;                             // 0x96
+    DWORD Reserved9;                            // 0x98
+    DWORD Reserved10;                           // 0x9c
+    DWORD Reserved11[2];                        // 0xa0
+    DWORD EGAPtr;                               // 0xa8
+    BYTE Reserved12[68];                        // 0xac
+    BYTE Reserved13[16];                        // 0xf0
+
+    DWORD Reserved14;                           // 0x100
+    BYTE Reserved15[12];                        // 0x104
+    BYTE Reserved16[17];                        // 0x110
+    BYTE Reserved17[15];                        // 0x121
+    BYTE Reserved18[3];                         // 0x130
+} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
+#pragma pack(pop)
+
+C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
+
+/* FUNCTIONS ******************************************************************/
+
+extern PBIOS_DATA_AREA Bda;
+
+VOID WINAPI BiosEquipmentService(LPWORD Stack);
+VOID WINAPI BiosGetMemorySize(LPWORD Stack);
+
+BOOLEAN
+BiosInitialize(IN LPCSTR BiosFileName);
+
+VOID
+BiosCleanup(VOID);
+
+#endif // _BIOS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/bios32.c b/subsystems/ntvdm/bios/bios32/bios32.c
new file mode 100644 (file)
index 0000000..fc27282
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bios32.c
+ * PURPOSE:         VDM 32-bit BIOS
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+#include "bop.h"
+
+#include "../bios.h"
+#include "../rom.h"
+#include "bios32.h"
+#include "bios32p.h"
+#include "kbdbios32.h"
+#include "vidbios32.h"
+
+#include "io.h"
+#include "hardware/cmos.h"
+#include "hardware/pic.h"
+#include "hardware/timer.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+CALLBACK16 BiosContext;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static VOID WINAPI BiosException(LPWORD Stack)
+{
+    /* Get the exception number and call the emulator API */
+    BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]);
+    EmulatorException(ExceptionNumber, Stack);
+}
+
+static VOID WINAPI BiosMiscService(LPWORD Stack)
+{
+    switch (getAH())
+    {
+        /* Wait */
+        case 0x86:
+        {
+            /*
+             * Interval in microseconds in CX:DX
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm
+             * for more information.
+             */
+            Sleep(MAKELONG(getDX(), getCX()));
+
+            /* Clear CF */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+            break;
+        }
+
+        /* Copy Extended Memory */
+        case 0x87:
+        {
+            DWORD Count = (DWORD)getCX() * 2;
+            PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI());
+            DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24);
+            DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
+            DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24);
+            DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
+
+            /* Check for flags */
+            if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
+            if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
+
+            if ((Count > SourceLimit) || (Count > DestLimit))
+            {
+                setAX(0x80);
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+                break;
+            }
+
+            /* Copy */
+            RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
+                          (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
+                          Count);
+
+            setAX(ERROR_SUCCESS);
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            break;
+        }
+
+        /* Get Extended Memory Size */
+        case 0x88:
+        {
+            UCHAR Low, High;
+
+            /*
+             * Return the (usable) extended memory (after 1 MB)
+             * size in kB from CMOS.
+             */
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW);
+            Low  = IOReadB(CMOS_DATA_PORT);
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH);
+            High = IOReadB(CMOS_DATA_PORT);
+            setAX(MAKEWORD(Low, High));
+
+            /* Clear CF */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
+                    getAH());
+        }
+    }
+}
+
+static VOID WINAPI BiosTimeService(LPWORD Stack)
+{
+    switch (getAH())
+    {
+        case 0x00:
+        {
+            /* Set AL to 1 if midnight had passed, 0 otherwise */
+            setAL(Bda->MidnightPassed ? 0x01 : 0x00);
+
+            /* Return the tick count in CX:DX */
+            setCX(HIWORD(Bda->TickCounter));
+            setDX(LOWORD(Bda->TickCounter));
+
+            /* Reset the midnight flag */
+            Bda->MidnightPassed = FALSE;
+
+            break;
+        }
+
+        case 0x01:
+        {
+            /* Set the tick count to CX:DX */
+            Bda->TickCounter = MAKELONG(getDX(), getCX());
+
+            /* Reset the midnight flag */
+            Bda->MidnightPassed = FALSE;
+
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
+                    getAH());
+        }
+    }
+}
+
+static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
+{
+    /* Increase the system tick count */
+    Bda->TickCounter++;
+}
+
+
+// From SeaBIOS
+static VOID PicSetIRQMask(USHORT off, USHORT on)
+{
+    UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
+    IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on);
+    IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on);
+}
+
+// From SeaBIOS
+VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
+{
+    UCHAR vector;
+
+    PicSetIRQMask(1 << hwirq, 0);
+    if (hwirq < 8)
+        vector = BIOS_PIC_MASTER_INT + hwirq;
+    else
+        vector = BIOS_PIC_SLAVE_INT  + hwirq - 8;
+
+    RegisterBiosInt32(vector, func);
+}
+
+
+VOID PicIRQComplete(LPWORD Stack)
+{
+    /* Get the interrupt number */
+    BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
+
+    /*
+     * If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
+     */
+
+    if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
+    {
+        /* It was an IRQ from the master PIC */
+        IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
+    }
+    else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
+    {
+        /* It was an IRQ from the slave PIC */
+        IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI);
+        IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI);
+    }
+}
+
+static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack)
+{
+    BYTE IrqNumber;
+
+    IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
+    IrqNumber = IOReadB(PIC_MASTER_CMD);
+
+    DPRINT("Master - IrqNumber = 0x%x\n", IrqNumber);
+
+    PicIRQComplete(Stack);
+}
+
+static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
+{
+    BYTE IrqNumber;
+
+    IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */);
+    IrqNumber = IOReadB(PIC_SLAVE_CMD);
+
+    DPRINT("Slave - IrqNumber = 0x%x\n", IrqNumber);
+
+    PicIRQComplete(Stack);
+}
+
+// Timer IRQ 0
+static VOID WINAPI BiosTimerIrq(LPWORD Stack)
+{
+    /*
+     * Perform the system timer interrupt.
+     *
+     * Do not call directly BiosSystemTimerInterrupt(Stack);
+     * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
+     * for their purpose...
+     */
+    /** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
+    Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
+    PicIRQComplete(Stack);
+}
+
+
+static VOID BiosHwSetup(VOID)
+{
+    /* Initialize the master and the slave PICs (cascade mode) */
+    IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
+    IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
+
+    /*
+     * Set the interrupt vector offsets for each PIC
+     * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15)
+     */
+    IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT);
+    IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT );
+
+    /* Tell the master PIC that there is a slave PIC at IRQ 2 */
+    IOWriteB(PIC_MASTER_DATA, 1 << 2);
+    /* Tell the slave PIC its cascade identity */
+    IOWriteB(PIC_SLAVE_DATA , 2);
+
+    /* Make sure both PICs are in 8086 mode */
+    IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086);
+    IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086);
+
+    /* Clear the masks for both PICs */
+    // IOWriteB(PIC_MASTER_DATA, 0x00);
+    // IOWriteB(PIC_SLAVE_DATA , 0x00);
+    /* Disable all IRQs */
+    IOWriteB(PIC_MASTER_DATA, 0xFF);
+    IOWriteB(PIC_SLAVE_DATA , 0xFF);
+
+
+    /* Initialize PIT Counter 0 */
+    IOWriteB(PIT_COMMAND_PORT, 0x34);
+    IOWriteB(PIT_DATA_PORT(0), 0x00);
+    IOWriteB(PIT_DATA_PORT(0), 0x00);
+
+    /* Initialize PIT Counter 1 */
+    IOWriteB(PIT_COMMAND_PORT, 0x74);
+    IOWriteB(PIT_DATA_PORT(1), 0x00);
+    IOWriteB(PIT_DATA_PORT(1), 0x00);
+
+    /* Initialize PIT Counter 2 */
+    IOWriteB(PIT_COMMAND_PORT, 0xB4);
+    IOWriteB(PIT_DATA_PORT(2), 0x00);
+    IOWriteB(PIT_DATA_PORT(2), 0x00);
+
+    EnableHwIRQ(0, BiosTimerIrq);
+}
+
+static VOID InitializeBiosInt32(VOID)
+{
+    USHORT i;
+    // USHORT Offset = 0;
+
+    /* Initialize the callback context */
+    InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000);
+
+    /* Register the BIOS 32-bit Interrupts */
+    for (i = 0x00; i <= 0xFF; i++)
+    {
+        // Offset += RegisterInt32(MAKELONG(Offset, BIOS_SEGMENT), i, NULL, NULL);
+        BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset,
+                                                         BiosContext.Segment),
+                                                i, NULL, NULL);
+    }
+
+    /* Initialize the exception vector interrupts to a default Exception handler */
+    for (i = 0; i < 8; i++)
+        RegisterBiosInt32(i, BiosException);
+
+    /* Initialize HW vector interrupts to a default HW handler */
+    for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++)
+        RegisterBiosInt32(i, BiosHandleMasterPicIRQ);
+    for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT  + 8; i++)
+        RegisterBiosInt32(i, BiosHandleSlavePicIRQ);
+
+    /* Initialize software vector handlers */
+    RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService    );
+    RegisterBiosInt32(BIOS_MEMORY_SIZE        , BiosGetMemorySize       );
+    RegisterBiosInt32(BIOS_MISC_INTERRUPT     , BiosMiscService         );
+    RegisterBiosInt32(BIOS_TIME_INTERRUPT     , BiosTimeService         );
+    RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
+
+    /* Some interrupts are in fact addresses to tables */
+    ((PULONG)BaseAddress)[0x1E] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x41] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x46] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x48] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * The BIOS POST (Power On-Self Test)
+ */
+BOOLEAN Bios32Initialize(VOID)
+{
+    BOOLEAN Success;
+    UCHAR Low, High;
+
+    /* Initialize the stack */
+    // That's what says IBM... (stack at 30:00FF going downwards)
+    // setSS(0x0000);
+    // setSP(0x0400);
+    setSS(0x0050);  // Stack at 50:0400, going downwards
+    setSP(0x0400);
+
+    /* Set data segment */
+    setDS(BDA_SEGMENT);
+
+    /* Initialize the BDA contents */
+    Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
+
+    /*
+     * Retrieve the conventional memory size
+     * in kB from CMOS, typically 640 kB.
+     */
+    IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW);
+    Low  = IOReadB(CMOS_DATA_PORT);
+    IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH);
+    High = IOReadB(CMOS_DATA_PORT);
+    Bda->MemorySize = MAKEWORD(Low, High);
+
+    /* Register the BIOS 32-bit Interrupts */
+    InitializeBiosInt32();
+
+    /* Initialize platform hardware (PIC/PIT chips, ...) */
+    BiosHwSetup();
+
+    /* Initialize the Keyboard and Video BIOS */
+    if (!KbdBios32Initialize() || !VidBios32Initialize()) return FALSE;
+
+    ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
+
+    /* Load some ROMs */
+    Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
+    DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    SearchAndInitRoms(&BiosContext);
+
+    /* We are done */
+    return TRUE;
+}
+
+VOID Bios32Cleanup(VOID)
+{
+    VidBios32Cleanup();
+    KbdBios32Cleanup();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/bios32.h b/subsystems/ntvdm/bios/bios32/bios32.h
new file mode 100644 (file)
index 0000000..4bd5d30
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bios32.h
+ * PURPOSE:         VDM 32-bit BIOS
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _BIOS32_H_
+#define _BIOS32_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+// #include "../bios.h"
+
+/* DEFINES ********************************************************************/
+
+// #define BIOS_EQUIPMENT_INTERRUPT    0x11
+// #define BIOS_MEMORY_SIZE            0x12
+// #define BIOS_MISC_INTERRUPT         0x15
+// #define BIOS_TIME_INTERRUPT         0x1A
+// #define BIOS_SYS_TIMER_INTERRUPT    0x1C
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN Bios32Initialize(VOID);
+VOID Bios32Cleanup(VOID);
+
+#endif // _BIOS32_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/bios32p.h b/subsystems/ntvdm/bios/bios32/bios32p.h
new file mode 100644 (file)
index 0000000..604fda3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bios32.h
+ * PURPOSE:         VDM 32-bit BIOS
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _BIOS32P_H_
+#define _BIOS32P_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include "../bios.h"
+
+/**/ #include "callback.h" /**/
+
+/* DEFINES ********************************************************************/
+
+#define BIOS_PIC_MASTER_INT 0x08
+#define BIOS_PIC_SLAVE_INT  0x70
+
+#define BIOS_EQUIPMENT_INTERRUPT    0x11
+#define BIOS_MEMORY_SIZE            0x12
+#define BIOS_MISC_INTERRUPT         0x15
+#define BIOS_TIME_INTERRUPT         0x1A
+#define BIOS_SYS_TIMER_INTERRUPT    0x1C
+
+/* FUNCTIONS ******************************************************************/
+
+extern CALLBACK16 BiosContext;
+#define RegisterBiosInt32(IntNumber, IntHandler) \
+do { \
+    BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset,  \
+                                                     BiosContext.Segment),    \
+                                            (IntNumber), (IntHandler), NULL); \
+} while(0);
+
+VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func);
+VOID PicIRQComplete(LPWORD Stack);
+
+#endif // _BIOS32P_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/kbdbios32.c b/subsystems/ntvdm/bios/bios32/kbdbios32.c
new file mode 100644 (file)
index 0000000..716af1f
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            kbdbios32.c
+ * PURPOSE:         VDM Keyboard 32-bit BIOS
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "kbdbios32.h"
+#include "../kbdbios.h"
+#include "bios32p.h"
+
+#include "io.h"
+#include "hardware/ps2.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BYTE BiosKeyboardMap[256];
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static BOOLEAN BiosKbdBufferPush(WORD Data)
+{
+    /* Get the location of the element after the tail */
+    WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD);
+
+    /* Wrap it around if it's at or beyond the end */
+    if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
+
+    /* If it's full, fail */
+    if (NextElement == Bda->KeybdBufferHead) return FALSE;
+
+    /* Put the value in the queue */
+    *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
+    Bda->KeybdBufferTail += sizeof(WORD);
+
+    /* Check if we are at, or have passed, the end of the buffer */
+    if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
+    {
+        /* Return it to the beginning */
+        Bda->KeybdBufferTail = Bda->KeybdBufferStart;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+static BOOLEAN BiosKbdBufferTop(LPWORD Data)
+{
+    /* If it's empty, fail */
+    if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
+
+    /* Otherwise, get the value and return success */
+    *Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
+
+    return TRUE;
+}
+
+static BOOLEAN BiosKbdBufferPop(VOID)
+{
+    /* If it's empty, fail */
+    if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
+
+    /* Remove the value from the queue */
+    Bda->KeybdBufferHead += sizeof(WORD);
+
+    /* Check if we are at, or have passed, the end of the buffer */
+    if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
+    {
+        /* Return it to the beginning */
+        Bda->KeybdBufferHead = Bda->KeybdBufferStart;
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+static WORD BiosPeekCharacter(VOID)
+{
+    WORD CharacterData = 0;
+
+    /* Get the key from the queue, but don't remove it */
+    if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
+    else return 0xFFFF;
+}
+
+static WORD BiosGetCharacter(VOID)
+{
+    WORD CharacterData = 0;
+
+    /* Check if there is a key available, and if so, remove it from the queue */
+    if (BiosKbdBufferTop(&CharacterData)) BiosKbdBufferPop();
+    else CharacterData = 0xFFFF;
+
+    return CharacterData;
+}
+
+static VOID WINAPI BiosKeyboardService(LPWORD Stack)
+{
+    switch (getAH())
+    {
+        /* Wait for keystroke and read */
+        case 0x00:
+        /* Wait for extended keystroke and read */
+        case 0x10:  // FIXME: Temporarily do the same as INT 16h, 00h
+        {
+            /* Read the character (and wait if necessary) */
+            WORD Character = BiosGetCharacter();
+
+            if (Character == 0xFFFF)
+            {
+                /* No key available. Set the handler CF to repeat the BOP */
+                setCF(1);
+                break;
+            }
+
+            setAX(Character);
+
+            break;
+        }
+
+        /* Get keystroke status */
+        case 0x01:
+        /* Get extended keystroke status */
+        case 0x11:  // FIXME: Temporarily do the same as INT 16h, 01h
+        {
+            WORD Character = BiosPeekCharacter();
+
+            if (Character != 0xFFFF)
+            {
+                /* There is a character, clear ZF and return it */
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
+                setAX(Character);
+            }
+            else
+            {
+                /* No character, set ZF */
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
+            }
+
+            break;
+        }
+
+        /* Get shift status */
+        case 0x02:
+        {
+            /* Return the lower byte of the keyboard shift status word */
+            setAL(LOBYTE(Bda->KeybdShiftFlags));
+            break;
+        }
+
+        /* Reserved */
+        case 0x04:
+        {
+            DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
+            break;
+        }
+
+        /* Push keystroke */
+        case 0x05:
+        {
+            /* Return 0 if success, 1 if failure */
+            setAL(BiosKbdBufferPush(getCX()) == FALSE);
+            break;
+        }
+
+        /* Get extended shift status */
+        case 0x12:
+        {
+            /*
+             * Be careful! The returned word is similar to Bda->KeybdShiftFlags
+             * but the high byte is organized differently:
+             * the bytes 2 and 3 of the high byte are not the same...
+             */
+            WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
+
+            /* Return the extended keyboard shift status word */
+            setAX(KeybdShiftFlags);
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
+                    getAH());
+        }
+    }
+}
+
+// Keyboard IRQ 1
+static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
+{
+    BYTE ScanCode, VirtualKey;
+    WORD Character;
+
+    /* Get the scan code and virtual key code */
+    ScanCode = IOReadB(PS2_DATA_PORT);
+    VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
+
+    /* Check if this is a key press or release */
+    if (!(ScanCode & (1 << 7)))
+    {
+        /* Key press */
+        if (VirtualKey == VK_NUMLOCK ||
+            VirtualKey == VK_CAPITAL ||
+            VirtualKey == VK_SCROLL  ||
+            VirtualKey == VK_INSERT)
+        {
+            /* For toggle keys, toggle the lowest bit in the keyboard map */
+            BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
+        }
+
+        /* Set the highest bit */
+        BiosKeyboardMap[VirtualKey] |= (1 << 7);
+
+        /* Find out which character this is */
+        Character = 0;
+        if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
+        {
+            /* Not ASCII */
+            Character = 0;
+        }
+
+        /* Push it onto the BIOS keyboard queue */
+        BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
+    }
+    else
+    {
+        /* Key release, unset the highest bit */
+        BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
+    }
+
+    /* Clear the keyboard flags */
+    Bda->KeybdShiftFlags = 0;
+
+    /* Set the appropriate flags based on the state */
+    if (BiosKeyboardMap[VK_RSHIFT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
+    if (BiosKeyboardMap[VK_LSHIFT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
+    if (BiosKeyboardMap[VK_CONTROL]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
+    if (BiosKeyboardMap[VK_MENU]     & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
+    if (BiosKeyboardMap[VK_SCROLL]   & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
+    if (BiosKeyboardMap[VK_NUMLOCK]  & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
+    if (BiosKeyboardMap[VK_CAPITAL]  & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
+    if (BiosKeyboardMap[VK_INSERT]   & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
+    if (BiosKeyboardMap[VK_RMENU]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
+    if (BiosKeyboardMap[VK_LMENU]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
+    if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
+    if (BiosKeyboardMap[VK_PAUSE]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
+    if (BiosKeyboardMap[VK_SCROLL]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
+    if (BiosKeyboardMap[VK_NUMLOCK]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK;
+    if (BiosKeyboardMap[VK_CAPITAL]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
+    if (BiosKeyboardMap[VK_INSERT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
+
+    PicIRQComplete(Stack);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN KbdBios32Initialize(VOID)
+{
+    /* Initialize the common Keyboard BIOS Support Library */
+    if (!KbdBiosInitialize()) return FALSE;
+
+    /* Initialize the BDA */
+    Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
+    Bda->KeybdBufferEnd   = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
+    Bda->KeybdBufferHead  = Bda->KeybdBufferTail = 0;
+
+    /* Register the BIOS 32-bit Interrupts */
+
+    /* Initialize software vector handlers */
+    RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
+
+    /* Set up the HW vector interrupts */
+    EnableHwIRQ(1, BiosKeyboardIrq);
+    // EnableHwIRQ(12, BiosMouseIrq);
+
+    return TRUE;
+}
+
+VOID KbdBios32Cleanup(VOID)
+{
+    /* Cleanup the common Keyboard BIOS Support Library */
+    KbdBiosCleanup();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/kbdbios32.h b/subsystems/ntvdm/bios/bios32/kbdbios32.h
new file mode 100644 (file)
index 0000000..b5f9c14
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            kbdbios32.h
+ * PURPOSE:         VDM Keyboard 32-bit BIOS
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _KBDBIOS32_H_
+#define _KBDBIOS32_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+// #define BIOS_KBD_INTERRUPT      0x16
+
+#define BIOS_KBD_BUFFER_SIZE    16
+
+#define BDA_KBDFLAG_RSHIFT      (1 << 0)
+#define BDA_KBDFLAG_LSHIFT      (1 << 1)
+#define BDA_KBDFLAG_CTRL        (1 << 2)
+#define BDA_KBDFLAG_ALT         (1 << 3)
+#define BDA_KBDFLAG_SCROLL_ON   (1 << 4)
+#define BDA_KBDFLAG_NUMLOCK_ON  (1 << 5)
+#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
+#define BDA_KBDFLAG_INSERT_ON   (1 << 7)
+#define BDA_KBDFLAG_RALT        (1 << 8)
+#define BDA_KBDFLAG_LALT        (1 << 9)
+#define BDA_KBDFLAG_SYSRQ       (1 << 10)
+#define BDA_KBDFLAG_PAUSE       (1 << 11)
+#define BDA_KBDFLAG_SCROLL      (1 << 12)
+#define BDA_KBDFLAG_NUMLOCK     (1 << 13)
+#define BDA_KBDFLAG_CAPSLOCK    (1 << 14)
+#define BDA_KBDFLAG_INSERT      (1 << 15)
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN KbdBios32Initialize(VOID);
+VOID KbdBios32Cleanup(VOID);
+
+#endif // _KBDBIOS32_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.c b/subsystems/ntvdm/bios/bios32/vidbios32.c
new file mode 100644 (file)
index 0000000..732776c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vidbios32.c
+ * PURPOSE:         VDM Video 32-bit BIOS
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * NOTE:            All of the real code is in bios/vidbios.c
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "vidbios32.h"
+#include "../vidbios.h"
+#include "bios32p.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN VidBios32Initialize(VOID)
+{
+    /* Initialize the common Video BIOS Support Library */
+    if (!VidBiosInitialize()) return FALSE;
+
+    /* Register the BIOS 32-bit Interrupts */
+    RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
+
+    return TRUE;
+}
+
+VOID VidBios32Cleanup(VOID)
+{
+    /* Cleanup the common Video BIOS Support Library */
+    VidBiosCleanup();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.h b/subsystems/ntvdm/bios/bios32/vidbios32.h
new file mode 100644 (file)
index 0000000..46b853b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vidbios32.h
+ * PURPOSE:         VDM Video 32-bit BIOS
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * NOTE:            All of the real code is in bios/vidbios.c
+ */
+
+#ifndef _VIDBIOS32_H_
+#define _VIDBIOS32_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+// #define BIOS_VIDEO_INTERRUPT    0x10
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN VidBios32Initialize(VOID);
+VOID VidBios32Cleanup(VOID);
+
+#endif // _VIDBIOS32_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/kbdbios.c b/subsystems/ntvdm/bios/kbdbios.c
new file mode 100644 (file)
index 0000000..7255086
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            kbdbios.c
+ * PURPOSE:         VDM Keyboard BIOS Support Library
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+#include "bop.h"
+
+#include "bios.h"
+// #include "kbdbios.h"
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define BOP_KBD_IRQ     0x09
+#define BOP_KBD_INT     0x16
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+static VOID WINAPI KbdBiosIRQ(LPWORD Stack)
+{
+    DPRINT1("KbdBiosIRQ is UNIMPLEMENTED\n");
+}
+
+static VOID WINAPI KbdBiosINT(LPWORD Stack)
+{
+    DPRINT1("KbdBiosINT is UNIMPLEMENTED\n");
+}
+
+BOOLEAN KbdBiosInitialize(VOID)
+{
+    /* Register the BIOS support BOPs */
+    RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ);
+    RegisterBop(BOP_KBD_INT, KbdBiosINT);
+
+    return TRUE;
+}
+
+VOID KbdBiosCleanup(VOID)
+{
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/kbdbios.h b/subsystems/ntvdm/bios/kbdbios.h
new file mode 100644 (file)
index 0000000..1d8798a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            kbdbios.h
+ * PURPOSE:         VDM Keyboard BIOS Support Library
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _KBDBIOS_H_
+#define _KBDBIOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define BIOS_KBD_INTERRUPT      0x16
+
+#define BIOS_KBD_BUFFER_SIZE    16
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN KbdBiosInitialize(VOID);
+VOID KbdBiosCleanup(VOID);
+
+#endif // _KBDBIOS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/rom.c b/subsystems/ntvdm/bios/rom.c
new file mode 100644 (file)
index 0000000..e4dbc6b
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            rom.c
+ * PURPOSE:         ROM Support Functions
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+#include "utils.h"
+
+#include "rom.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static HANDLE
+OpenRomFile(IN  PCSTR  RomFileName,
+            OUT PULONG RomSize OPTIONAL)
+{
+    HANDLE hRomFile;
+    ULONG  ulRomSize = 0;
+
+    /* Open the ROM image file */
+    hRomFile = FileOpen(RomFileName, &ulRomSize);
+
+    /* If we failed, bail out */
+    if (hRomFile == NULL) return NULL;
+
+    /*
+     * The size of the ROM image file is at most 256kB. For instance,
+     * the SeaBIOS image, which includes also expansion ROMs inside it,
+     * covers the range C000:0000 to F000:FFFF .
+     */
+    if (ulRomSize > 0x40000)
+    {
+        /* We failed, bail out */
+        DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize);
+        FileClose(hRomFile);
+        return NULL;
+    }
+
+    /* Success, return file handle and size if needed */
+    if (RomSize) *RomSize = ulRomSize;
+    return hRomFile;
+}
+
+static BOOLEAN
+LoadRomFileByHandle(IN  HANDLE RomFileHandle,
+                    IN  PVOID  RomLocation,
+                    IN  ULONG  RomSize,
+                    OUT PULONG BytesRead)
+{
+    /*
+     * The size of the ROM image file is at most 256kB. For instance,
+     * the SeaBIOS image, which includes also expansion ROMs inside it,
+     * covers the range C000:0000 to F000:FFFF .
+     */
+    if (RomSize > 0x40000)
+    {
+        DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize);
+        return FALSE;
+    }
+
+    /* Attempt to load the ROM image file into memory */
+    return FileLoadByHandle(RomFileHandle,
+                            REAL_TO_PHYS(RomLocation),
+                            RomSize,
+                            BytesRead);
+}
+
+static UCHAR
+ComputeChecksum(IN ULONG RomLocation,
+                IN ULONG RomSize)
+{
+    ULONG RomLastAddress = RomLocation + RomSize;
+    UCHAR Sum = 0x00;   // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
+
+    while (RomLocation < RomLastAddress)
+    {
+        Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
+        ++RomLocation;
+    }
+
+    return Sum;
+}
+
+static VOID
+InitRomRange(IN PCALLBACK16 Context,
+             IN ULONG Start,
+             IN ULONG End,
+             IN ULONG Increment)
+{
+    ULONG Address, AddressBoot;
+    ULONG RomSize;
+    UCHAR Checksum;
+
+    for (Address = Start; Address < End; Address += Increment)
+    {
+        /* Does the ROM have a valid signature? */
+        if (*(PUSHORT)REAL_TO_PHYS(Address) == OPTION_ROM_SIGNATURE)
+        {
+            /* Check the control sum of the ROM */
+
+            /*
+             * If this is an adapter ROM (Start: C8000, End: E0000), its
+             * reported size is stored in byte 2 of the ROM.
+             *
+             * If this is an expansion ROM (Start: E0000, End: F0000),
+             * its real length is 64kB.
+             */
+            RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512;
+            if (Address >= 0xE0000) RomSize = 0x10000;
+
+            Checksum = ComputeChecksum(Address, RomSize);
+            if (Checksum == 0x00)
+            {
+                AddressBoot = Address + 3;
+                DPRINT1("Going to run @ address 0x%p\n", AddressBoot);
+
+                AddressBoot = MAKELONG((AddressBoot & 0xFFFF), (AddressBoot & 0xF0000) >> 4);
+                // setDS((Address & 0xF0000) >> 4);
+                setDS((Address & 0xFF000) >> 4);
+                RunCallback16(Context, AddressBoot);
+                // Call16((AddressBoot & 0xF0000) >> 4, (AddressBoot & 0xFFFF));
+
+                DPRINT1("Rom @ address 0x%p initialized\n", Address);
+            }
+            else
+            {
+                DPRINT1("Rom @ address 0x%p has invalid checksum of 0x%02x\n", Address, Checksum);
+            }
+        }
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN
+LoadBios(IN  PCSTR  BiosFileName,
+         OUT PVOID* BiosLocation OPTIONAL,
+         OUT PULONG BiosSize     OPTIONAL)
+{
+    BOOLEAN Success;
+    HANDLE  hBiosFile;
+    ULONG   ulBiosSize = 0;
+    PVOID   pBiosLocation;
+
+    /* Open the BIOS image file */
+    hBiosFile = OpenRomFile(BiosFileName, &ulBiosSize);
+
+    /* If we failed, bail out */
+    if (hBiosFile == NULL) return FALSE;
+
+    /* BIOS location needs to be aligned on 32-bit boundary */
+    // (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize)
+    pBiosLocation = MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize, sizeof(ULONG));
+
+    /* Attempt to load the BIOS image file into memory */
+    Success = LoadRomFileByHandle(hBiosFile,
+                                  pBiosLocation,
+                                  ulBiosSize,
+                                  &ulBiosSize);
+    DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    /* Close the BIOS image file */
+    FileClose(hBiosFile);
+
+    /* In case of success, return BIOS location and size if needed */
+    if (Success)
+    {
+        if (BiosLocation) *BiosLocation = pBiosLocation;
+        if (BiosSize)     *BiosSize     = ulBiosSize;
+    }
+
+    return Success;
+}
+
+BOOLEAN
+LoadRom(IN  PCSTR  RomFileName,
+        IN  PVOID  RomLocation,
+        OUT PULONG RomSize OPTIONAL)
+{
+    BOOLEAN Success;
+    HANDLE  hRomFile;
+    ULONG   ulRomSize = 0;
+
+    /* Open the ROM image file */
+    hRomFile = OpenRomFile(RomFileName, &ulRomSize);
+
+    /* If we failed, bail out */
+    if (hRomFile == NULL) return FALSE;
+
+    /* Attempt to load the ROM image file into memory */
+    Success = LoadRomFileByHandle(hRomFile,
+                                  RomLocation,
+                                  ulRomSize,
+                                  &ulRomSize);
+    DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    /* Close the ROM image file and return */
+    FileClose(hRomFile);
+
+    /* In case of success, return ROM size if needed */
+    if (Success)
+    {
+        if (RomSize) *RomSize = ulRomSize;
+    }
+
+    return Success;
+}
+
+VOID
+SearchAndInitRoms(IN PCALLBACK16 Context)
+{
+    /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
+    InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);
+
+    /* Expansion ROM -- Start: E0000, End: F0000, 64kB block */
+    InitRomRange(Context, 0xE0000, 0xEFFFF, 0x10000);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/rom.h b/subsystems/ntvdm/bios/rom.h
new file mode 100644 (file)
index 0000000..01f95e8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            rom.h
+ * PURPOSE:         ROM Support Functions
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _ROM_H_
+#define _ROM_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define ROM_AREA_START  0xE0000
+#define ROM_AREA_END    0xFFFFF
+
+#define OPTION_ROM_SIGNATURE    0xAA55
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+LoadBios(IN  PCSTR  BiosFileName,
+         OUT PVOID* BiosLocation OPTIONAL,
+         OUT PULONG BiosSize     OPTIONAL);
+
+BOOLEAN
+LoadRom(IN  PCSTR  RomFileName,
+        IN  PVOID  RomLocation,
+        OUT PULONG RomSize OPTIONAL);
+
+VOID
+SearchAndInitRoms(IN PCALLBACK16 Context);
+
+#endif // _ROM_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/vidbios.c b/subsystems/ntvdm/bios/vidbios.c
new file mode 100644 (file)
index 0000000..41d22d3
--- /dev/null
@@ -0,0 +1,1600 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vidbios.c
+ * PURPOSE:         VDM Video BIOS Support Library
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+#include "bop.h"
+
+#include "bios.h"
+// #include "vidbios.h"
+
+#include "io.h"
+#include "hardware/vga.h"
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define BOP_VIDEO_INT   0x10
+
+/* MACROS *********************************************************************/
+
+//
+// These macros are defined for ease-of-use of some VGA I/O ports
+// whose addresses depend whether we are in Monochrome or Colour mode.
+//
+#define VGA_INSTAT1_READ    Bda->CrtBasePort + 6    // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR
+#define VGA_CRTC_INDEX      Bda->CrtBasePort        // VGA_CRTC_INDEX_MONO   or VGA_CRTC_INDEX_COLOR
+#define VGA_CRTC_DATA       Bda->CrtBasePort + 1    // VGA_CRTC_DATA_MONO    or VGA_CRTC_DATA_COLOR
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/*
+ * VGA Register Configurations for BIOS Video Modes
+ * The configurations come from DOSBox.
+ */
+static VGA_REGISTERS VideoMode_40x25_text =
+{
+    /* Miscellaneous Register */
+    0x67,
+
+    /* Sequencer Registers */
+    {0x00, 0x08, 0x03, 0x00, 0x07},
+
+    /* CRTC Registers */
+    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+     0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_80x25_text =
+{
+    /* Miscellaneous Register */
+    0x67,
+
+    /* Sequencer Registers */
+    {0x00, 0x00, 0x03, 0x00, 0x07},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+     0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_320x200_4color =
+{
+    /* Miscellaneous Register */
+    0x63,
+
+    /* Sequencer Registers */
+    {0x00, 0x09, 0x03, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
+     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_640x200_2color =
+{
+    /* Miscellaneous Register */
+    0x63,
+
+    /* Sequencer Registers */
+    {0x00, 0x09, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+     0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_320x200_16color =
+{
+    /* Miscellaneous Register */
+    0x63,
+
+    /* Sequencer Registers */
+    {0x00, 0x09, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+//     {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+//      0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
+     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_640x200_16color =
+{
+    /* Miscellaneous Register */
+    0x63,
+
+    /* Sequencer Registers */
+    {0x00, 0x01, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+//     {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+//      0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
+     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_640x350_16color =
+{
+    /* Miscellaneous Register */
+    0xA3,
+
+    /* Sequencer Registers */
+    {0x00, 0x01, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+     0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_640x480_2color =
+{
+    /* Miscellaneous Register */
+    0xE3,
+
+    /* Sequencer Registers */
+    {0x00, 0x01, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_640x480_16color =
+{
+    /* Miscellaneous Register */
+    0xE3,
+
+    /* Sequencer Registers */
+    {0x00, 0x01, 0x0F, 0x00, 0x02},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+     0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
+};
+
+static VGA_REGISTERS VideoMode_320x200_256color =
+{
+    /* Miscellaneous Register */
+    0x63,
+
+    /* Sequencer Registers */
+    {0x00, 0x01, 0x0F, 0x00, 0x0E},
+
+    /* CRTC Registers */
+    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
+     0xFF},
+
+    /* GC Registers */
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},
+
+    /* AC Registers */
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+     0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
+};
+
+/* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */
+static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
+{
+    &VideoMode_40x25_text,          /* Mode 00h */      // 16 color (mono)
+    &VideoMode_40x25_text,          /* Mode 01h */      // 16 color
+    &VideoMode_80x25_text,          /* Mode 02h */      // 16 color (mono)
+    &VideoMode_80x25_text,          /* Mode 03h */      // 16 color
+    &VideoMode_320x200_4color,      /* Mode 04h */      // CGA 4 color
+    &VideoMode_320x200_4color,      /* Mode 05h */      // CGA same (m)
+    &VideoMode_640x200_2color,      /* Mode 06h */      // CGA 640*200 2 color
+    NULL,                           /* Mode 07h */      // MDA monochrome text 80*25
+    NULL,                           /* Mode 08h */      // PCjr
+    NULL,                           /* Mode 09h */      // PCjr
+    NULL,                           /* Mode 0Ah */      // PCjr
+    NULL,                           /* Mode 0Bh */      // Reserved
+    NULL,                           /* Mode 0Ch */      // Reserved
+    &VideoMode_320x200_16color,     /* Mode 0Dh */      // EGA 320*200 16 color
+    &VideoMode_640x200_16color,     /* Mode 0Eh */      // EGA 640*200 16 color
+    NULL,                           /* Mode 0Fh */      // EGA 640*350 mono
+    &VideoMode_640x350_16color,     /* Mode 10h */      // EGA 640*350 HiRes 16 color
+    &VideoMode_640x480_2color,      /* Mode 11h */      // VGA 640*480 mono
+    &VideoMode_640x480_16color,     /* Mode 12h */      // VGA
+    &VideoMode_320x200_256color,    /* Mode 13h */      // VGA
+};
+
+// FIXME: Are they computable with the previous data ??
+// Values taken from DOSBox.
+static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] =
+{
+    0x0800, 0x0800, 0x1000, 0x1000,
+    0x4000, 0x4000, 0x4000, 0x1000,
+    0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x2000, 0x4000, 0x8000,
+    0x8000, 0xA000, 0xA000, 0x2000
+};
+
+/*
+ * BIOS Mode Palettes
+ *
+ * Many people have different versions of those palettes
+ * (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html ,
+ * etc...) A choice should be made at some point.
+ */
+
+// This is the same as EgaPalette__HiRes
+static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
+    RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
+
+    RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
+    RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
+    RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
+    RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
+
+
+    RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
+    RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
+    RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
+
+    RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
+    RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
+};
+
+// Unused at the moment
+static CONST COLORREF mtext_palette[64] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
+};
+
+// Unused at the moment
+static CONST COLORREF mtext_s3_palette[64] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
+};
+
+// Unused at the moment
+static CONST COLORREF CgaPalette[16] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
+};
+
+// Unused at the moment
+static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
+};
+
+static CONST COLORREF EgaPalette___16ColorFixed_DOSBox[VGA_MAX_COLORS / 4] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+
+
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+
+
+
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+
+
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
+};
+
+// This is the same as TextPalette
+static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
+    RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
+
+    RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
+    RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
+    RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
+    RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
+
+
+    RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
+    RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
+    RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
+
+    RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
+    RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
+};
+
+#define USE_REACTOS_COLORS
+// #define USE_DOSBOX_COLORS
+
+/*
+ * Same palette as the default one 'VgaDefaultPalette' in vga.c
+ */
+#if defined(USE_REACTOS_COLORS)
+
+// ReactOS colors
+static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
+    RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
+    RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
+    RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
+    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
+    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
+    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
+    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
+    RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
+    RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
+    RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
+    RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
+    RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
+    RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
+    RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
+    RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
+    RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
+    RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
+    RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
+    RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
+    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
+    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
+    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
+    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
+    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
+    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
+    RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
+    RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
+    RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
+    RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
+    RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
+    RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
+    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
+    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
+    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
+    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
+    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
+    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
+    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
+    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
+    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
+    RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
+    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
+    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
+    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
+    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
+    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
+    RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
+    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
+    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
+    RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
+    RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
+    RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
+    RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
+    RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
+    RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
+};
+
+#elif defined(USE_DOSBOX_COLORS)
+
+// DOSBox colors
+static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
+    RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
+    RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
+    RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
+    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
+    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
+    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
+    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
+    RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
+    RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
+
+    RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
+    RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
+    RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
+    RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
+    RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
+    RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
+    RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
+    RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
+    RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
+    RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
+    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
+    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
+    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
+    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
+    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
+    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
+
+    RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
+    RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
+    RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
+    RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
+    RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
+    RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
+    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
+    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
+    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
+    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
+    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
+    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
+    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
+    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
+    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
+    RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
+
+    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
+    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
+    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
+    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
+    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
+    RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
+    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
+    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
+    RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
+    RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
+    RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
+    RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
+    RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
+    RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
+};
+
+#endif
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
+{
+    INT i, j;
+    INT Counter = 0;
+    WORD Character;
+    DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+    for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+    {
+        for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+        {
+            /* Read from video memory */
+            EmulatorReadMemory(&EmulatorContext,
+                               VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+                               (LPVOID)&Character,
+                               sizeof(WORD));
+
+            /* Write the data to the buffer in row order */
+            Buffer[Counter++] = Character;
+        }
+    }
+}
+
+static VOID VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
+{
+    INT i, j;
+    INT Counter = 0;
+    WORD Character;
+    DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+    for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+    {
+        for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+        {
+            Character = Buffer[Counter++];
+
+            /* Write to video memory */
+            EmulatorWriteMemory(&EmulatorContext,
+                                VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+                                (LPVOID)&Character,
+                                sizeof(WORD));
+        }
+    }
+}
+
+static BOOLEAN VidBiosScrollWindow(INT Direction,
+                                   DWORD Amount,
+                                   SMALL_RECT Rectangle,
+                                   BYTE Page,
+                                   BYTE FillAttribute)
+{
+    DWORD i;
+    LPWORD WindowData;
+    WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
+    WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
+    DWORD WindowSize = WindowWidth * WindowHeight;
+
+    /* Allocate a buffer for the window */
+    WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
+                                   HEAP_ZERO_MEMORY,
+                                   WindowSize * sizeof(WORD));
+    if (WindowData == NULL) return FALSE;
+
+    /* Read the window data */
+    VidBiosReadWindow(WindowData, Rectangle, Page);
+
+    if ((Amount == 0)
+        || (((Direction == SCROLL_DIRECTION_UP)
+        || (Direction == SCROLL_DIRECTION_DOWN))
+        && (Amount >= WindowHeight))
+        || (((Direction == SCROLL_DIRECTION_LEFT)
+        || (Direction == SCROLL_DIRECTION_RIGHT))
+        && (Amount >= WindowWidth)))
+    {
+        /* Fill the window */
+        for (i = 0; i < WindowSize; i++)
+        {
+            WindowData[i] = MAKEWORD(' ', FillAttribute);
+        }
+
+        goto Done;
+    }
+
+    switch (Direction)
+    {
+        case SCROLL_DIRECTION_UP:
+        {
+            RtlMoveMemory(WindowData,
+                          &WindowData[WindowWidth * Amount],
+                          (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+            for (i = 0; i < Amount * WindowWidth; i++)
+            {
+                WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
+            }
+
+            break;
+        }
+
+        case SCROLL_DIRECTION_DOWN:
+        {
+            RtlMoveMemory(&WindowData[WindowWidth * Amount],
+                          WindowData,
+                          (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+            for (i = 0; i < Amount * WindowWidth; i++)
+            {
+                WindowData[i] = MAKEWORD(' ', FillAttribute);
+            }
+
+            break;
+        }
+
+        default:
+        {
+            // TODO: NOT IMPLEMENTED!
+            UNIMPLEMENTED;
+        }
+    }
+
+Done:
+    /* Write back the window data */
+    VidBiosWriteWindow(WindowData, Rectangle, Page);
+
+    /* Free the window buffer */
+    HeapFree(GetProcessHeap(), 0, WindowData);
+
+    return TRUE;
+}
+
+static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
+{
+    INT i;
+
+    if (Registers == NULL) return FALSE;
+
+    /* Disable interrupts */
+    setIF(0);
+
+    /*
+     * Set the CRT base address according to the selected mode,
+     * monochrome or color. The following macros:
+     * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
+     * used to access the correct VGA I/O ports.
+     */
+    Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
+                                                : VGA_CRTC_INDEX_MONO;
+
+    /* Write the misc register */
+    IOWriteB(VGA_MISC_WRITE, Registers->Misc);
+
+    /* Synchronous reset on */
+    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+    IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
+
+    /* Write the sequencer registers */
+    for (i = 1; i < VGA_SEQ_MAX_REG; i++)
+    {
+        IOWriteB(VGA_SEQ_INDEX, i);
+        IOWriteB(VGA_SEQ_DATA, Registers->Sequencer[i]);
+    }
+
+    /* Synchronous reset off */
+    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+    IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
+
+    /* Unlock CRTC registers 0-7 */
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
+    IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) | 0x80);
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
+    IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) & ~0x80);
+    // Make sure they remain unlocked
+    Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
+    Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
+
+    /* Write the CRTC registers */
+    for (i = 0; i < VGA_CRTC_MAX_REG; i++)
+    {
+        IOWriteB(VGA_CRTC_INDEX, i);
+        IOWriteB(VGA_CRTC_DATA, Registers->CRT[i]);
+    }
+
+    /* Write the GC registers */
+    for (i = 0; i < VGA_GC_MAX_REG; i++)
+    {
+        IOWriteB(VGA_GC_INDEX, i);
+        IOWriteB(VGA_GC_DATA, Registers->Graphics[i]);
+    }
+
+    /* Write the AC registers */
+    // DbgPrint("\n");
+    for (i = 0; i < VGA_AC_MAX_REG; i++)
+    {
+        IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+        IOWriteB(VGA_AC_INDEX, i);
+        IOWriteB(VGA_AC_WRITE, Registers->Attribute[i]);
+        // DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]);
+    }
+    // DbgPrint("\n");
+
+    /* Set the PEL mask */
+    IOWriteB(VGA_DAC_MASK, 0xFF);
+
+    /* Enable screen and disable palette access */
+    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+    IOWriteB(VGA_AC_INDEX, 0x20);
+
+    /* Enable interrupts */
+    setIF(1);
+
+    return TRUE;
+}
+
+static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
+{
+    ULONG i;
+
+    // /* Disable screen and enable palette access */
+    // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+    // IOWriteB(VGA_AC_INDEX, 0x00);
+
+    for (i = 0; i < Size; i++)
+    {
+        IOWriteB(VGA_DAC_WRITE_INDEX, i);
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
+    }
+
+    /* The following step might be optional */
+    for (i = Size; i < VGA_MAX_COLORS; i++)
+    {
+        IOWriteB(VGA_DAC_WRITE_INDEX, i);
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
+        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
+    }
+
+    /* Enable screen and disable palette access */
+    // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+    // IOWriteB(VGA_AC_INDEX, 0x20);
+}
+
+static VOID VgaChangePalette(BYTE ModeNumber)
+{
+    const COLORREF* Palette;
+    ULONG Size;
+
+    if (ModeNumber >= 0x13)
+    {
+        /* VGA modes */
+        Palette = VgaPalette;
+        Size    = sizeof(VgaPalette)/sizeof(VgaPalette[0]);
+    }
+    else if (ModeNumber == 0x10)
+    {
+        /* EGA HiRes mode */
+        Palette = EgaPalette__HiRes;
+        Size    = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]);
+    }
+    else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
+    {
+        /* EGA modes */
+        Palette = EgaPalette___16ColorFixed_DOSBox;
+        Size    = sizeof(EgaPalette___16ColorFixed_DOSBox)/sizeof(EgaPalette___16ColorFixed_DOSBox[0]);
+    }
+
+    VgaSetPalette(Palette, Size);
+}
+
+static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
+{
+    /* Make sure the selected video page is valid */
+    if (Page >= BIOS_MAX_PAGES) return;
+
+    /* Get the cursor location */
+    *Row    = HIBYTE(Bda->CursorPosition[Page]);
+    *Column = LOBYTE(Bda->CursorPosition[Page]);
+}
+
+static VOID VidBiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
+{
+    /* Make sure the selected video page is valid */
+    if (Page >= BIOS_MAX_PAGES) return;
+
+    /* Update the position in the BDA */
+    Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
+
+    /* Check if this is the current video page */
+    if (Page == Bda->VideoPage)
+    {
+        WORD Offset = Row * Bda->ScreenColumns + Column;
+
+        /* Modify the CRTC registers */
+        IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+        IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset));
+        IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+        IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset));
+    }
+}
+
+VOID VidBiosSyncCursorPosition(VOID)
+{
+    BYTE Row, Column;
+    BYTE Low, High;
+    SHORT ScreenColumns = VgaGetDisplayResolution().X;
+    WORD Offset;
+
+    /* Get the cursor location */
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+    Low  = IOReadB(VGA_CRTC_DATA);
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+    High = IOReadB(VGA_CRTC_DATA);
+
+    Offset = MAKEWORD(Low, High);
+
+    Row    = (BYTE)(Offset / ScreenColumns);
+    Column = (BYTE)(Offset % ScreenColumns);
+
+    /* Synchronize our cursor position with VGA */
+    VidBiosSetCursorPosition(Row, Column, Bda->VideoPage);
+}
+
+BYTE VidBiosGetVideoMode(VOID)
+{
+    return Bda->VideoMode;
+}
+
+static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
+{
+    BYTE Page;
+
+    COORD Resolution;
+    PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
+
+    DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
+
+    if (!VgaSetRegisters(VgaMode)) return FALSE;
+
+    VgaChangePalette(ModeNumber);
+
+    /*
+     * IBM standard modes do not clear the screen if the
+     * high bit of AL is set (EGA or higher only).
+     * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
+     * for more information.
+     */
+    // if ((ModeNumber & 0x08) == 0) VgaClearMemory();
+    VgaClearMemory();
+
+    // Bda->CrtModeControl;
+    // Bda->CrtColorPaletteMask;
+    // Bda->EGAFlags;
+    // Bda->VGAFlags;
+
+    /* Update the values in the BDA */
+    Bda->VideoMode       = ModeNumber;
+    Bda->VideoPageSize   = VideoModePageSize[ModeNumber];
+    Bda->VideoPage       = 0;
+    Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
+
+    /* Set the start address in the CRTC */
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
+    IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
+    IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
+
+    /* Update the character height */
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
+    Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F);
+
+    /* Update the screen size */
+    Resolution = VgaGetDisplayResolution();
+    Bda->ScreenColumns = Resolution.X;
+    Bda->ScreenRows    = Resolution.Y - 1;
+
+    /* Set the cursor position for each page */
+    for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
+        VidBiosSetCursorPosition(0, 0, Page);
+
+    /* Refresh display */
+    VgaRefreshDisplay();
+
+    return TRUE;
+}
+
+static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber)
+{
+    BYTE Row, Column;
+
+    /* Check if the page exists */
+    if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
+
+    /* Check if this is the same page */
+    if (PageNumber == Bda->VideoPage) return TRUE;
+
+    /* Update the values in the BDA */
+    Bda->VideoPage       = PageNumber;
+    Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
+
+    /* Set the start address in the CRTC */
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
+    IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
+    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
+    IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
+
+    /*
+     * Get the cursor location (we don't update anything on the BIOS side
+     * but we update the cursor location on the VGA side).
+     */
+    VidBiosGetCursorPosition(&Row, &Column, PageNumber);
+    VidBiosSetCursorPosition(Row, Column, PageNumber);
+
+    return TRUE;
+}
+
+static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
+{
+    WORD CharData = MAKEWORD(Character, Attribute);
+    BYTE Row, Column;
+
+    /* Make sure the page exists */
+    if (Page >= BIOS_MAX_PAGES) return;
+
+    /* Get the cursor location */
+    VidBiosGetCursorPosition(&Row, &Column, Page);
+
+    if (Character == '\a')
+    {
+        /* Bell control character */
+        // NOTE: We may use what the terminal emulator offers to us...
+        Beep(800, 200);
+        return;
+    }
+    else if (Character == '\b')
+    {
+        /* Backspace control character */
+        if (Column > 0)
+        {
+            Column--;
+        }
+        else if (Row > 0)
+        {
+            Column = Bda->ScreenColumns - 1;
+            Row--;
+        }
+
+        /* Erase the existing character */
+        CharData = MAKEWORD(' ', Attribute);
+        EmulatorWriteMemory(&EmulatorContext,
+                            TO_LINEAR(TEXT_VIDEO_SEG,
+                                Page * Bda->VideoPageSize +
+                                (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+                            (LPVOID)&CharData,
+                            sizeof(WORD));
+    }
+    else if (Character == '\t')
+    {
+        /* Horizontal Tabulation control character */
+        do
+        {
+            // Taken from DOSBox
+            VidBiosPrintCharacter(' ', Attribute, Page);
+            VidBiosGetCursorPosition(&Row, &Column, Page);
+        } while (Column % 8);
+    }
+    else if (Character == '\n')
+    {
+        /* Line Feed control character */
+        Row++;
+    }
+    else if (Character == '\r')
+    {
+        /* Carriage Return control character */
+        Column = 0;
+    }
+    else
+    {
+        /* Default character */
+
+        /* Write the character */
+        EmulatorWriteMemory(&EmulatorContext,
+                            TO_LINEAR(TEXT_VIDEO_SEG,
+                                Page * Bda->VideoPageSize +
+                                (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+                            (LPVOID)&CharData,
+                            sizeof(WORD));
+
+        /* Advance the cursor */
+        Column++;
+    }
+
+    /* Check if it passed the end of the row */
+    if (Column >= Bda->ScreenColumns)
+    {
+        /* Return to the first column and go to the next line */
+        Column = 0;
+        Row++;
+    }
+
+    /* Scroll the screen up if needed */
+    if (Row > Bda->ScreenRows)
+    {
+        /* The screen must be scrolled up */
+        SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
+
+        VidBiosScrollWindow(SCROLL_DIRECTION_UP,
+                            1,
+                            Rectangle,
+                            Page,
+                            DEFAULT_ATTRIBUTE);
+
+        Row--;
+    }
+
+    /* Set the cursor position */
+    VidBiosSetCursorPosition(Row, Column, Page);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID WINAPI VidBiosVideoService(LPWORD Stack)
+{
+    switch (getAH())
+    {
+        /* Set Video Mode */
+        case 0x00:
+        {
+            VidBiosSetVideoMode(getAL());
+            break;
+        }
+
+        /* Set Text-Mode Cursor Shape */
+        case 0x01:
+        {
+            /* Update the BDA */
+            Bda->CursorStartLine = getCH();
+            Bda->CursorEndLine   = getCL();
+
+            /* Modify the CRTC registers */
+            IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
+            IOWriteB(VGA_CRTC_DATA , Bda->CursorStartLine);
+            IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
+            IOWriteB(VGA_CRTC_DATA , Bda->CursorEndLine);
+
+            break;
+        }
+
+        /* Set Cursor Position */
+        case 0x02:
+        {
+            VidBiosSetCursorPosition(getDH(), getDL(), getBH());
+            break;
+        }
+
+        /* Get Cursor Position and Shape */
+        case 0x03:
+        {
+            /* Make sure the selected video page exists */
+            if (getBH() >= BIOS_MAX_PAGES) break;
+
+            /* Return the result */
+            setAX(0);
+            setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
+            setDX(Bda->CursorPosition[getBH()]);
+            break;
+        }
+
+        /* Query Light Pen */
+        case 0x04:
+        {
+            /*
+             * On modern BIOSes, this function returns 0
+             * so that we can ignore the other registers.
+             */
+            setAX(0);
+            break;
+        }
+
+        /* Select Active Display Page */
+        case 0x05:
+        {
+            VidBiosSetVideoPage(getAL());
+            break;
+        }
+
+        /* Scroll Window Up/Down */
+        case 0x06:
+        case 0x07:
+        {
+            SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
+
+            /* Call the internal function */
+            VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
+                                                  : SCROLL_DIRECTION_DOWN,
+                                getAL(),
+                                Rectangle,
+                                Bda->VideoPage,
+                                getBH());
+
+            break;
+        }
+
+        /* Read Character and Attribute at Cursor Position */
+        case 0x08:
+        {
+            WORD  CharacterData;
+            BYTE  Page = getBH();
+            DWORD Offset;
+
+            /* Check if the page exists */
+            if (Page >= BIOS_MAX_PAGES) break;
+
+            /* Find the offset of the character */
+            Offset = Page * Bda->VideoPageSize +
+                     (HIBYTE(Bda->CursorPosition[Page])  * Bda->ScreenColumns +
+                      LOBYTE(Bda->CursorPosition[Page])) * 2;
+
+            /* Read from the video memory */
+            EmulatorReadMemory(&EmulatorContext,
+                               TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+                               (LPVOID)&CharacterData,
+                               sizeof(WORD));
+
+            /* Return the character data in AX */
+            setAX(CharacterData);
+
+            break;
+        }
+
+        /* Write Character and Attribute at Cursor Position */
+        case 0x09:
+        /* Write Character only (PCjr: + Attribute) at Cursor Position */
+        case 0x0A:
+        {
+            WORD  CharacterData = MAKEWORD(getAL(), getBL());
+            BYTE  Page = getBH();
+            DWORD Offset, Counter = getCX();
+
+            /* Check if the page exists */
+            if (Page >= BIOS_MAX_PAGES) break;
+
+            /* Find the offset of the character */
+            Offset = Page * Bda->VideoPageSize +
+                     (HIBYTE(Bda->CursorPosition[Page])  * Bda->ScreenColumns +
+                      LOBYTE(Bda->CursorPosition[Page])) * 2;
+
+            /* Write to video memory a certain number of times */
+            while (Counter > 0)
+            {
+                EmulatorWriteMemory(&EmulatorContext,
+                                    TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+                                    (LPVOID)&CharacterData,
+                                    (getAH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
+                Offset += 2;
+                Counter--;
+            }
+
+            break;
+        }
+
+        /* Teletype Output */
+        case 0x0E:
+        {
+            VidBiosPrintCharacter(getAL(), getBL(), getBH());
+            break;
+        }
+
+        /* Get Current Video Mode */
+        case 0x0F:
+        {
+            setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
+            setBX(MAKEWORD(getBL(), Bda->VideoPage));
+            break;
+        }
+
+        /* Palette Control */
+        case 0x10:
+        {
+            switch (getAL())
+            {
+                /* Set Single Palette Register */
+                case 0x00:
+                {
+                    /* Write the index */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, getBL());
+
+                    /* Write the data */
+                    IOWriteB(VGA_AC_WRITE, getBH());
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Set Overscan Color */
+                case 0x01:
+                {
+                    /* Write the index */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+                    /* Write the data */
+                    IOWriteB(VGA_AC_WRITE, getBH());
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Set All Palette Registers */
+                case 0x02:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Set the palette registers */
+                    for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
+                    {
+                        /* Write the index */
+                        IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                        IOWriteB(VGA_AC_INDEX, i);
+
+                        /* Write the data */
+                        IOWriteB(VGA_AC_WRITE, Buffer[i]);
+                    }
+
+                    /* Set the overscan register */
+                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+                    IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Get Single Palette Register */
+                case 0x07:
+                {
+                    /* Write the index */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, getBL());
+
+                    /* Read the data */
+                    setBH(IOReadB(VGA_AC_READ));
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Get Overscan Color */
+                case 0x08:
+                {
+                    /* Write the index */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+                    /* Read the data */
+                    setBH(IOReadB(VGA_AC_READ));
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Get All Palette Registers */
+                case 0x09:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Get the palette registers */
+                    for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
+                    {
+                        /* Write the index */
+                        IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                        IOWriteB(VGA_AC_INDEX, i);
+
+                        /* Read the data */
+                        Buffer[i] = IOReadB(VGA_AC_READ);
+                    }
+
+                    /* Get the overscan register */
+                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+                    Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ);
+
+                    /* Enable screen and disable palette access */
+                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+                    IOWriteB(VGA_AC_INDEX, 0x20);
+                    break;
+                }
+
+                /* Set Individual DAC Register */
+                case 0x10:
+                {
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
+
+                    /* Write the data in this order: Red, Green, Blue */
+                    IOWriteB(VGA_DAC_DATA, getDH());
+                    IOWriteB(VGA_DAC_DATA, getCH());
+                    IOWriteB(VGA_DAC_DATA, getCL());
+
+                    break;
+                }
+
+                /* Set Block of DAC Registers */
+                case 0x12:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
+
+                    for (i = 0; i < getCX(); i++)
+                    {
+                        /* Write the data in this order: Red, Green, Blue */
+                        IOWriteB(VGA_DAC_DATA, *Buffer++);
+                        IOWriteB(VGA_DAC_DATA, *Buffer++);
+                        IOWriteB(VGA_DAC_DATA, *Buffer++);
+                    }
+
+                    break;
+                }
+
+                /* Get Individual DAC Register */
+                case 0x15:
+                {
+                    /* Write the index */
+                    IOWriteB(VGA_DAC_READ_INDEX, getBL());
+
+                    /* Read the data in this order: Red, Green, Blue */
+                    setDH(IOReadB(VGA_DAC_DATA));
+                    setCH(IOReadB(VGA_DAC_DATA));
+                    setCL(IOReadB(VGA_DAC_DATA));
+
+                    break;
+                }
+
+                /* Get Block of DAC Registers */
+                case 0x17:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    IOWriteB(VGA_DAC_READ_INDEX, getBL());
+
+                    for (i = 0; i < getCX(); i++)
+                    {
+                        /* Write the data in this order: Red, Green, Blue */
+                        *Buffer++ = IOReadB(VGA_DAC_DATA);
+                        *Buffer++ = IOReadB(VGA_DAC_DATA);
+                        *Buffer++ = IOReadB(VGA_DAC_DATA);
+                    }
+
+                    break;
+                }
+
+                default:
+                {
+                    DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
+                            getAL());
+                    break;
+                }
+            }
+
+            break;
+        }
+
+        /* Alternate Function Select */
+        case 0x12:
+        {
+            DPRINT1("BIOS Function INT 12h (Alternate Function Select), BX = 0x%04X NOT IMPLEMENTED\n",
+                    getBX());
+            break;
+        }
+
+        /* Write String */
+        case 0x13:
+        {
+            DPRINT1("BIOS Function INT 13h (Write String) is UNIMPLEMENTED\n");
+            break;
+        }
+
+        /* Display combination code */
+        case 0x1A:
+        {
+            switch(getAL())
+            {
+                case 0x00: /* Get Display combiantion code */
+                   setAX(MAKEWORD(0x1A, 0x1A));
+                   setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
+                   break;
+                case 0x01: /* Set Display combination code */
+                   DPRINT1("Set Display combination code - Unsupported\n");
+                   break;
+                default:
+                   break;
+            }
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
+                    getAH());
+        }
+    }
+}
+
+
+/*
+ * Those attach / detach functions are work-in-progress
+ */
+
+static BOOL Attached = TRUE;
+
+VOID VidBiosAttachToConsole(VOID)
+{
+    // VgaRefreshDisplay();
+    if (!Attached)
+    {
+        VgaAttachToConsole();
+        Attached = TRUE;
+    }
+
+    VgaRefreshDisplay();
+    VidBiosSyncCursorPosition();
+}
+
+VOID VidBiosDetachFromConsole(VOID)
+{
+    /* Perform another screen refresh */
+    VgaRefreshDisplay();
+
+    /* Detach from the console */
+    VgaDetachFromConsole(FALSE);
+    Attached = FALSE;
+}
+
+
+BOOLEAN VidBiosInitialize(VOID)
+{
+    /* Some interrupts are in fact addresses to tables */
+    ((PULONG)BaseAddress)[0x1D] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x1F] = (ULONG)NULL;
+    // ((PULONG)BaseAddress)[0x42] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x43] = (ULONG)NULL;
+    ((PULONG)BaseAddress)[0x44] = (ULONG)NULL;
+
+    //
+    // FIXME: At the moment we always set a VGA mode. In the future,
+    // we should set this mode **only** when:
+    // - an app starts to use directly the video memory
+    //   (that should be done in emulator.c)
+    // - or starts to use non-stream I/O interrupts
+    //   (that should be done here, or maybe in VGA ??)
+    //
+
+    /* Set the default video mode */
+    VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
+
+    /* Synchronize our cursor position with VGA */
+    VidBiosSyncCursorPosition();
+
+    /* Register the BIOS support BOPs */
+    RegisterBop(BOP_VIDEO_INT, VidBiosVideoService);
+
+    return TRUE;
+}
+
+VOID VidBiosCleanup(VOID)
+{
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bios/vidbios.h b/subsystems/ntvdm/bios/vidbios.h
new file mode 100644 (file)
index 0000000..5e29147
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vidbios.h
+ * PURPOSE:         VDM Video BIOS Support Library
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _VIDBIOS_H_
+#define _VIDBIOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define BIOS_VIDEO_INTERRUPT    0x10
+
+#define CONSOLE_FONT_HEIGHT     8
+#define BIOS_DEFAULT_VIDEO_MODE 0x03
+#define BIOS_MAX_PAGES          8
+#define BIOS_MAX_VIDEO_MODE     0x13
+#define DEFAULT_ATTRIBUTE       0x07
+
+#define GRAPHICS_VIDEO_SEG      0xA000
+#define TEXT_VIDEO_SEG          0xB800
+
+enum
+{
+    SCROLL_DIRECTION_UP,
+    SCROLL_DIRECTION_DOWN,
+    SCROLL_DIRECTION_LEFT,
+    SCROLL_DIRECTION_RIGHT
+};
+
+/* FUNCTIONS ******************************************************************/
+
+VOID VidBiosSyncCursorPosition(VOID);
+
+VOID WINAPI VidBiosVideoService(LPWORD Stack);
+
+VOID VidBiosDetachFromConsole(VOID);
+VOID VidBiosAttachToConsole(VOID);
+
+BOOLEAN VidBiosInitialize(VOID);
+VOID VidBiosCleanup(VOID);
+
+#endif // _VIDBIOS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c
new file mode 100644 (file)
index 0000000..4070042
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bop.c
+ * PURPOSE:         BIOS Operation Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+// #define NDEBUG
+
+#include "emulator.h"
+#include "bop.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/*
+ * This is the list of registered BOP handlers.
+ */
+EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] = { NULL };
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
+{
+    BopProc[BopCode] = BopHandler;
+}
+
+VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
+{
+    WORD StackSegment, StackPointer;
+    LPWORD Stack;
+
+    /* Get the SS:SP */
+    StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
+    StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
+
+    /* Get the stack */
+    Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
+
+    /* Call the BOP handler */
+    if (BopProc[BopCode] != NULL)
+        BopProc[BopCode](Stack);
+    else
+        DPRINT("Invalid BOP code: 0x%02X\n", BopCode);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h
new file mode 100644 (file)
index 0000000..a936d1f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bop.h
+ * PURPOSE:         BIOS Operation Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _BOP_H_
+#define _BOP_H_
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define EMULATOR_BOP            0xC4C4
+#define EMULATOR_MAX_BOP_NUM    0xFF + 1
+
+/* FUNCTIONS ******************************************************************/
+
+typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
+
+VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler);
+VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode);
+
+#endif // _BOP_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/callback.c b/subsystems/ntvdm/callback.c
new file mode 100644 (file)
index 0000000..0cffdfd
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            callback.c
+ * PURPOSE:         16 and 32-bit Callbacks Support
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "bop.h"
+#include <isvbop.h>
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/*
+ * This is the list of registered 32-bit Interrupt handlers.
+ */
+EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
+
+/* BOP Identifiers */
+#define BOP_CONTROL             0xFF    // Control BOP Handler
+    #define BOP_CONTROL_DEFFUNC 0x00    // Default Control BOP Function
+
+/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
+#define BOP_CONTROL_INT32       0xFF
+
+
+#define BOP(num)            LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num)
+#define UnSimulate16(trap)           \
+do {                                 \
+    *(PUSHORT)(trap) = EMULATOR_BOP; \
+    (trap) += sizeof(USHORT);        \
+    *(trap) = BOP_UNSIMULATE;        \
+} while(0)
+// #define UnSimulate16        MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE)
+
+#define CALL16_TRAMPOLINE_SIZE  (1 * sizeof(ULONGLONG))
+#define  INT16_TRAMPOLINE_SIZE  (1 * sizeof(ULONGLONG))
+
+//
+// WARNING WARNING!!
+//
+// If you modify the code stubs here, think also
+// about updating them in int32.c too!!
+//
+
+/* 16-bit generic interrupt code for calling a 32-bit interrupt handler */
+BYTE Int16To32[] =
+{
+    0xFA,               // cli
+
+    /* Push the value of the interrupt to be called */
+    0x6A, 0xFF,         // push i (patchable to 0x6A, 0xIntNum)
+
+    /* The BOP Sequence */
+// BOP_SEQ:
+    0xF8,               // clc
+    BOP(BOP_CONTROL),   // Control BOP
+    BOP_CONTROL_INT32,  // 32-bit Interrupt dispatcher
+
+    0x73, 0x04,         // jnc EXIT (offset +4)
+
+    0xFB,               // sti
+
+    // HACK: The following instruction should be HLT!
+    0x90,               // nop
+
+    0xEB, 0xF5,         // jmp BOP_SEQ (offset -11)
+
+// EXIT:
+    0x44, 0x44,         // inc sp, inc sp
+    0xCF,               // iret
+};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+InitializeContext(IN PCALLBACK16 Context,
+                  IN USHORT      Segment,
+                  IN USHORT      Offset)
+{
+    Context->TrampolineFarPtr = MAKELONG(Offset, Segment);
+    Context->Segment          = Segment;
+    Context->NextOffset       = Offset + max(CALL16_TRAMPOLINE_SIZE,
+                                             INT16_TRAMPOLINE_SIZE);
+}
+
+VOID
+Call16(IN USHORT Segment,
+       IN USHORT Offset)
+{
+    /* Save CS:IP */
+    USHORT OrgCS = getCS();
+    USHORT OrgIP = getIP();
+
+    /* Set the new CS:IP */
+    setCS(Segment);
+    setIP(Offset);
+
+    DPRINT("Call16(%04X:%04X)\n", Segment, Offset);
+
+    /* Start CPU simulation */
+    EmulatorSimulate();
+
+    /* Restore CS:IP */
+    setCS(OrgCS);
+    setIP(OrgIP);
+}
+
+
+
+ULONG
+RegisterCallback16(IN  ULONG   FarPtr,
+                   IN  LPBYTE  CallbackCode,
+                   IN  SIZE_T  CallbackSize,
+                   OUT PSIZE_T CodeSize OPTIONAL)
+{
+    LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr);
+    LPBYTE Code      = CodeStart;
+
+    SIZE_T OurCodeSize = CallbackSize;
+
+    if (CallbackCode == NULL) CallbackSize = 0;
+
+    if (CallbackCode)
+    {
+        /* 16-bit interrupt code */
+        RtlCopyMemory(Code, CallbackCode, CallbackSize);
+        Code += CallbackSize;
+    }
+
+    /* Return the real size of the code if needed */
+    if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
+
+    // /* Return the entry-point address for 32-bit calls */
+    // return (ULONG_PTR)(CodeStart + CallbackSize);
+    return OurCodeSize;
+}
+
+VOID
+RunCallback16(IN PCALLBACK16 Context,
+              IN ULONG       FarPtr)
+{
+    PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
+    PUCHAR Trampoline     = TrampolineBase;
+    UCHAR  OldTrampoline[CALL16_TRAMPOLINE_SIZE];
+
+    /* Save the old trampoline */
+    ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
+
+    DPRINT1("RunCallback16(0x%p)\n", FarPtr);
+
+    /* Build the generic entry-point for 16-bit far calls */
+    *Trampoline++ = 0x9A; // Call far seg:off
+    *(PULONG)Trampoline = FarPtr;
+    Trampoline += sizeof(ULONG);
+    UnSimulate16(Trampoline);
+
+    /* Perform the call */
+    Call16(HIWORD(Context->TrampolineFarPtr),
+           LOWORD(Context->TrampolineFarPtr));
+
+    /* Restore the old trampoline */
+    ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
+}
+
+
+
+ULONG
+RegisterInt16(IN  ULONG   FarPtr,
+              IN  BYTE    IntNumber,
+              IN  LPBYTE  CallbackCode,
+              IN  SIZE_T  CallbackSize,
+              OUT PSIZE_T CodeSize OPTIONAL)
+{
+    /* Get a pointer to the IVT and set the corresponding entry (far pointer) */
+    LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000);
+    IntVecTable[IntNumber] = FarPtr;
+
+    /* Register the 16-bit callback */
+    return RegisterCallback16(FarPtr,
+                              CallbackCode,
+                              CallbackSize,
+                              CodeSize);
+}
+
+ULONG
+RegisterInt32(IN  ULONG   FarPtr,
+              IN  BYTE    IntNumber,
+              IN  EMULATOR_INT32_PROC IntHandler,
+              OUT PSIZE_T CodeSize OPTIONAL)
+{
+    /* Array for holding our copy of the 16-bit interrupt callback */
+    BYTE IntCallback[sizeof(Int16To32)/sizeof(BYTE)];
+
+    /* Check whether the 32-bit interrupt was already registered */
+#if 0
+    if (Int32Proc[IntNumber] != NULL)
+    {
+        DPRINT1("RegisterInt32: Interrupt 0x%X already registered!\n", IntNumber);
+        return 0;
+    }
+#endif
+
+    /* Register the 32-bit interrupt handler */
+    Int32Proc[IntNumber] = IntHandler;
+
+    /* Copy the generic 16-bit interrupt callback and patch it */
+    RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32));
+    IntCallback[2] = IntNumber;
+
+    /* Register the 16-bit interrupt callback */
+    return RegisterInt16(FarPtr,
+                         IntNumber,
+                         IntCallback,
+                         sizeof(IntCallback),
+                         CodeSize);
+}
+
+VOID
+Int32Call(IN PCALLBACK16 Context,
+          IN BYTE IntNumber)
+{
+    PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
+    PUCHAR Trampoline     = TrampolineBase;
+    UCHAR  OldTrampoline[INT16_TRAMPOLINE_SIZE];
+
+    DPRINT("Int32Call(0x%X)\n", IntNumber);
+
+    /* Save the old trampoline */
+    ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
+
+    /* Build the generic entry-point for 16-bit calls */
+    if (IntNumber == 0x03)
+    {
+        /* We are redefining for INT 03h */
+        *Trampoline++ = 0xCC; // Call INT 03h
+        /** *Trampoline++ = 0x90; // nop **/
+    }
+    else
+    {
+        /* Normal interrupt */
+        *Trampoline++ = 0xCD; // Call INT XXh
+        *Trampoline++ = IntNumber;
+    }
+    UnSimulate16(Trampoline);
+
+    /* Perform the call */
+    Call16(HIWORD(Context->TrampolineFarPtr),
+           LOWORD(Context->TrampolineFarPtr));
+
+    /* Restore the old trampoline */
+    ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
+}
+
+
+
+VOID WINAPI Int32Dispatch(LPWORD Stack)
+{
+    /* Get the interrupt number */
+    BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
+
+    /* Call the 32-bit Interrupt handler */
+    if (Int32Proc[IntNum] != NULL)
+        Int32Proc[IntNum](Stack);
+    else
+        DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX());
+}
+
+static VOID WINAPI ControlBop(LPWORD Stack)
+{
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    if (FuncNum == BOP_CONTROL_INT32)
+        Int32Dispatch(Stack);
+    else
+        // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
+        DisplayMessage(L"Unassigned Control BOP Function: 0x%02X\n", FuncNum);
+}
+
+VOID InitializeCallbacks(VOID)
+{
+    /* Register the Control BOP */
+    RegisterBop(BOP_CONTROL, ControlBop);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/callback.h b/subsystems/ntvdm/callback.h
new file mode 100644 (file)
index 0000000..c29ef9c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            callback.h
+ * PURPOSE:         32-bit Interrupt Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _CALLBACK_H_
+#define _CALLBACK_H_
+
+/* DEFINES ********************************************************************/
+
+/* 32-bit Interrupt Identifiers */
+#define EMULATOR_MAX_INT32_NUM  0xFF + 1
+
+#define INT_HANDLER_OFFSET 0x1000
+#define COMMON_STUB_OFFSET 0x2000
+
+
+typedef struct _CALLBACK16
+{
+    ULONG  TrampolineFarPtr; // Where the trampoline zone is placed
+    USHORT Segment;
+    USHORT NextOffset;
+} CALLBACK16, *PCALLBACK16;
+
+
+/* FUNCTIONS ******************************************************************/
+
+typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
+
+VOID
+InitializeContext(IN PCALLBACK16 Context,
+                  IN USHORT      Segment,
+                  IN USHORT      Offset);
+
+VOID
+Call16(IN USHORT Segment,
+       IN USHORT Offset);
+
+ULONG
+RegisterCallback16(IN  ULONG   FarPtr,
+                   IN  LPBYTE  CallbackCode,
+                   IN  SIZE_T  CallbackSize,
+                   OUT PSIZE_T CodeSize OPTIONAL);
+
+VOID
+RunCallback16(IN PCALLBACK16 Context,
+              IN ULONG       FarPtr);
+
+ULONG
+RegisterInt16(IN  ULONG   FarPtr,
+              IN  BYTE    IntNumber,
+              IN  LPBYTE  CallbackCode,
+              IN  SIZE_T  CallbackSize,
+              OUT PSIZE_T CodeSize OPTIONAL);
+
+ULONG
+RegisterInt32(IN  ULONG   FarPtr,
+              IN  BYTE    IntNumber,
+              IN  EMULATOR_INT32_PROC IntHandler,
+              OUT PSIZE_T CodeSize OPTIONAL);
+
+VOID
+Int32Call(IN PCALLBACK16 Context,
+          IN BYTE IntNumber);
+
+VOID WINAPI Int32Dispatch(LPWORD Stack);
+VOID InitializeCallbacks(VOID);
+
+#endif // _CALLBACK_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/clock.c b/subsystems/ntvdm/clock.c
new file mode 100644 (file)
index 0000000..74e1fe4
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            clock.c
+ * PURPOSE:         Clock for VDM
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+
+// #include "clock.h"
+
+#include "hardware/cmos.h"
+#include "hardware/ps2.h"
+#include "hardware/timer.h"
+#include "hardware/vga.h"
+
+/* DEFINES ********************************************************************/
+
+/*
+ * Activate IPS_DISPLAY if you want to display the
+ * number of instructions per second, as well as
+ * the computed number of ticks for the PIT.
+ */
+// #define IPS_DISPLAY
+
+/*
+ * Activate WORKING_TIMER when the PIT timing problem is fixed.
+ */
+// #define WORKING_TIMER
+
+
+/* Processor speed */
+#define STEPS_PER_CYCLE 256
+#define KBD_INT_CYCLES 16
+
+/* VARIABLES ******************************************************************/
+
+LARGE_INTEGER StartPerfCount, Frequency;
+
+LARGE_INTEGER LastTimerTick, LastRtcTick, Counter;
+LONGLONG TimerTicks;
+DWORD StartTickCount, CurrentTickCount;
+DWORD LastClockUpdate;
+DWORD LastVerticalRefresh;
+INT KeyboardIntCounter = 0;
+
+#ifdef IPS_DISPLAY
+    DWORD LastCyclePrintout;
+    DWORD Cycles = 0;
+#endif
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID ClockUpdate(VOID)
+{
+    extern BOOLEAN CpuSimulate;
+    UINT i;
+
+#ifdef WORKING_TIMER
+    DWORD PitResolution = PitGetResolution();
+#endif
+    DWORD RtcFrequency = RtcGetTicksPerSecond();
+
+    /* Get the current number of ticks */
+    CurrentTickCount = GetTickCount();
+
+#ifdef WORKING_TIMER
+    if ((PitResolution <= 1000) && (RtcFrequency <= 1000))
+    {
+        /* Calculate the approximate performance counter value instead */
+        Counter.QuadPart = StartPerfCount.QuadPart
+                           + (CurrentTickCount - StartTickCount)
+                           * (Frequency.QuadPart / 1000);
+    }
+    else
+#endif
+    {
+        /* Get the current performance counter value */
+        QueryPerformanceCounter(&Counter);
+    }
+
+    /* Get the number of PIT ticks that have passed */
+    TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
+                 * PIT_BASE_FREQUENCY) / Frequency.QuadPart;
+
+    /* Update the PIT */
+    if (TimerTicks > 0)
+    {
+        PitClock(TimerTicks);
+        LastTimerTick = Counter;
+    }
+
+    /* Check for RTC update */
+    if ((CurrentTickCount - LastClockUpdate) >= 1000)
+    {
+        RtcTimeUpdate();
+        LastClockUpdate = CurrentTickCount;
+    }
+
+    /* Check for RTC periodic tick */
+    if ((Counter.QuadPart - LastRtcTick.QuadPart)
+        >= (Frequency.QuadPart / (LONGLONG)RtcFrequency))
+    {
+        RtcPeriodicTick();
+        LastRtcTick = Counter;
+    }
+
+    /* Check for vertical retrace */
+    if ((CurrentTickCount - LastVerticalRefresh) >= 15)
+    {
+        VgaRefreshDisplay();
+        LastVerticalRefresh = CurrentTickCount;
+    }
+
+    if (++KeyboardIntCounter == KBD_INT_CYCLES)
+    {
+        GenerateKeyboardInterrupts();
+        KeyboardIntCounter = 0;
+    }
+
+    /* Horizontal retrace occurs as fast as possible */
+    VgaHorizontalRetrace();
+
+    /* Continue CPU emulation */
+    for (i = 0; VdmRunning && CpuSimulate && (i < STEPS_PER_CYCLE); i++)
+    {
+        EmulatorStep();
+#ifdef IPS_DISPLAY
+        Cycles++;
+#endif
+    }
+
+#ifdef IPS_DISPLAY
+    if ((CurrentTickCount - LastCyclePrintout) >= 1000)
+    {
+        DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %I64d\n", Cycles, TimerTicks);
+        LastCyclePrintout = CurrentTickCount;
+        Cycles = 0;
+    }
+#endif
+}
+
+BOOLEAN ClockInitialize(VOID)
+{
+    /* Initialize the performance counter (needed for hardware timers) */
+    if (!QueryPerformanceFrequency(&Frequency))
+    {
+        wprintf(L"FATAL: Performance counter not available\n");
+        return FALSE;
+    }
+
+    /* Find the starting performance and tick count */
+    StartTickCount = GetTickCount();
+    QueryPerformanceCounter(&StartPerfCount);
+
+    /* Set the different last counts to the starting count */
+    LastClockUpdate = LastVerticalRefresh =
+#ifdef IPS_DISPLAY
+    LastCyclePrintout =
+#endif
+    StartTickCount;
+
+    /* Set the last timer ticks to the current time */
+    LastTimerTick = LastRtcTick = StartPerfCount;
+
+    return TRUE;
+}
diff --git a/subsystems/ntvdm/clock.h b/subsystems/ntvdm/clock.h
new file mode 100644 (file)
index 0000000..53927d2
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            clock.h
+ * PURPOSE:         Clock for VDM
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _CLOCK_H_
+#define _CLOCK_H_
+
+/* FUNCTIONS ******************************************************************/
+
+VOID ClockUpdate(VOID);
+BOOLEAN ClockInitialize(VOID);
+
+#endif // _CLOCK_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dem.c b/subsystems/ntvdm/dos/dem.c
new file mode 100644 (file)
index 0000000..f0b251d
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dem.c
+ * PURPOSE:         DOS 32-bit Emulation Support Library -
+ *                  This library is used by the built-in NTVDM DOS32 and by
+ *                  the NT 16-bit DOS in Windows (via BOPs). It also exposes
+ *                  exported functions that can be used by VDDs.
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "utils.h"
+
+#include "dem.h"
+#include "bop.h"
+
+#include "bios/bios.h"
+
+/* Extra PSDK/NDK Headers */
+#include <ndk/obtypes.h>
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/**/extern BYTE CurrentDrive;/**/
+
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define BOP_DOS 0x50    // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
+#define BOP_CMD 0x54    // DOS Command Interpreter BOP (for COMMAND.COM)
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static VOID WINAPI DosSystemBop(LPWORD Stack)
+{
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    switch (FuncNum)
+    {
+        case 0x11:  // Load the DOS kernel
+        {
+            BOOLEAN Success;
+            HANDLE  hDosKernel;
+            ULONG   ulDosKernelSize = 0;
+
+            DPRINT1("You are loading Windows NT DOS!\n");
+
+            /* Open the DOS kernel file */
+            hDosKernel = FileOpen("ntdos.sys", &ulDosKernelSize);
+
+            /* If we failed, bail out */
+            if (hDosKernel == NULL) goto Quit;
+
+            /*
+             * Attempt to load the DOS kernel into memory.
+             * The segment where to load the DOS kernel is defined
+             * by the DOS BIOS and is found in DI:0000 .
+             */
+            Success = FileLoadByHandle(hDosKernel,
+                                       REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
+                                       ulDosKernelSize,
+                                       &ulDosKernelSize);
+
+            DPRINT1("Windows NT DOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
+                    (Success ? "succeeded" : "failed"),
+                    getDI(), 0x0000,
+                    ulDosKernelSize,
+                    GetLastError());
+
+            /* Close the DOS kernel file */
+            FileClose(hDosKernel);
+
+Quit:
+            if (!Success)
+            {
+                /* We failed everything, stop the VDM */
+                EmulatorTerminate();
+            }
+
+            break;
+        }
+
+        default:
+        {
+
+            DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
+            // setCF(1); // Disable, otherwise we enter an infinite loop
+            break;
+        }
+    }
+}
+
+static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
+{
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    switch (FuncNum)
+    {
+        case 0x08:  // Launch external command
+        {
+#define CMDLINE_LENGTH  1024
+
+            BOOL Result;
+            DWORD dwExitCode;
+
+            LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
+            LPSTR CmdPtr  = Command;
+            CHAR CommandLine[CMDLINE_LENGTH] = "";
+            STARTUPINFOA StartupInfo;
+            PROCESS_INFORMATION ProcessInformation;
+
+            /* NULL-terminate the command by removing the return carriage character */
+            while (*CmdPtr != '\r') CmdPtr++;
+            *CmdPtr = '\0';
+
+            DPRINT1("CMD Run Command '%s'\n", Command);
+
+            /* Spawn a user-defined 32-bit command preprocessor */
+
+            /* Build the command line */
+            // FIXME: Use COMSPEC env var!!
+            strcpy(CommandLine, "cmd.exe /c ");
+            strcat(CommandLine, Command);
+
+            ZeroMemory(&StartupInfo, sizeof(StartupInfo));
+            ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
+
+            StartupInfo.cb = sizeof(StartupInfo);
+
+            VidBiosDetachFromConsole();
+
+            Result = CreateProcessA(NULL,
+                                    CommandLine,
+                                    NULL,
+                                    NULL,
+                                    TRUE,
+                                    0,
+                                    NULL,
+                                    NULL,
+                                    &StartupInfo,
+                                    &ProcessInformation);
+            if (Result)
+            {
+                DPRINT1("Command '%s' launched successfully\n", Command);
+
+                /* Wait for process termination */
+                WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
+
+                /* Get the exit code */
+                GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
+
+                /* Close handles */
+                CloseHandle(ProcessInformation.hThread);
+                CloseHandle(ProcessInformation.hProcess);
+            }
+            else
+            {
+                DPRINT1("Failed when launched command '%s'\n");
+                dwExitCode = GetLastError();
+            }
+
+            VidBiosAttachToConsole();
+
+            setAL((UCHAR)dwExitCode);
+
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
+            // setCF(1); // Disable, otherwise we enter an infinite loop
+            break;
+        }
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
+{
+    /* Register the DOS BOPs */
+    RegisterBop(BOP_DOS, DosSystemBop        );
+    RegisterBop(BOP_CMD, DosCmdInterpreterBop);
+
+    if (DosKernelFileName)
+    {
+        BOOLEAN Success;
+        HANDLE  hDosBios;
+        ULONG   ulDosBiosSize = 0;
+
+        /* Open the DOS BIOS file */
+        hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
+
+        /* If we failed, bail out */
+        if (hDosBios == NULL) return FALSE;
+
+        /* Attempt to load the DOS BIOS into memory */
+        Success = FileLoadByHandle(hDosBios,
+                                   REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
+                                   ulDosBiosSize,
+                                   &ulDosBiosSize);
+
+        DPRINT1("DOS BIOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
+                (Success ? "succeeded" : "failed"),
+                0x0070, 0x0000,
+                ulDosBiosSize,
+                GetLastError());
+
+        /* Close the DOS BIOS file */
+        FileClose(hDosBios);
+
+        if (Success)
+        {
+            /* Position execution pointers and return */
+            setCS(0x0070);
+            setIP(0x0000);
+        }
+
+        return Success;
+    }
+    else
+    {
+        BOOLEAN Result;
+
+        Result  = DosBIOSInitialize();
+        // Result &= DosKRNLInitialize();
+
+        return Result;
+    }
+}
+
+/* PUBLIC EXPORTED APIS *******************************************************/
+
+// demLFNCleanup
+// demLFNGetCurrentDirectory
+
+// demGetFileTimeByHandle_WOW
+// demWOWLFNAllocateSearchHandle
+// demWOWLFNCloseSearchHandle
+// demWOWLFNEntry
+// demWOWLFNGetSearchHandle
+// demWOWLFNInit
+
+DWORD
+WINAPI
+demClientErrorEx(IN HANDLE FileHandle,
+                 IN CHAR   Unknown,
+                 IN BOOL   Flag)
+{
+    UNIMPLEMENTED;
+    return GetLastError();
+}
+
+DWORD
+WINAPI
+demFileDelete(IN LPCSTR FileName)
+{
+    if (DeleteFileA(FileName)) SetLastError(ERROR_SUCCESS);
+
+    return GetLastError();
+}
+
+DWORD
+WINAPI
+demFileFindFirst(OUT PVOID  lpFindFileData,
+                 IN  LPCSTR FileName,
+                 IN  WORD   AttribMask)
+{
+    BOOLEAN Success = TRUE;
+    WIN32_FIND_DATAA FindData;
+    PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
+
+    /* Fill the block */
+    FindFileBlock->DriveLetter  = CurrentDrive + 'A';
+    FindFileBlock->AttribMask   = AttribMask;
+    FindFileBlock->SearchHandle = FindFirstFileA(FileName, &FindData);
+    if (FindFileBlock->SearchHandle == INVALID_HANDLE_VALUE) return GetLastError();
+
+    do
+    {
+        /* Check the attributes */
+        if (!((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
+                                            FILE_ATTRIBUTE_SYSTEM |
+                                            FILE_ATTRIBUTE_DIRECTORY))
+            & ~AttribMask))
+        {
+            break;
+        }
+    }
+    while ((Success = FindNextFileA(FindFileBlock->SearchHandle, &FindData)));
+
+    if (!Success) return GetLastError();
+
+    FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
+    FileTimeToDosDateTime(&FindData.ftLastWriteTime,
+                          &FindFileBlock->FileDate,
+                          &FindFileBlock->FileTime);
+    FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
+                                                     : FindData.nFileSizeLow;
+    strcpy(FindFileBlock->FileName, FindData.cAlternateFileName);
+
+    return ERROR_SUCCESS;
+}
+
+DWORD
+WINAPI
+demFileFindNext(OUT PVOID lpFindFileData)
+{
+    WIN32_FIND_DATAA FindData;
+    PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
+
+    do
+    {
+        if (!FindNextFileA(FindFileBlock->SearchHandle, &FindData))
+            return GetLastError();
+
+        /* Update the block */
+        FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
+        FileTimeToDosDateTime(&FindData.ftLastWriteTime,
+                              &FindFileBlock->FileDate,
+                              &FindFileBlock->FileTime);
+        FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
+                                                         : FindData.nFileSizeLow;
+        strcpy(FindFileBlock->FileName, FindData.cAlternateFileName);
+    }
+    while((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
+                                        FILE_ATTRIBUTE_SYSTEM |
+                                        FILE_ATTRIBUTE_DIRECTORY))
+          & ~FindFileBlock->AttribMask);
+
+    return ERROR_SUCCESS;
+}
+
+UCHAR
+WINAPI
+demGetPhysicalDriveType(IN UCHAR DriveNumber)
+{
+    UNIMPLEMENTED;
+    return DOSDEVICE_DRIVE_UNKNOWN;
+}
+
+BOOL
+WINAPI
+demIsShortPathName(IN LPCSTR Path,
+                   IN BOOL Unknown)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+DWORD
+WINAPI
+demSetCurrentDirectoryGetDrive(IN  LPCSTR CurrentDirectory,
+                               OUT PUCHAR DriveNumber)
+{
+    UNIMPLEMENTED;
+    return ERROR_SUCCESS;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dem.h b/subsystems/ntvdm/dos/dem.h
new file mode 100644 (file)
index 0000000..1e5f2de
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dem.h
+ * PURPOSE:         DOS 32-bit Emulation Support Library -
+ *                  This library is used by the built-in NTVDM DOS32 and by
+ *                  the NT 16-bit DOS in Windows (via BOPs). It also exposes
+ *                  exported functions that can be used by VDDs.
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _DEM_H_
+#define _DEM_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include "dos32krnl/dos.h"
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames);
+
+DWORD
+WINAPI
+demClientErrorEx
+(
+    IN HANDLE FileHandle,
+    IN CHAR   Unknown,
+    IN BOOL   Flag
+);
+
+DWORD
+WINAPI
+demFileDelete
+(
+    IN LPCSTR FileName
+);
+
+DWORD
+WINAPI
+demFileFindFirst
+(
+    OUT PVOID  lpFindFileData,
+    IN  LPCSTR FileName,
+    IN  WORD   AttribMask
+);
+
+DWORD
+WINAPI
+demFileFindNext
+(
+    OUT PVOID lpFindFileData
+);
+
+UCHAR
+WINAPI
+demGetPhysicalDriveType
+(
+    IN UCHAR DriveNumber
+);
+
+BOOL
+WINAPI
+demIsShortPathName
+(
+    IN LPCSTR Path,
+    IN BOOL Unknown
+);
+
+DWORD
+WINAPI
+demSetCurrentDirectoryGetDrive
+(
+    IN  LPCSTR CurrentDirectory,
+    OUT PUCHAR DriveNumber
+);
+
+#endif // _DEM_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dos32krnl/bios.c b/subsystems/ntvdm/dos/dos32krnl/bios.c
new file mode 100644 (file)
index 0000000..32057e5
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dos.c
+ * PURPOSE:         VDM DOS Kernel
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "dos.h"
+
+#include "bios/bios.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+// static BYTE CurrentDrive;
+// static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+CHAR DosReadCharacter(WORD FileHandle)
+{
+    CHAR Character = '\0';
+    WORD BytesRead;
+
+    /* Use the file reading function */
+    DosReadFile(FileHandle, &Character, 1, &BytesRead);
+
+    return Character;
+}
+
+BOOLEAN DosCheckInput(VOID)
+{
+    HANDLE Handle = DosGetRealHandle(DOS_INPUT_HANDLE);
+
+    if (IsConsoleHandle(Handle))
+    {
+        /* Save AX */
+        USHORT AX = getAX();
+
+        /* Call the BIOS */
+        setAH(0x01); // or 0x11 for enhanced, but what to choose?
+        Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
+
+        /* Restore AX */
+        setAX(AX);
+
+        /* Return keyboard status */
+        return (getZF() == 0);
+    }
+    else
+    {
+        DWORD FileSizeHigh;
+        DWORD FileSize = GetFileSize(Handle, &FileSizeHigh);
+        LONG LocationHigh = 0;
+        DWORD Location = SetFilePointer(Handle, 0, &LocationHigh, FILE_CURRENT);
+
+        return ((Location != FileSize) || (LocationHigh != FileSizeHigh));
+    }
+}
+
+VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
+{
+    WORD BytesWritten;
+
+    /* Use the file writing function */
+    DosWriteFile(FileHandle, &Character, 1, &BytesWritten);
+}
+
+BOOLEAN DosBIOSInitialize(VOID)
+{
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT);
+
+    LPWSTR SourcePtr, Environment;
+    LPSTR AsciiString;
+    DWORD AsciiSize;
+    LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
+
+#if 0
+    UCHAR i;
+    CHAR CurrentDirectory[MAX_PATH];
+    CHAR DosDirectory[DOS_DIR_LENGTH];
+    LPSTR Path;
+
+    FILE *Stream;
+    WCHAR Buffer[256];
+#endif
+
+    /* Initialize the MCB */
+    Mcb->BlockType = 'Z';
+    Mcb->Size = USER_MEMORY_SIZE;
+    Mcb->OwnerPsp = 0;
+
+    /* Initialize the link MCB to the UMB area */
+    Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1);
+    Mcb->BlockType = 'M';
+    Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2;
+    Mcb->OwnerPsp = SYSTEM_PSP;
+
+    /* Initialize the UMB area */
+    Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT);
+    Mcb->BlockType = 'Z';
+    Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT;
+    Mcb->OwnerPsp = 0;
+
+    /* Get the environment strings */
+    SourcePtr = Environment = GetEnvironmentStringsW();
+    if (Environment == NULL) return FALSE;
+
+    /* Fill the DOS system environment block */
+    while (*SourcePtr)
+    {
+        /* Get the size of the ASCII string */
+        AsciiSize = WideCharToMultiByte(CP_ACP,
+                                        0,
+                                        SourcePtr,
+                                        -1,
+                                        NULL,
+                                        0,
+                                        NULL,
+                                        NULL);
+
+        /* Allocate memory for the ASCII string */
+        AsciiString = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AsciiSize);
+        if (AsciiString == NULL)
+        {
+            FreeEnvironmentStringsW(Environment);
+            return FALSE;
+        }
+
+        /* Convert to ASCII */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            SourcePtr,
+                            -1,
+                            AsciiString,
+                            AsciiSize,
+                            NULL,
+                            NULL);
+
+        /* Copy the string into DOS memory */
+        strcpy(DestPtr, AsciiString);
+
+        /* Move to the next string */
+        SourcePtr += wcslen(SourcePtr) + 1;
+        DestPtr += strlen(AsciiString);
+        *(DestPtr++) = 0;
+
+        /* Free the memory */
+        HeapFree(GetProcessHeap(), 0, AsciiString);
+    }
+    *DestPtr = 0;
+
+    /* Free the memory allocated for environment strings */
+    FreeEnvironmentStringsW(Environment);
+
+
+#if 0
+
+    /* Clear the current directory buffer */
+    ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
+
+    /* Get the current directory */
+    if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
+
+    /* Convert that to a DOS path */
+    if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
+
+    /* Set the drive */
+    CurrentDrive = DosDirectory[0] - 'A';
+
+    /* Get the directory part of the path */
+    Path = strchr(DosDirectory, '\\');
+    if (Path != NULL)
+    {
+        /* Skip the backslash */
+        Path++;
+    }
+
+    /* Set the directory */
+    if (Path != NULL)
+    {
+        strncpy(CurrentDirectories[CurrentDrive], Path, DOS_DIR_LENGTH);
+    }
+
+    /* Read CONFIG.SYS */
+    Stream = _wfopen(DOS_CONFIG_PATH, L"r");
+    if (Stream != NULL)
+    {
+        while (fgetws(Buffer, sizeof(Buffer)/sizeof(Buffer[0]), Stream))
+        {
+            // TODO: Parse the line
+        }
+        fclose(Stream);
+    }
+
+#endif
+
+
+    /* Register the DOS 32-bit Interrupts */
+    // RegisterDosInt32(0x20, DosInt20h);
+
+    /* Initialize the DOS kernel */
+    return DosKRNLInitialize();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dos32krnl/dos.c b/subsystems/ntvdm/dos/dos32krnl/dos.c
new file mode 100644 (file)
index 0000000..6ce7e3f
--- /dev/null
@@ -0,0 +1,2581 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dos/dos32krnl/dos.c
+ * PURPOSE:         VDM DOS Kernel
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "dos.h"
+#include "dos/dem.h"
+
+#include "bios/bios.h"
+#include "registers.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+CALLBACK16 DosContext;
+
+static WORD CurrentPsp = SYSTEM_PSP;
+static WORD DosLastError = 0;
+static DWORD DiskTransferArea;
+/*static*/ BYTE CurrentDrive;
+static CHAR LastDrive = 'E';
+static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
+
+static struct
+{
+    HANDLE Handle;
+    WORD   RefCount;
+} DosSystemFileTable[DOS_SFT_SIZE];
+
+static BYTE DosAllocStrategy = DOS_ALLOC_BEST_FIT;
+static BOOLEAN DosUmbLinked = FALSE;
+static WORD DosErrorLevel = 0x0000;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/*
+ * Memory management functions
+ */
+static VOID DosCombineFreeBlocks(WORD StartBlock)
+{
+    PDOS_MCB CurrentMcb = SEGMENT_TO_MCB(StartBlock), NextMcb;
+
+    /* If this is the last block or it's not free, quit */
+    if (CurrentMcb->BlockType == 'Z' || CurrentMcb->OwnerPsp != 0) return;
+
+    while (TRUE)
+    {
+        /* Get a pointer to the next MCB */
+        NextMcb = SEGMENT_TO_MCB(StartBlock + CurrentMcb->Size + 1);
+
+        /* Check if the next MCB is free */
+        if (NextMcb->OwnerPsp == 0)
+        {
+            /* Combine them */
+            CurrentMcb->Size += NextMcb->Size + 1;
+            CurrentMcb->BlockType = NextMcb->BlockType;
+            NextMcb->BlockType = 'I';
+        }
+        else
+        {
+            /* No more adjoining free blocks */
+            break;
+        }
+    }
+}
+
+static WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
+{
+    WORD Result = 0, Segment = FIRST_MCB_SEGMENT, MaxSize = 0;
+    PDOS_MCB CurrentMcb, NextMcb;
+    BOOLEAN SearchUmb = FALSE;
+
+    DPRINT("DosAllocateMemory: Size 0x%04X\n", Size);
+
+    if (DosUmbLinked && (DosAllocStrategy & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)))
+    {
+        /* Search UMB first */
+        Segment = UMB_START_SEGMENT;
+        SearchUmb = TRUE;
+    }
+
+    while (TRUE)
+    {
+        /* Get a pointer to the MCB */
+        CurrentMcb = SEGMENT_TO_MCB(Segment);
+
+        /* Make sure it's valid */
+        if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z')
+        {
+            DPRINT("The DOS memory arena is corrupted!\n");
+            DosLastError = ERROR_ARENA_TRASHED;
+            return 0;
+        }
+
+        /* Only check free blocks */
+        if (CurrentMcb->OwnerPsp != 0) goto Next;
+
+        /* Combine this free block with adjoining free blocks */
+        DosCombineFreeBlocks(Segment);
+
+        /* Update the maximum block size */
+        if (CurrentMcb->Size > MaxSize) MaxSize = CurrentMcb->Size;
+
+        /* Check if this block is big enough */
+        if (CurrentMcb->Size < Size) goto Next;
+
+        switch (DosAllocStrategy & 0x3F)
+        {
+            case DOS_ALLOC_FIRST_FIT:
+            {
+                /* For first fit, stop immediately */
+                Result = Segment;
+                goto Done;
+            }
+
+            case DOS_ALLOC_BEST_FIT:
+            {
+                /* For best fit, update the smallest block found so far */
+                if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size))
+                {
+                    Result = Segment;
+                }
+
+                break;
+            }
+
+            case DOS_ALLOC_LAST_FIT:
+            {
+                /* For last fit, make the current block the result, but keep searching */
+                Result = Segment;
+                break;
+            }
+        }
+
+Next:
+        /* If this was the last MCB in the chain, quit */
+        if (CurrentMcb->BlockType == 'Z')
+        {
+            /* Check if nothing was found while searching through UMBs */
+            if ((Result == 0) && SearchUmb && (DosAllocStrategy & DOS_ALLOC_HIGH_LOW))
+            {
+                /* Search low memory */
+                Segment = FIRST_MCB_SEGMENT;
+                continue;
+            }
+
+            break;
+        }
+
+        /* Otherwise, update the segment and continue */
+        Segment += CurrentMcb->Size + 1;
+    }
+
+Done:
+
+    /* If we didn't find a free block, return 0 */
+    if (Result == 0)
+    {
+        DosLastError = ERROR_NOT_ENOUGH_MEMORY;
+        if (MaxAvailable) *MaxAvailable = MaxSize;
+        return 0;
+    }
+
+    /* Get a pointer to the MCB */
+    CurrentMcb = SEGMENT_TO_MCB(Result);
+
+    /* Check if the block is larger than requested */
+    if (CurrentMcb->Size > Size)
+    {
+        /* It is, split it into two blocks */
+        NextMcb = SEGMENT_TO_MCB(Result + Size + 1);
+
+        /* Initialize the new MCB structure */
+        NextMcb->BlockType = CurrentMcb->BlockType;
+        NextMcb->Size = CurrentMcb->Size - Size - 1;
+        NextMcb->OwnerPsp = 0;
+
+        /* Update the current block */
+        CurrentMcb->BlockType = 'M';
+        CurrentMcb->Size = Size;
+    }
+
+    /* Take ownership of the block */
+    CurrentMcb->OwnerPsp = CurrentPsp;
+
+    /* Return the segment of the data portion of the block */
+    return Result + 1;
+}
+
+static BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
+{
+    BOOLEAN Success = TRUE;
+    WORD Segment = BlockData - 1, ReturnSize = 0, NextSegment;
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment), NextMcb;
+
+    DPRINT("DosResizeMemory: BlockData 0x%04X, NewSize 0x%04X\n",
+           BlockData,
+           NewSize);
+
+    /* Make sure this is a valid, allocated block */
+    if ((Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') || Mcb->OwnerPsp == 0)
+    {
+        Success = FALSE;
+        DosLastError = ERROR_INVALID_HANDLE;
+        goto Done;
+    }
+
+    ReturnSize = Mcb->Size;
+
+    /* Check if we need to expand or contract the block */
+    if (NewSize > Mcb->Size)
+    {
+        /* We can't expand the last block */
+        if (Mcb->BlockType != 'M')
+        {
+            Success = FALSE;
+            goto Done;
+        }
+
+        /* Get the pointer and segment of the next MCB */
+        NextSegment = Segment + Mcb->Size + 1;
+        NextMcb = SEGMENT_TO_MCB(NextSegment);
+
+        /* Make sure the next segment is free */
+        if (NextMcb->OwnerPsp != 0)
+        {
+            DPRINT("Cannot expand memory block: next segment is not free!\n");
+            DosLastError = ERROR_NOT_ENOUGH_MEMORY;
+            Success = FALSE;
+            goto Done;
+        }
+
+        /* Combine this free block with adjoining free blocks */
+        DosCombineFreeBlocks(NextSegment);
+
+        /* Set the maximum possible size of the block */
+        ReturnSize += NextMcb->Size + 1;
+
+        /* Maximize the current block */
+        Mcb->Size = ReturnSize;
+        Mcb->BlockType = NextMcb->BlockType;
+
+        /* Invalidate the next block */
+        NextMcb->BlockType = 'I';
+
+        /* Check if the block is larger than requested */
+        if (Mcb->Size > NewSize)
+        {
+            DPRINT("Block too large, reducing size from 0x%04X to 0x%04X\n",
+                   Mcb->Size,
+                   NewSize);
+
+            /* It is, split it into two blocks */
+            NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1);
+    
+            /* Initialize the new MCB structure */
+            NextMcb->BlockType = Mcb->BlockType;
+            NextMcb->Size = Mcb->Size - NewSize - 1;
+            NextMcb->OwnerPsp = 0;
+
+            /* Update the current block */
+            Mcb->BlockType = 'M';
+            Mcb->Size = NewSize;
+        }
+    }
+    else if (NewSize < Mcb->Size)
+    {
+        DPRINT("Shrinking block from 0x%04X to 0x%04X\n",
+                Mcb->Size,
+                NewSize);
+
+        /* Just split the block */
+        NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1);
+        NextMcb->BlockType = Mcb->BlockType;
+        NextMcb->Size = Mcb->Size - NewSize - 1;
+        NextMcb->OwnerPsp = 0;
+
+        /* Update the MCB */
+        Mcb->BlockType = 'M';
+        Mcb->Size = NewSize;
+    }
+
+Done:
+    /* Check if the operation failed */
+    if (!Success)
+    {
+        DPRINT("DosResizeMemory FAILED. Maximum available: 0x%04X\n",
+               ReturnSize);
+
+        /* Return the maximum possible size */
+        if (MaxAvailable) *MaxAvailable = ReturnSize;
+    }
+    
+    return Success;
+}
+
+static BOOLEAN DosFreeMemory(WORD BlockData)
+{
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(BlockData - 1);
+
+    DPRINT("DosFreeMemory: BlockData 0x%04X\n", BlockData);
+
+    /* Make sure the MCB is valid */
+    if (Mcb->BlockType != 'M' && Mcb->BlockType != 'Z')
+    {
+        DPRINT("MCB block type '%c' not valid!\n", Mcb->BlockType);
+        return FALSE;
+    }
+
+    /* Mark the block as free */
+    Mcb->OwnerPsp = 0;
+
+    return TRUE;
+}
+
+static BOOLEAN DosLinkUmb(VOID)
+{
+    DWORD Segment = FIRST_MCB_SEGMENT;
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment);
+
+    DPRINT("Linking UMB\n");
+
+    /* Check if UMBs are already linked */
+    if (DosUmbLinked) return FALSE;
+
+    /* Find the last block */
+    while ((Mcb->BlockType == 'M') && (Segment <= 0xFFFF))
+    {
+        Segment += Mcb->Size + 1;
+        Mcb = SEGMENT_TO_MCB(Segment);
+    }
+
+    /* Make sure it's valid */
+    if (Mcb->BlockType != 'Z') return FALSE;
+
+    /* Connect the MCB with the UMB chain */
+    Mcb->BlockType = 'M';
+
+    DosUmbLinked = TRUE;
+    return TRUE;
+}
+
+static BOOLEAN DosUnlinkUmb(VOID)
+{
+    DWORD Segment = FIRST_MCB_SEGMENT;
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment);
+
+    DPRINT("Unlinking UMB\n");
+
+    /* Check if UMBs are already unlinked */
+    if (!DosUmbLinked) return FALSE;
+
+    /* Find the block preceding the MCB that links it with the UMB chain */
+    while (Segment <= 0xFFFF)
+    {
+        if ((Segment + Mcb->Size) == (FIRST_MCB_SEGMENT + USER_MEMORY_SIZE))
+        {
+            /* This is the last non-UMB segment */
+            break;
+        }
+
+        /* Advance to the next MCB */
+        Segment += Mcb->Size + 1;
+        Mcb = SEGMENT_TO_MCB(Segment);
+    }
+
+    /* Mark the MCB as the last MCB */
+    Mcb->BlockType = 'Z';
+
+    DosUmbLinked = FALSE;
+    return TRUE;
+}
+
+static VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
+{
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment - 1);
+
+    /* Just set the owner */
+    Mcb->OwnerPsp = NewOwner;
+}
+
+static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
+{
+    PCHAR Ptr, DestBuffer = NULL;
+    ULONG TotalSize = 0;
+    WORD DestSegment;
+
+    Ptr = (PCHAR)Environment;
+
+    /* Calculate the size of the environment block */
+    while (*Ptr)
+    {
+        TotalSize += strlen(Ptr) + 1;
+        Ptr += strlen(Ptr) + 1;
+    }
+    TotalSize++;
+
+    /* Add the string buffer size */
+    TotalSize += strlen(ProgramName) + 1;
+
+    /* Allocate the memory for the environment block */
+    DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
+    if (!DestSegment) return 0;
+
+    Ptr = (PCHAR)Environment;
+
+    DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
+    while (*Ptr)
+    {
+        /* Copy the string */
+        strcpy(DestBuffer, Ptr);
+
+        /* Advance to the next string */
+        DestBuffer += strlen(Ptr);
+        Ptr += strlen(Ptr) + 1;
+
+        /* Put a zero after the string */
+        *(DestBuffer++) = 0;
+    }
+
+    /* Set the final zero */
+    *(DestBuffer++) = 0;
+
+    /* Copy the program name after the environment block */
+    strcpy(DestBuffer, ProgramName);
+
+    return DestSegment;
+}
+
+
+
+
+
+
+/* Taken from base/shell/cmd/console.c */
+BOOL IsConsoleHandle(HANDLE hHandle)
+{
+    DWORD dwMode;
+
+    /* Check whether the handle may be that of a console... */
+    if ((GetFileType(hHandle) & FILE_TYPE_CHAR) == 0) return FALSE;
+
+    /*
+     * It may be. Perform another test... The idea comes from the
+     * MSDN description of the WriteConsole API:
+     *
+     * "WriteConsole fails if it is used with a standard handle
+     *  that is redirected to a file. If an application processes
+     *  multilingual output that can be redirected, determine whether
+     *  the output handle is a console handle (one method is to call
+     *  the GetConsoleMode function and check whether it succeeds).
+     *  If the handle is a console handle, call WriteConsole. If the
+     *  handle is not a console handle, the output is redirected and
+     *  you should call WriteFile to perform the I/O."
+     */
+    return GetConsoleMode(hHandle, &dwMode);
+}
+
+WORD DosOpenHandle(HANDLE Handle)
+{
+    BYTE i;
+    WORD DosHandle;
+    PDOS_PSP PspBlock;
+    LPBYTE HandleTable;
+
+    /* The system PSP has no handle table */
+    if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE;
+
+    /* Get a pointer to the handle table */
+    PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+    HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+    /* Find a free entry in the JFT */
+    for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++)
+    {
+        if (HandleTable[DosHandle] == 0xFF) break;
+    }
+
+    /* If there are no free entries, fail */
+    if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE;
+
+    /* Check if the handle is already in the SFT */
+    for (i = 0; i < DOS_SFT_SIZE; i++)
+    {
+        /* Check if this is the same handle */
+        if (DosSystemFileTable[i].Handle != Handle) continue;
+
+        /* Already in the table, reference it */
+        DosSystemFileTable[i].RefCount++;
+
+        /* Set the JFT entry to that SFT index */
+        HandleTable[DosHandle] = i;
+
+        /* Return the new handle */
+        return DosHandle;
+    }
+
+    /* Add the handle to the SFT */
+    for (i = 0; i < DOS_SFT_SIZE; i++)
+    {
+        /* Make sure this is an empty table entry */
+        if (DosSystemFileTable[i].Handle != INVALID_HANDLE_VALUE) continue;
+
+        /* Initialize the empty table entry */
+        DosSystemFileTable[i].Handle   = Handle;
+        DosSystemFileTable[i].RefCount = 1;
+
+        /* Set the JFT entry to that SFT index */
+        HandleTable[DosHandle] = i;
+
+        /* Return the new handle */
+        return DosHandle;
+    }
+
+    /* The SFT is full */
+    return INVALID_DOS_HANDLE;
+}
+
+HANDLE DosGetRealHandle(WORD DosHandle)
+{
+    PDOS_PSP PspBlock;
+    LPBYTE HandleTable;
+
+    /* The system PSP has no handle table */
+    if (CurrentPsp == SYSTEM_PSP) return INVALID_HANDLE_VALUE;
+
+    /* Get a pointer to the handle table */
+    PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+    HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+    /* Make sure the handle is open */
+    if (HandleTable[DosHandle] == 0xFF) return INVALID_HANDLE_VALUE;
+
+    /* Return the Win32 handle */
+    return DosSystemFileTable[HandleTable[DosHandle]].Handle;
+}
+
+static VOID DosCopyHandleTable(LPBYTE DestinationTable)
+{
+    INT i;
+    PDOS_PSP PspBlock;
+    LPBYTE SourceTable;
+
+    /* Clear the table first */
+    for (i = 0; i < 20; i++) DestinationTable[i] = 0xFF;
+
+    /* Check if this is the initial process */
+    if (CurrentPsp == SYSTEM_PSP)
+    {
+        /* Set up the standard I/O devices */
+        for (i = 0; i <= 2; i++)
+        {
+            /* Set the index in the SFT */
+            DestinationTable[i] = (BYTE)i;
+
+            /* Increase the reference count */
+            DosSystemFileTable[i].RefCount++;
+        }
+
+        /* Done */
+        return;
+    }
+
+    /* Get the parent PSP block and handle table */
+    PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+    SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+    /* Copy the first 20 handles into the new table */
+    for (i = 0; i < 20; i++)
+    {
+        DestinationTable[i] = SourceTable[i];
+
+        /* Increase the reference count */
+        DosSystemFileTable[SourceTable[i]].RefCount++;
+    }
+}
+
+static BOOLEAN DosCloseHandle(WORD DosHandle)
+{
+    BYTE SftIndex;
+    PDOS_PSP PspBlock;
+    LPBYTE HandleTable;
+
+    DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle);
+
+    /* The system PSP has no handle table */
+    if (CurrentPsp == SYSTEM_PSP) return FALSE;
+
+    /* Get a pointer to the handle table */
+    PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+    HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+    /* Make sure the handle is open */
+    if (HandleTable[DosHandle] == 0xFF) return FALSE;
+
+    /* Decrement the reference count of the SFT entry */
+    SftIndex = HandleTable[DosHandle];
+    DosSystemFileTable[SftIndex].RefCount--;
+
+    /* Check if the reference count fell to zero */
+    if (!DosSystemFileTable[SftIndex].RefCount)
+    {
+        /* Close the file, it's no longer needed */
+        CloseHandle(DosSystemFileTable[SftIndex].Handle);
+
+        /* Clear the handle */
+        DosSystemFileTable[SftIndex].Handle = INVALID_HANDLE_VALUE;
+    }
+
+    /* Clear the entry in the JFT */
+    HandleTable[DosHandle] = 0xFF;
+
+    return TRUE;
+}
+
+static BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle)
+{
+    BYTE SftIndex;
+    PDOS_PSP PspBlock;
+    LPBYTE HandleTable;
+
+    DPRINT("DosDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n",
+           OldHandle,
+           NewHandle);
+
+    /* The system PSP has no handle table */
+    if (CurrentPsp == SYSTEM_PSP) return FALSE;
+
+    /* Get a pointer to the handle table */
+    PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+    HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
+
+    /* Make sure the old handle is open */
+    if (HandleTable[OldHandle] == 0xFF) return FALSE;
+
+    /* Check if the new handle is open */
+    if (HandleTable[NewHandle] != 0xFF)
+    {
+        /* Close it */
+        DosCloseHandle(NewHandle);
+    }
+
+    /* Increment the reference count of the SFT entry */
+    SftIndex = HandleTable[OldHandle];
+    DosSystemFileTable[SftIndex].RefCount++;
+
+    /* Make the new handle point to that SFT entry */
+    HandleTable[NewHandle] = SftIndex;
+
+    /* Return success */
+    return TRUE;
+}
+
+
+
+
+
+
+
+static BOOLEAN DosChangeDrive(BYTE Drive)
+{
+    WCHAR DirectoryPath[DOS_CMDLINE_LENGTH];
+
+    /* Make sure the drive exists */
+    if (Drive > (LastDrive - 'A')) return FALSE;
+
+    /* Find the path to the new current directory */
+    swprintf(DirectoryPath, L"%c\\%S", Drive + 'A', CurrentDirectories[Drive]);
+
+    /* Change the current directory of the process */
+    if (!SetCurrentDirectory(DirectoryPath)) return FALSE;
+
+    /* Set the current drive */
+    CurrentDrive = Drive;
+
+    /* Return success */
+    return TRUE;
+}
+
+static BOOLEAN DosChangeDirectory(LPSTR Directory)
+{
+    BYTE DriveNumber;
+    DWORD Attributes;
+    LPSTR Path;
+
+    /* Make sure the directory path is not too long */
+    if (strlen(Directory) >= DOS_DIR_LENGTH)
+    {
+        DosLastError = ERROR_PATH_NOT_FOUND;
+        return FALSE;
+    }
+
+    /* Get the drive number */
+    DriveNumber = Directory[0] - 'A';
+
+    /* Make sure the drive exists */
+    if (DriveNumber > (LastDrive - 'A'))
+    {
+        DosLastError = ERROR_PATH_NOT_FOUND;
+        return FALSE;
+    }
+
+    /* Get the file attributes */
+    Attributes = GetFileAttributesA(Directory);
+
+    /* Make sure the path exists and is a directory */
+    if ((Attributes == INVALID_FILE_ATTRIBUTES)
+        || !(Attributes & FILE_ATTRIBUTE_DIRECTORY))
+    {
+        DosLastError = ERROR_PATH_NOT_FOUND;
+        return FALSE;
+    }
+
+    /* Check if this is the current drive */
+    if (DriveNumber == CurrentDrive)
+    {
+        /* Change the directory */
+        if (!SetCurrentDirectoryA(Directory))
+        {
+            DosLastError = LOWORD(GetLastError());
+            return FALSE;
+        }
+    }
+
+    /* Get the directory part of the path */
+    Path = strchr(Directory, '\\');
+    if (Path != NULL)
+    {
+        /* Skip the backslash */
+        Path++;
+    }
+
+    /* Set the directory for the drive */
+    if (Path != NULL)
+    {
+        strncpy(CurrentDirectories[DriveNumber], Path, DOS_DIR_LENGTH);
+    }
+    else
+    {
+        CurrentDirectories[DriveNumber][0] = '\0';
+    }
+
+    /* Return success */
+    return TRUE;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment)
+{
+    PDOS_PSP PspBlock = SEGMENT_TO_PSP(PspSegment);
+    LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
+
+    ZeroMemory(PspBlock, sizeof(DOS_PSP));
+
+    /* Set the exit interrupt */
+    PspBlock->Exit[0] = 0xCD; // int 0x20
+    PspBlock->Exit[1] = 0x20;
+
+    /* Set the number of the last paragraph */
+    PspBlock->LastParagraph = PspSegment + ProgramSize - 1;
+
+    /* Save the interrupt vectors */
+    PspBlock->TerminateAddress = IntVecTable[0x22];
+    PspBlock->BreakAddress     = IntVecTable[0x23];
+    PspBlock->CriticalAddress  = IntVecTable[0x24];
+
+    /* Set the parent PSP */
+    PspBlock->ParentPsp = CurrentPsp;
+
+    /* Copy the parent handle table */
+    DosCopyHandleTable(PspBlock->HandleTable);
+
+    /* Set the environment block */
+    PspBlock->EnvBlock = Environment;
+
+    /* Set the handle table pointers to the internal handle table */
+    PspBlock->HandleTableSize = 20;
+    PspBlock->HandleTablePtr = MAKELONG(0x18, PspSegment);
+
+    /* Set the DOS version */
+    PspBlock->DosVersion = DOS_VERSION;
+
+    /* Set the far call opcodes */
+    PspBlock->FarCall[0] = 0xCD; // int 0x21
+    PspBlock->FarCall[1] = 0x21;
+    PspBlock->FarCall[2] = 0xCB; // retf
+
+    /* Set the command line */
+    PspBlock->CommandLineSize = (BYTE)min(strlen(CommandLine), DOS_CMDLINE_LENGTH - 1);
+    RtlCopyMemory(PspBlock->CommandLine, CommandLine, PspBlock->CommandLineSize);
+    PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r';
+}
+
+DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
+                        IN LPCSTR ExecutablePath,
+                        IN LPCSTR CommandLine,
+                        IN PVOID Environment,
+                        OUT PDWORD StackLocation OPTIONAL,
+                        OUT PDWORD EntryPoint OPTIONAL)
+{
+    DWORD Result = ERROR_SUCCESS;
+    HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
+    LPBYTE Address = NULL;
+    WORD Segment = 0;
+    WORD EnvBlock = 0;
+    WORD MaxAllocSize;
+    DWORD i, FileSize, ExeSize;
+    PIMAGE_DOS_HEADER Header;
+    PDWORD RelocationTable;
+    PWORD RelocWord;
+
+    DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n",
+            LoadType,
+            ExecutablePath,
+            CommandLine,
+            Environment,
+            StackLocation,
+            EntryPoint);
+
+    if (LoadType == DOS_LOAD_OVERLAY)
+    {
+        DPRINT1("Overlay loading is not supported yet.\n");
+        return ERROR_NOT_SUPPORTED;
+    }
+
+    /* Open a handle to the executable */
+    FileHandle = CreateFileA(ExecutablePath,
+                             GENERIC_READ,
+                             FILE_SHARE_READ,
+                             NULL,
+                             OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL,
+                             NULL);
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        Result = GetLastError();
+        goto Cleanup;
+    }
+
+    /* Get the file size */
+    FileSize = GetFileSize(FileHandle, NULL);
+
+    /* Create a mapping object for the file */
+    FileMapping = CreateFileMapping(FileHandle,
+                                    NULL,
+                                    PAGE_READONLY,
+                                    0,
+                                    0,
+                                    NULL);
+    if (FileMapping == NULL)
+    {
+        Result = GetLastError();
+        goto Cleanup;
+    }
+
+    /* Map the file into memory */
+    Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
+    if (Address == NULL)
+    {
+        Result = GetLastError();
+        goto Cleanup;
+    }
+
+    /* Copy the environment block to DOS memory */
+    EnvBlock = DosCopyEnvironmentBlock(Environment, ExecutablePath);
+    if (EnvBlock == 0)
+    {
+        Result = ERROR_NOT_ENOUGH_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Check if this is an EXE file or a COM file */
+    if (Address[0] == 'M' && Address[1] == 'Z')
+    {
+        /* EXE file */
+
+        /* Get the MZ header */
+        Header = (PIMAGE_DOS_HEADER)Address;
+
+        /* Get the base size of the file, in paragraphs (rounded up) */
+        ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4;
+
+        /* Add the PSP size, in paragraphs */
+        ExeSize += sizeof(DOS_PSP) >> 4;
+
+        /* Add the maximum size that should be allocated */
+        ExeSize += Header->e_maxalloc;
+
+        /* Make sure it does not pass 0xFFFF */
+        if (ExeSize > 0xFFFF) ExeSize = 0xFFFF;
+
+        /* Reduce the size one by one until the allocation is successful */
+        for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--, ExeSize--)
+        {
+            /* Try to allocate that much memory */
+            Segment = DosAllocateMemory((WORD)ExeSize, NULL);
+            if (Segment != 0) break;
+        }
+
+        /* Check if at least the lowest allocation was successful */
+        if (Segment == 0)
+        {
+            Result = ERROR_NOT_ENOUGH_MEMORY;
+            goto Cleanup;
+        }
+
+        /* Initialize the PSP */
+        DosInitializePsp(Segment,
+                         CommandLine,
+                         (WORD)ExeSize,
+                         EnvBlock);
+
+        /* The process owns its own memory */
+        DosChangeMemoryOwner(Segment, Segment);
+        DosChangeMemoryOwner(EnvBlock, Segment);
+
+        /* Copy the program to Segment:0100 */
+        RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100),
+                      Address + (Header->e_cparhdr << 4),
+                      min(FileSize - (Header->e_cparhdr << 4),
+                          (ExeSize << 4) - sizeof(DOS_PSP)));
+
+        /* Get the relocation table */
+        RelocationTable = (PDWORD)(Address + Header->e_lfarlc);
+
+        /* Perform relocations */
+        for (i = 0; i < Header->e_crlc; i++)
+        {
+            /* Get a pointer to the word that needs to be patched */
+            RelocWord = (PWORD)SEG_OFF_TO_PTR(Segment + HIWORD(RelocationTable[i]),
+                                                0x100 + LOWORD(RelocationTable[i]));
+
+            /* Add the number of the EXE segment to it */
+            *RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
+        }
+
+        if (LoadType == DOS_LOAD_AND_EXECUTE)
+        {
+            /* Set the initial segment registers */
+            setDS(Segment);
+            setES(Segment);
+
+            /* Set the stack to the location from the header */
+            EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
+                             Header->e_sp);
+
+            /* Execute */
+            CurrentPsp = Segment;
+            DiskTransferArea = MAKELONG(0x80, Segment);
+            EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
+                            Header->e_ip);
+        }
+    }
+    else
+    {
+        /* COM file */
+
+        /* Find the maximum amount of memory that can be allocated */
+        DosAllocateMemory(0xFFFF, &MaxAllocSize);
+
+        /* Make sure it's enough for the whole program and the PSP */
+        if (((DWORD)MaxAllocSize << 4) < (FileSize + sizeof(DOS_PSP)))
+        {
+            Result = ERROR_NOT_ENOUGH_MEMORY;
+            goto Cleanup;
+        }
+
+        /* Allocate all of it */
+        Segment = DosAllocateMemory(MaxAllocSize, NULL);
+        if (Segment == 0)
+        {
+            Result = ERROR_ARENA_TRASHED;
+            goto Cleanup;
+        }
+
+        /* The process owns its own memory */
+        DosChangeMemoryOwner(Segment, Segment);
+        DosChangeMemoryOwner(EnvBlock, Segment);
+
+        /* Copy the program to Segment:0100 */
+        RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100),
+                      Address,
+                      FileSize);
+
+        /* Initialize the PSP */
+        DosInitializePsp(Segment,
+                         CommandLine,
+                         MaxAllocSize,
+                         EnvBlock);
+
+        if (LoadType == DOS_LOAD_AND_EXECUTE)
+        {
+            /* Set the initial segment registers */
+            setDS(Segment);
+            setES(Segment);
+
+            /* Set the stack to the last word of the segment */
+            EmulatorSetStack(Segment, 0xFFFE);
+
+            /*
+             * Set the value on the stack to 0, so that a near return
+             * jumps to PSP:0000 which has the exit code.
+             */
+            *((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0;
+
+            /* Execute */
+            CurrentPsp = Segment;
+            DiskTransferArea = MAKELONG(0x80, Segment);
+            EmulatorExecute(Segment, 0x100);
+        }
+    }
+
+Cleanup:
+    if (Result != ERROR_SUCCESS)
+    {
+        /* It was not successful, cleanup the DOS memory */
+        if (EnvBlock) DosFreeMemory(EnvBlock);
+        if (Segment) DosFreeMemory(Segment);
+    }
+
+    /* Unmap the file*/
+    if (Address != NULL) UnmapViewOfFile(Address);
+
+    /* Close the file mapping object */
+    if (FileMapping != NULL) CloseHandle(FileMapping);
+
+    /* Close the file handle */
+    if (FileHandle != INVALID_HANDLE_VALUE) CloseHandle(FileHandle);
+
+    return Result;
+}
+
+DWORD DosStartProcess(IN LPCSTR ExecutablePath,
+                      IN LPCSTR CommandLine,
+                      IN PVOID Environment)
+{
+    DWORD Result;
+
+    Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE,
+                               ExecutablePath,
+                               CommandLine,
+                               Environment,
+                               NULL,
+                               NULL);
+
+    if (Result != ERROR_SUCCESS) goto Quit;
+
+    /* Attach to the console */
+    VidBiosAttachToConsole(); // FIXME: And in fact, attach the full NTVDM UI to the console
+
+    /* Start simulation */
+    SetEvent(VdmTaskEvent);
+    EmulatorSimulate();
+
+    /* Detach from the console */
+    VidBiosDetachFromConsole(); // FIXME: And in fact, detach the full NTVDM UI from the console
+
+Quit:
+    return Result;
+}
+
+#ifndef STANDALONE
+WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
+                      LPCSTR ProgramName,
+                      PDOS_EXEC_PARAM_BLOCK Parameters)
+{
+    DWORD Result;
+    DWORD BinaryType;
+    LPVOID Environment = NULL;
+    VDM_COMMAND_INFO CommandInfo;
+    CHAR CmdLine[MAX_PATH];
+    CHAR AppName[MAX_PATH];
+    CHAR PifFile[MAX_PATH];
+    CHAR Desktop[MAX_PATH];
+    CHAR Title[MAX_PATH];
+    CHAR Env[MAX_PATH];
+    STARTUPINFOA StartupInfo;
+    PROCESS_INFORMATION ProcessInfo;
+
+    /* Get the binary type */
+    if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
+
+    /* Did the caller specify an environment segment? */
+    if (Parameters->Environment)
+    {
+        /* Yes, use it instead of the parent one */
+        Environment = SEG_OFF_TO_PTR(Parameters->Environment, 0);
+    }
+
+    /* Set up the startup info structure */
+    ZeroMemory(&StartupInfo, sizeof(STARTUPINFOA));
+    StartupInfo.cb = sizeof(STARTUPINFOA);
+
+    /* Create the process */
+    if (!CreateProcessA(ProgramName,
+                        FAR_POINTER(Parameters->CommandLine),
+                        NULL,
+                        NULL,
+                        FALSE,
+                        0,
+                        Environment,
+                        NULL,
+                        &StartupInfo,
+                        &ProcessInfo))
+    {
+        return GetLastError();
+    }
+
+    /* Check the type of the program */
+    switch (BinaryType)
+    {
+        /* These are handled by NTVDM */
+        case SCS_DOS_BINARY:
+        case SCS_WOW_BINARY:
+        {
+            /* Clear the structure */
+            ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+
+            /* Initialize the structure members */
+            CommandInfo.TaskId = SessionId;
+            CommandInfo.VDMState = VDM_FLAG_NESTED_TASK | VDM_FLAG_DONT_WAIT;
+            CommandInfo.CmdLine = CmdLine;
+            CommandInfo.CmdLen = sizeof(CmdLine);
+            CommandInfo.AppName = AppName;
+            CommandInfo.AppLen = sizeof(AppName);
+            CommandInfo.PifFile = PifFile;
+            CommandInfo.PifLen = sizeof(PifFile);
+            CommandInfo.Desktop = Desktop;
+            CommandInfo.DesktopLen = sizeof(Desktop);
+            CommandInfo.Title = Title;
+            CommandInfo.TitleLen = sizeof(Title);
+            CommandInfo.Env = Env;
+            CommandInfo.EnvLen = sizeof(Env);
+
+            /* Get the VDM command information */
+            if (!GetNextVDMCommand(&CommandInfo))
+            {
+                /* Shouldn't happen */
+                ASSERT(FALSE);
+            }
+
+            /* Increment the re-entry count */
+            CommandInfo.VDMState = VDM_INC_REENTER_COUNT;
+            GetNextVDMCommand(&CommandInfo);
+
+            /* Load the executable */
+            Result = DosLoadExecutable(LoadType,
+                                       AppName,
+                                       CmdLine,
+                                       Env,
+                                       &Parameters->StackLocation,
+                                       &Parameters->EntryPoint);
+            if (Result != ERROR_SUCCESS)
+            {
+                DisplayMessage(L"Could not load '%S'. Error: %u", AppName, Result);
+                // FIXME: Decrement the reenter count. Or, instead, just increment
+                // the VDM reenter count *only* if this call succeeds...
+            }
+
+            break;
+        }
+
+        /* Not handled by NTVDM */
+        default:
+        {
+            /* Wait for the process to finish executing */
+            WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
+        }
+    }
+
+    /* Close the handles */
+    CloseHandle(ProcessInfo.hProcess);
+    CloseHandle(ProcessInfo.hThread);
+
+    return ERROR_SUCCESS;
+}
+#endif
+
+VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode)
+{
+    WORD i;
+    WORD McbSegment = FIRST_MCB_SEGMENT;
+    PDOS_MCB CurrentMcb;
+    LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
+    PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
+
+    DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n",
+           Psp,
+           ReturnCode);
+
+    /* Check if this PSP is it's own parent */
+    if (PspBlock->ParentPsp == Psp) goto Done;
+
+    for (i = 0; i < PspBlock->HandleTableSize; i++)
+    {
+        /* Close the handle */
+        DosCloseHandle(i);
+    }
+
+    /* Free the memory used by the process */
+    while (TRUE)
+    {
+        /* Get a pointer to the MCB */
+        CurrentMcb = SEGMENT_TO_MCB(McbSegment);
+
+        /* Make sure the MCB is valid */
+        if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType !='Z') break;
+
+        /* If this block was allocated by the process, free it */
+        if (CurrentMcb->OwnerPsp == Psp) DosFreeMemory(McbSegment + 1);
+
+        /* If this was the last block, quit */
+        if (CurrentMcb->BlockType == 'Z') break;
+
+        /* Update the segment and continue */
+        McbSegment += CurrentMcb->Size + 1;
+    }
+
+Done:
+    /* Restore the interrupt vectors */
+    IntVecTable[0x22] = PspBlock->TerminateAddress;
+    IntVecTable[0x23] = PspBlock->BreakAddress;
+    IntVecTable[0x24] = PspBlock->CriticalAddress;
+
+    /* Update the current PSP */
+    if (Psp == CurrentPsp)
+    {
+        CurrentPsp = PspBlock->ParentPsp;
+        if (CurrentPsp == SYSTEM_PSP)
+        {
+            ResetEvent(VdmTaskEvent);
+            EmulatorUnsimulate();
+        }
+    }
+
+#ifndef STANDALONE
+    // FIXME: This is probably not the best way to do it
+    /* Check if this was a nested DOS task */
+    if (CurrentPsp != SYSTEM_PSP)
+    {
+        VDM_COMMAND_INFO CommandInfo;
+
+        /* Decrement the re-entry count */
+        CommandInfo.TaskId = SessionId;
+        CommandInfo.VDMState = VDM_DEC_REENTER_COUNT;
+        GetNextVDMCommand(&CommandInfo);
+
+        /* Clear the structure */
+        ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+
+        /* Update the VDM state of the task */
+        CommandInfo.TaskId = SessionId;
+        CommandInfo.VDMState = VDM_FLAG_DONT_WAIT;
+        GetNextVDMCommand(&CommandInfo);
+    }
+#endif
+
+    /* Save the return code - Normal termination */
+    DosErrorLevel = MAKEWORD(ReturnCode, 0x00);
+
+    /* Return control to the parent process */
+    EmulatorExecute(HIWORD(PspBlock->TerminateAddress),
+                    LOWORD(PspBlock->TerminateAddress));
+}
+
+BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
+{
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    if (Handle == INVALID_HANDLE_VALUE)
+    {
+        /* Doesn't exist */
+        DosLastError = ERROR_FILE_NOT_FOUND;
+        return FALSE;
+    }
+
+    switch (ControlCode)
+    {
+        /* Get Device Information */
+        case 0x00:
+        {
+            WORD InfoWord = 0;
+
+            /*
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2820.htm
+             * for a list of possible flags.
+             */
+
+            if (Handle == DosSystemFileTable[DOS_INPUT_HANDLE].Handle)
+            {
+                /* Console input */
+                InfoWord |= 1 << 0;
+            }
+            else if (Handle == DosSystemFileTable[DOS_OUTPUT_HANDLE].Handle)
+            {
+                /* Console output */
+                InfoWord |= 1 << 1;
+            }
+
+            /* It is a device */
+            InfoWord |= 1 << 7;
+
+            /* Return the device information word */
+            setDX(InfoWord);
+            return TRUE;
+        }
+
+        /* Unsupported control code */
+        default:
+        {
+            DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode);
+
+            DosLastError = ERROR_INVALID_PARAMETER;
+            return FALSE;
+        }
+    }
+}
+
+VOID WINAPI DosInt20h(LPWORD Stack)
+{
+    /* This is the exit interrupt */
+    DosTerminateProcess(Stack[STACK_CS], 0);
+}
+
+VOID WINAPI DosInt21h(LPWORD Stack)
+{
+    BYTE Character;
+    SYSTEMTIME SystemTime;
+    PCHAR String;
+    PDOS_INPUT_BUFFER InputBuffer;
+
+    /* Check the value in the AH register */
+    switch (getAH())
+    {
+        /* Terminate Program */
+        case 0x00:
+        {
+            DosTerminateProcess(Stack[STACK_CS], 0);
+            break;
+        }
+
+        /* Read Character from STDIN with Echo */
+        case 0x01:
+        {
+            // FIXME: Under DOS 2+, input / output handle may be redirected!!!!
+            Character = DosReadCharacter(DOS_INPUT_HANDLE);
+            DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+
+            // /* Let the BOP repeat if needed */
+            // if (getCF()) break;
+
+            setAL(Character);
+            break;
+        }
+
+        /* Write Character to STDOUT */
+        case 0x02:
+        {
+            // FIXME: Under DOS 2+, output handle may be redirected!!!!
+            Character = getDL();
+            DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+
+            /*
+             * We return the output character (DOS 2.1+).
+             * Also, if we're going to output a TAB, then
+             * don't return a TAB but a SPACE instead.
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2554.htm
+             * for more information.
+             */
+            setAL(Character == '\t' ? ' ' : Character);
+            break;
+        }
+
+        /* Read Character from STDAUX */
+        case 0x03:
+        {
+            // FIXME: Really read it from STDAUX!
+            DPRINT1("INT 16h, 03h: Read character from STDAUX is HALFPLEMENTED\n");
+            // setAL(DosReadCharacter());
+            break;
+        }
+
+        /* Write Character to STDAUX */
+        case 0x04:
+        {
+            // FIXME: Really write it to STDAUX!
+            DPRINT1("INT 16h, 04h: Write character to STDAUX is HALFPLEMENTED\n");
+            // DosPrintCharacter(getDL());
+            break;
+        }
+
+        /* Write Character to Printer */
+        case 0x05:
+        {
+            // FIXME: Really write it to printer!
+            DPRINT1("INT 16h, 05h: Write character to printer is HALFPLEMENTED -\n\n");
+            DPRINT1("0x%p\n", getDL());
+            DPRINT1("\n\n-----------\n\n");
+            break;
+        }
+
+        /* Direct Console I/O */
+        case 0x06:
+        {
+            Character = getDL();
+
+            // FIXME: Under DOS 2+, output handle may be redirected!!!!
+
+            if (Character != 0xFF)
+            {
+                /* Output */
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+
+                /*
+                 * We return the output character (DOS 2.1+).
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2558.htm
+                 * for more information.
+                 */
+                setAL(Character);
+            }
+            else
+            {
+                /* Input */
+                if (DosCheckInput())
+                {
+                    Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
+                    setAL(DosReadCharacter(DOS_INPUT_HANDLE));
+                }
+                else
+                {
+                    /* No character available */
+                    Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
+                    setAL(0x00);
+                }
+            }
+
+            break;
+        }
+
+        /* Character Input without Echo */
+        case 0x07:
+        case 0x08:
+        {
+            // FIXME: Under DOS 2+, input handle may be redirected!!!!
+            Character = DosReadCharacter(DOS_INPUT_HANDLE);
+
+            // FIXME: For 0x07, do not check Ctrl-C/Break.
+            //        For 0x08, do check those control sequences and if needed,
+            //        call INT 0x23.
+
+            // /* Let the BOP repeat if needed */
+            // if (getCF()) break;
+
+            setAL(Character);
+            break;
+        }
+
+        /* Write string to STDOUT */
+        case 0x09:
+        {
+            String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            while (*String != '$')
+            {
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, *String);
+                String++;
+            }
+
+            /*
+             * We return the terminating character (DOS 2.1+).
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2562.htm
+             * for more information.
+             */
+            setAL('$');
+            break;
+        }
+
+        /* Read Buffered Input */
+        case 0x0A:
+        {
+            WORD Count = 0;
+            InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            DPRINT1("Read Buffered Input\n");
+
+            while (Count < InputBuffer->MaxLength)
+            {
+                /* Try to read a character (wait) */
+                Character = DosReadCharacter(DOS_INPUT_HANDLE);
+
+                /* Echo the character and append it to the buffer */
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+                InputBuffer->Buffer[Count] = Character;
+
+                if (Character == '\r') break;
+                Count++;
+            }
+
+            /* Update the length */
+            InputBuffer->Length = Count;
+
+            break;
+        }
+
+        /* Get STDIN Status */
+        case 0x0B:
+        {
+            setAL(DosCheckInput() ? 0xFF : 0x00);
+            break;
+        }
+
+        /* Flush Buffer and Read STDIN */
+        case 0x0C:
+        {
+            BYTE InputFunction = getAL();
+
+            /* Flush STDIN buffer */
+            DosFlushFileBuffers(DOS_INPUT_HANDLE);
+
+            /*
+             * If the input function number contained in AL is valid, i.e.
+             * AL == 0x01 or 0x06 or 0x07 or 0x08 or 0x0A, call ourselves
+             * recursively with AL == AH.
+             */
+            if (InputFunction == 0x01 || InputFunction == 0x06 ||
+                InputFunction == 0x07 || InputFunction == 0x08 ||
+                InputFunction == 0x0A)
+            {
+                setAH(InputFunction);
+                /*
+                 * Instead of calling ourselves really recursively as in:
+                 * DosInt21h(Stack);
+                 * prefer resetting the CF flag to let the BOP repeat.
+                 */
+                setCF(1);
+            }
+            break;
+        }
+
+        /* Disk Reset */
+        case 0x0D:
+        {
+            PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+
+            // TODO: Flush what's needed.
+            DPRINT1("INT 21h, 0Dh is UNIMPLEMENTED\n");
+
+            /* Clear CF in DOS 6 only */
+            if (PspBlock->DosVersion == 0x0006)
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+            break;
+        }
+
+        /* Set Default Drive  */
+        case 0x0E:
+        {
+            DosChangeDrive(getDL());
+            setAL(LastDrive - 'A' + 1);
+            break;
+        }
+
+        /* NULL Function for CP/M Compatibility */
+        case 0x18:
+        {
+            /*
+             * This function corresponds to the CP/M BDOS function
+             * "get bit map of logged drives", which is meaningless
+             * under MS-DOS.
+             *
+             * For: PTS-DOS 6.51 & S/DOS 1.0 - EXTENDED RENAME FILE USING FCB
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2584.htm
+             * for more information.
+             */
+            setAL(0x00);
+            break;
+        }
+
+        /* Get Default Drive */
+        case 0x19:
+        {
+            setAL(CurrentDrive);
+            break;
+        }
+
+        /* Set Disk Transfer Area */
+        case 0x1A:
+        {
+            DiskTransferArea = MAKELONG(getDX(), getDS());
+            break;
+        }
+
+        /* NULL Function for CP/M Compatibility */
+        case 0x1D:
+        case 0x1E:
+        {
+            /*
+             * Function 0x1D corresponds to the CP/M BDOS function
+             * "get bit map of read-only drives", which is meaningless
+             * under MS-DOS.
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2592.htm
+             * for more information.
+             *
+             * Function 0x1E corresponds to the CP/M BDOS function
+             * "set file attributes", which was meaningless under MS-DOS 1.x.
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2593.htm
+             * for more information.
+             */
+            setAL(0x00);
+            break;
+        }
+
+        /* NULL Function for CP/M Compatibility */
+        case 0x20:
+        {
+            /*
+             * This function corresponds to the CP/M BDOS function
+             * "get/set default user (sublibrary) number", which is meaningless
+             * under MS-DOS.
+             *
+             * For: S/DOS 1.0+ & PTS-DOS 6.51+ - GET OEM REVISION
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2596.htm
+             * for more information.
+             */
+            setAL(0x00);
+            break;
+        }
+
+        /* Set Interrupt Vector */
+        case 0x25:
+        {
+            ULONG FarPointer = MAKELONG(getDX(), getDS());
+            DPRINT1("Setting interrupt 0x%x ...\n", getAL());
+
+            /* Write the new far pointer to the IDT */
+            ((PULONG)BaseAddress)[getAL()] = FarPointer;
+            break;
+        }
+
+        /* Create New PSP */
+        case 0x26:
+        {
+            DPRINT1("INT 21h, 26h - Create New PSP is UNIMPLEMENTED\n");
+            break;
+        }
+
+        /* Get System Date */
+        case 0x2A:
+        {
+            GetLocalTime(&SystemTime);
+            setCX(SystemTime.wYear);
+            setDX(MAKEWORD(SystemTime.wDay, SystemTime.wMonth));
+            setAL(SystemTime.wDayOfWeek);
+            break;
+        }
+
+        /* Set System Date */
+        case 0x2B:
+        {
+            GetLocalTime(&SystemTime);
+            SystemTime.wYear  = getCX();
+            SystemTime.wMonth = getDH();
+            SystemTime.wDay   = getDL();
+
+            /* Return success or failure */
+            setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
+            break;
+        }
+
+        /* Get System Time */
+        case 0x2C:
+        {
+            GetLocalTime(&SystemTime);
+            setCX(MAKEWORD(SystemTime.wMinute, SystemTime.wHour));
+            setDX(MAKEWORD(SystemTime.wMilliseconds / 10, SystemTime.wSecond));
+            break;
+        }
+
+        /* Set System Time */
+        case 0x2D:
+        {
+            GetLocalTime(&SystemTime);
+            SystemTime.wHour         = getCH();
+            SystemTime.wMinute       = getCL();
+            SystemTime.wSecond       = getDH();
+            SystemTime.wMilliseconds = getDL() * 10; // In hundredths of seconds
+
+            /* Return success or failure */
+            setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
+            break;
+        }
+
+        /* Get Disk Transfer Area */
+        case 0x2F:
+        {
+            setES(HIWORD(DiskTransferArea));
+            setBX(LOWORD(DiskTransferArea));
+            break;
+        }
+
+        /* Get DOS Version */
+        case 0x30:
+        {
+            PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+
+            /*
+             * DOS 2+ - GET DOS VERSION
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2711.htm
+             * for more information.
+             */
+
+            if (LOBYTE(PspBlock->DosVersion) < 5 || getAL() == 0x00)
+            {
+                /*
+                 * Return DOS OEM number:
+                 * 0x00 for IBM PC-DOS
+                 * 0x02 for packaged MS-DOS
+                 */
+                setBH(0x02);
+            }
+
+            if (LOBYTE(PspBlock->DosVersion) >= 5 && getAL() == 0x01)
+            {
+                /*
+                 * Return version flag:
+                 * 1 << 3 if DOS is in ROM,
+                 * 0 (reserved) if not.
+                 */
+                setBH(0x00);
+            }
+
+            /* Return DOS 24-bit user serial number in BL:CX */
+            setBL(0x00);
+            setCX(0x0000);
+
+            /*
+             * Return DOS version: Minor:Major in AH:AL
+             * The Windows NT DOS box returns version 5.00, subject to SETVER.
+             */
+            setAX(PspBlock->DosVersion);
+
+            break;
+        }
+
+        /* Extended functionalities */
+        case 0x33:
+        {
+            if (getAL() == 0x06)
+            {
+                /*
+                 * DOS 5+ - GET TRUE VERSION NUMBER
+                 * This function always returns the true version number, unlike
+                 * AH=30h, whose return value may be changed with SETVER.
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2730.htm
+                 * for more information.
+                 */
+
+                /*
+                 * Return the true DOS version: Minor:Major in BH:BL
+                 * The Windows NT DOS box returns BX=3205h (version 5.50).
+                 */
+                setBX(NTDOS_VERSION);
+
+                /* DOS revision 0 */
+                setDL(0x00);
+
+                /* Unpatched DOS */
+                setDH(0x00);
+            }
+            // else
+            // {
+                // /* Invalid subfunction */
+                // setAL(0xFF);
+            // }
+
+            break;
+        }
+
+        /* Get Interrupt Vector */
+        case 0x35:
+        {
+            DWORD FarPointer = ((PDWORD)BaseAddress)[getAL()];
+
+            /* Read the address from the IDT into ES:BX */
+            setES(HIWORD(FarPointer));
+            setBX(LOWORD(FarPointer));
+            break;
+        }
+
+        /* SWITCH character - AVAILDEV */
+        case 0x37:
+        {
+            if (getAL() == 0x00)
+            {
+                /*
+                 * DOS 2+ - "SWITCHAR" - GET SWITCH CHARACTER
+                 * This setting is ignored by MS-DOS 4.0+.
+                 * MS-DOS 5+ always return AL=00h/DL=2Fh.
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2752.htm
+                 * for more information.
+                 */
+                setDL('/');
+                setAL(0x00);
+            }
+            else if (getAL() == 0x01)
+            {
+                /*
+                 * DOS 2+ - "SWITCHAR" - SET SWITCH CHARACTER
+                 * This setting is ignored by MS-DOS 5+.
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2753.htm
+                 * for more information.
+                 */
+                // getDL();
+                setAL(0xFF);
+            }
+            else if (getAL() == 0x02)
+            {
+                /*
+                 * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm
+                 * for more information.
+                 */
+                // setDL();
+                setAL(0xFF);
+            }
+            else if (getAL() == 0x03)
+            {
+                /*
+                 * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm
+                 * for more information.
+                 */
+                // getDL();
+                setAL(0xFF);
+            }
+            else
+            {
+                /* Invalid subfunction */
+                setAL(0xFF);
+            }
+
+            break;
+        }
+
+        /* Create Directory */
+        case 0x39:
+        {
+            String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            if (CreateDirectoryA(String, NULL))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(LOWORD(GetLastError()));
+            }
+
+            break;
+        }
+
+        /* Remove Directory */
+        case 0x3A:
+        {
+            String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            if (RemoveDirectoryA(String))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(LOWORD(GetLastError()));
+            }
+
+            break;
+        }
+
+        /* Set Current Directory */
+        case 0x3B:
+        {
+            String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            if (DosChangeDirectory(String))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(DosLastError);
+            }
+
+            break;
+        }
+
+        /* Create File */
+        case 0x3C:
+        {
+            WORD FileHandle;
+            WORD ErrorCode = DosCreateFile(&FileHandle,
+                                           (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
+                                           getCX());
+
+            if (ErrorCode == 0)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(FileHandle);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+
+        /* Open File */
+        case 0x3D:
+        {
+            WORD FileHandle;
+            WORD ErrorCode = DosOpenFile(&FileHandle,
+                                         (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
+                                         getAL());
+
+            if (ErrorCode == 0)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(FileHandle);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+
+        /* Close File */
+        case 0x3E:
+        {
+            if (DosCloseHandle(getBX()))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_HANDLE);
+            }
+
+            break;
+        }
+
+        /* Read from File or Device */
+        case 0x3F:
+        {
+            WORD BytesRead = 0;
+            WORD ErrorCode = DosReadFile(getBX(),
+                                         SEG_OFF_TO_PTR(getDS(), getDX()),
+                                         getCX(),
+                                         &BytesRead);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(BytesRead);
+            }
+            else if (ErrorCode != ERROR_NOT_READY)
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+
+        /* Write to File or Device */
+        case 0x40:
+        {
+            WORD BytesWritten = 0;
+            WORD ErrorCode = DosWriteFile(getBX(),
+                                          SEG_OFF_TO_PTR(getDS(), getDX()),
+                                          getCX(),
+                                          &BytesWritten);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(BytesWritten);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+
+        /* Delete File */
+        case 0x41:
+        {
+            LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            if (demFileDelete(FileName) == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                /*
+                 * See Ralf Brown: http://www.ctyme.com/intr/rb-2797.htm
+                 * "AX destroyed (DOS 3.3) AL seems to be drive of deleted file."
+                 */
+                setAL(FileName[0] - 'A');
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(GetLastError());
+            }
+
+            break;
+        }
+
+        /* Seek File */
+        case 0x42:
+        {
+            DWORD NewLocation;
+            WORD ErrorCode = DosSeekFile(getBX(),
+                                         MAKELONG(getDX(), getCX()),
+                                         getAL(),
+                                         &NewLocation);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+                /* Return the new offset in DX:AX */
+                setDX(HIWORD(NewLocation));
+                setAX(LOWORD(NewLocation));
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+
+        /* Get/Set File Attributes */
+        case 0x43:
+        {
+            DWORD Attributes;
+            LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
+
+            if (getAL() == 0x00)
+            {
+                /* Get the attributes */
+                Attributes = GetFileAttributesA(FileName);
+
+                /* Check if it failed */
+                if (Attributes == INVALID_FILE_ATTRIBUTES)
+                {
+                    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                    setAX(GetLastError());
+                }
+                else
+                {
+                    /* Return the attributes that DOS can understand */
+                    Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                    setCX(Attributes & 0x00FF);
+                }
+            }
+            else if (getAL() == 0x01)
+            {
+                /* Try to set the attributes */
+                if (SetFileAttributesA(FileName, getCL()))
+                {
+                    Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                }
+                else
+                {
+                    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                    setAX(GetLastError());
+                }
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_FUNCTION);
+            }
+
+            break;
+        }
+
+        /* IOCTL */
+        case 0x44:
+        {
+            if (DosHandleIoctl(getAL(), getBX()))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(DosLastError);
+            }
+
+            break;
+        }
+
+        /* Duplicate Handle */
+        case 0x45:
+        {
+            WORD NewHandle;
+            HANDLE Handle = DosGetRealHandle(getBX());
+
+            if (Handle == INVALID_HANDLE_VALUE)
+            {
+                /* The handle is invalid */
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_HANDLE);
+                break;
+            }
+
+            /* Open a new handle to the same entry */
+            NewHandle = DosOpenHandle(Handle);
+
+            if (NewHandle == INVALID_DOS_HANDLE)
+            {
+                /* Too many files open */
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_TOO_MANY_OPEN_FILES);
+                break;
+            }
+
+            /* Return the result */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            setAX(NewHandle);
+            break;
+        }
+
+        /* Force Duplicate Handle */
+        case 0x46:
+        {
+            if (DosDuplicateHandle(getBX(), getCX()))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_HANDLE);
+            }
+
+            break;
+        }
+
+        /* Get Current Directory */
+        case 0x47:
+        {
+            BYTE DriveNumber = getDL();
+            String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getSI());
+
+            /* Get the real drive number */
+            if (DriveNumber == 0)
+            {
+                DriveNumber = CurrentDrive;
+            }
+            else
+            {
+                /* Decrement DriveNumber since it was 1-based */
+                DriveNumber--;
+            }
+
+            if (DriveNumber <= LastDrive - 'A')
+            {
+                /*
+                 * Copy the current directory into the target buffer.
+                 * It doesn't contain the drive letter and the backslash.
+                 */
+                strncpy(String, CurrentDirectories[DriveNumber], DOS_DIR_LENGTH);
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(0x0100); // Undocumented, see Ralf Brown: http://www.ctyme.com/intr/rb-2933.htm
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_DRIVE);
+            }
+
+            break;
+        }
+
+        /* Allocate Memory */
+        case 0x48:
+        {
+            WORD MaxAvailable = 0;
+            WORD Segment = DosAllocateMemory(getBX(), &MaxAvailable);
+
+            if (Segment != 0)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(Segment);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(DosLastError);
+                setBX(MaxAvailable);
+            }
+
+            break;
+        }
+
+        /* Free Memory */
+        case 0x49:
+        {
+            if (DosFreeMemory(getES()))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_ARENA_TRASHED);
+            }
+
+            break;
+        }
+
+        /* Resize Memory Block */
+        case 0x4A:
+        {
+            WORD Size;
+
+            if (DosResizeMemory(getES(), getBX(), &Size))
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(DosLastError);
+                setBX(Size);
+            }
+
+            break;
+        }
+
+#ifndef STANDALONE
+        /* Execute */
+        case 0x4B:
+        {
+            DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)getAL();
+            LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX());
+            PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX());
+            WORD ErrorCode = DosCreateProcess(LoadType, ProgramName, ParamBlock);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
+
+            break;
+        }
+#endif
+
+        /* Terminate With Return Code */
+        case 0x4C:
+        {
+            DosTerminateProcess(CurrentPsp, getAL());
+            break;
+        }
+
+        /* Get Return Code (ERRORLEVEL) */
+        case 0x4D:
+        {
+            /*
+             * According to Ralf Brown: http://www.ctyme.com/intr/rb-2976.htm
+             * DosErrorLevel is cleared after being read by this function.
+             */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            setAX(DosErrorLevel);
+            DosErrorLevel = 0x0000; // Clear it
+            break;
+        }
+
+        /* Find First File */
+        case 0x4E:
+        {
+            WORD Result = (WORD)demFileFindFirst(FAR_POINTER(DiskTransferArea),
+                                                 SEG_OFF_TO_PTR(getDS(), getDX()),
+                                                 getCX());
+
+            setAX(Result);
+
+            if (Result == ERROR_SUCCESS)
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            else
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+            break;
+        }
+
+        /* Find Next File */
+        case 0x4F:
+        {
+            WORD Result = (WORD)demFileFindNext(FAR_POINTER(DiskTransferArea));
+
+            setAX(Result);
+
+            if (Result == ERROR_SUCCESS)
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            else
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+            break;
+        }
+
+        /* Internal - Set Current Process ID (Set PSP Address) */
+        case 0x50:
+        {
+            // FIXME: Is it really what it's done ??
+            CurrentPsp = getBX();
+            break;
+        }
+
+        /* Internal - Get Current Process ID (Get PSP Address) */
+        case 0x51:
+        /* Get Current PSP Address */
+        case 0x62:
+        {
+            /*
+             * Undocumented AH=51h is identical to the documented AH=62h.
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2982.htm
+             * and http://www.ctyme.com/intr/rb-3140.htm
+             * for more information.
+             */
+            setBX(CurrentPsp);
+            break;
+        }
+
+        /* Internal - Get "List of lists" (SYSVARS) */
+        case 0x52:
+        {
+            /*
+             * On return, ES points at the DOS data segment (see also INT 2F/AX=1203h).
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2983.htm
+             * for more information.
+             */
+
+            /* Return the DOS "list of lists" in ES:BX */
+            setES(0x0000);
+            setBX(0x0000);
+
+            DisplayMessage(L"Required for AARD code, do you remember? :P");
+            break;
+        }
+
+        /* Get/Set Memory Management Options */
+        case 0x58:
+        {
+            if (getAL() == 0x00)
+            {
+                /* Get allocation strategy */
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAX(DosAllocStrategy);
+            }
+            else if (getAL() == 0x01)
+            {
+                /* Set allocation strategy */
+
+                if ((getBL() & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
+                    == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
+                {
+                    /* Can't set both */
+                    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                    setAX(ERROR_INVALID_PARAMETER);
+                    break;
+                }
+
+                if ((getBL() & 0x3F) > DOS_ALLOC_LAST_FIT)
+                {
+                    /* Invalid allocation strategy */
+                    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                    setAX(ERROR_INVALID_PARAMETER);
+                    break;
+                }
+
+                DosAllocStrategy = getBL();
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else if (getAL() == 0x02)
+            {
+                /* Get UMB link state */
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setAL(DosUmbLinked ? 0x01 : 0x00);
+            }
+            else if (getAL() == 0x03)
+            {
+                /* Set UMB link state */
+                if (getBX()) DosLinkUmb();
+                else DosUnlinkUmb();
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            }
+            else
+            {
+                /* Invalid or unsupported function */
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ERROR_INVALID_FUNCTION);
+            }
+
+            break;
+        }
+
+        /* Unsupported */
+        default:
+        {
+            DPRINT1("DOS Function INT 0x21, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
+                    getAH(), getAL());
+
+            setAL(0); // Some functions expect AL to be 0 when it's not supported.
+            Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+        }
+    }
+}
+
+VOID WINAPI DosBreakInterrupt(LPWORD Stack)
+{
+    UNREFERENCED_PARAMETER(Stack);
+
+    /* Stop the VDM task */
+    ResetEvent(VdmTaskEvent);
+    EmulatorUnsimulate();
+}
+
+VOID WINAPI DosFastConOut(LPWORD Stack)
+{
+    /*
+     * This is the DOS 2+ Fast Console Output Interrupt.
+     * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm
+     * for more information.
+     */
+
+    /* Save AX and BX */
+    USHORT AX = getAX();
+    USHORT BX = getBX();
+
+    /* Set the parameters (AL = character, already set) */
+    setBL(DOS_CHAR_ATTRIBUTE);
+    setBH(Bda->VideoPage);
+
+    /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
+    setAH(0x0E);
+    Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT);
+
+    /* Restore AX and BX */
+    setBX(BX);
+    setAX(AX);
+}
+
+VOID WINAPI DosInt2Fh(LPWORD Stack)
+{
+    DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
+            getAH(), getAL());
+    Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+}
+
+BOOLEAN DosKRNLInitialize(VOID)
+{
+
+#if 1
+
+    UCHAR i;
+    CHAR CurrentDirectory[MAX_PATH];
+    CHAR DosDirectory[DOS_DIR_LENGTH];
+    LPSTR Path;
+
+    FILE *Stream;
+    WCHAR Buffer[256];
+
+    /* Clear the current directory buffer */
+    ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
+
+    /* Get the current directory */
+    if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
+
+    /* Convert that to a DOS path */
+    if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH))
+    {
+        // TODO: Use some kind of default path?
+        return FALSE;
+    }
+
+    /* Set the drive */
+    CurrentDrive = DosDirectory[0] - 'A';
+
+    /* Get the directory part of the path */
+    Path = strchr(DosDirectory, '\\');
+    if (Path != NULL)
+    {
+        /* Skip the backslash */
+        Path++;
+    }
+
+    /* Set the directory */
+    if (Path != NULL)
+    {
+        strncpy(CurrentDirectories[CurrentDrive], Path, DOS_DIR_LENGTH);
+    }
+
+    /* Read CONFIG.SYS */
+    Stream = _wfopen(DOS_CONFIG_PATH, L"r");
+    if (Stream != NULL)
+    {
+        while (fgetws(Buffer, 256, Stream))
+        {
+            // TODO: Parse the line
+        }
+        fclose(Stream);
+    }
+
+    /* Initialize the SFT */
+    for (i = 0; i < DOS_SFT_SIZE; i++)
+    {
+        DosSystemFileTable[i].Handle   = INVALID_HANDLE_VALUE;
+        DosSystemFileTable[i].RefCount = 0;
+    }
+
+    /* Get handles to standard I/O devices */
+    DosSystemFileTable[0].Handle = GetStdHandle(STD_INPUT_HANDLE);
+    DosSystemFileTable[1].Handle = GetStdHandle(STD_OUTPUT_HANDLE);
+    DosSystemFileTable[2].Handle = GetStdHandle(STD_ERROR_HANDLE);
+
+    /* Initialize the reference counts */
+    DosSystemFileTable[0].RefCount =
+    DosSystemFileTable[1].RefCount =
+    DosSystemFileTable[2].RefCount = 1;
+
+#endif
+
+    /* Initialize the callback context */
+    InitializeContext(&DosContext, 0x0070, 0x0000);
+
+    /* Register the DOS 32-bit Interrupts */
+    RegisterDosInt32(0x20, DosInt20h        );
+    RegisterDosInt32(0x21, DosInt21h        );
+//  RegisterDosInt32(0x22, DosInt22h        ); // Termination
+    RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
+//  RegisterDosInt32(0x24, DosInt24h        ); // Critical Error
+    RegisterDosInt32(0x29, DosFastConOut    ); // DOS 2+ Fast Console Output
+    RegisterDosInt32(0x2F, DosInt2Fh        );
+
+    return TRUE;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dos32krnl/dos.h b/subsystems/ntvdm/dos/dos32krnl/dos.h
new file mode 100644 (file)
index 0000000..f3e9140
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dos.h
+ * PURPOSE:         VDM DOS Kernel
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _DOS_H_
+#define _DOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/**/ #include "callback.h" /**/
+
+/* DEFINES ********************************************************************/
+
+//
+// We are DOS 5.00 (reported by INT 21h, AH=30h)
+//    and DOS 5.50 (reported by INT 21h, AX=3306h) for Windows NT Compatibility
+//
+#define DOS_VERSION     MAKEWORD(5, 00)
+#define NTDOS_VERSION   MAKEWORD(5, 50)
+
+#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT"
+#define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT"
+#define FIRST_MCB_SEGMENT 0x1000
+#define USER_MEMORY_SIZE 0x8FFE
+#define SYSTEM_PSP 0x08
+#define SYSTEM_ENV_BLOCK 0x800
+
+#define INVALID_DOS_HANDLE  0xFFFF
+#define DOS_INPUT_HANDLE    0
+#define DOS_OUTPUT_HANDLE   1
+#define DOS_ERROR_HANDLE    2
+
+#define DOS_SFT_SIZE 255
+#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
+#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
+#define UMB_START_SEGMENT 0xC000
+#define UMB_END_SEGMENT 0xDFFF
+#define DOS_ALLOC_HIGH 0x40
+#define DOS_ALLOC_HIGH_LOW 0x80
+#define DOS_CMDLINE_LENGTH 127
+#define DOS_DIR_LENGTH 64
+#define NUM_DRIVES ('Z' - 'A' + 1)
+#define DOS_CHAR_ATTRIBUTE 0x07
+
+enum DOS_ALLOC_STRATEGY
+{
+    DOS_ALLOC_FIRST_FIT,
+    DOS_ALLOC_BEST_FIT,
+    DOS_ALLOC_LAST_FIT
+};
+
+typedef enum
+{
+    DOS_LOAD_AND_EXECUTE = 0x00,
+    DOS_LOAD_ONLY = 0x01,
+    DOS_LOAD_OVERLAY = 0x03
+} DOS_EXEC_TYPE;
+
+#pragma pack(push, 1)
+
+typedef struct _DOS_MCB
+{
+    CHAR BlockType;
+    WORD OwnerPsp;
+    WORD Size;
+    BYTE Unused[3];
+    CHAR Name[8];
+} DOS_MCB, *PDOS_MCB;
+
+typedef struct _DOS_FCB
+{
+    BYTE DriveNumber;
+    CHAR FileName[8];
+    CHAR FileExt[3];
+    WORD BlockNumber;
+    WORD RecordSize;
+    DWORD FileSize;
+    WORD LastWriteDate;
+    WORD LastWriteTime;
+    BYTE Reserved[8];
+    BYTE BlockRecord;
+    BYTE RecordNumber[3];
+} DOS_FCB, *PDOS_FCB;
+
+typedef struct _DOS_PSP
+{
+    BYTE Exit[2];
+    WORD LastParagraph;
+    BYTE Reserved0[6];
+    DWORD TerminateAddress;
+    DWORD BreakAddress;
+    DWORD CriticalAddress;
+    WORD ParentPsp;
+    BYTE HandleTable[20];
+    WORD EnvBlock;
+    DWORD LastStack;
+    WORD HandleTableSize;
+    DWORD HandleTablePtr;
+    DWORD PreviousPsp;
+    DWORD Reserved1;
+    WORD DosVersion;
+    BYTE Reserved2[14];
+    BYTE FarCall[3];
+    BYTE Reserved3[9];
+    DOS_FCB Fcb;
+    BYTE CommandLineSize;
+    CHAR CommandLine[DOS_CMDLINE_LENGTH];
+} DOS_PSP, *PDOS_PSP;
+
+typedef struct _DOS_INPUT_BUFFER
+{
+    BYTE MaxLength;
+    BYTE Length;
+    CHAR Buffer[ANYSIZE_ARRAY];
+} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
+
+typedef struct _DOS_DRIVER_HEADER
+{
+    DWORD NextDriver;
+    WORD Attributes;
+    WORD StrategyEntry;
+    WORD InterruptEntry;
+    CHAR DeviceName[8];
+} DOS_DRIVER_HEADER, *PDOS_DRIVER_HEADER;
+
+typedef struct _DOS_FIND_FILE_BLOCK
+{
+    CHAR DriveLetter;
+    CHAR Pattern[11];
+    UCHAR AttribMask;
+    DWORD Unused;
+    HANDLE SearchHandle;
+
+    /* The following part of the structure is documented */
+    UCHAR Attributes;
+    WORD FileTime;
+    WORD FileDate;
+    DWORD FileSize;
+    CHAR FileName[13];
+} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK;
+
+typedef struct _DOS_EXEC_PARAM_BLOCK
+{
+    /* Input variables */
+    WORD Environment;
+    DWORD CommandLine;
+    DWORD FirstFcb;
+    DWORD SecondFcb;
+
+    /* Output variables */
+    DWORD StackLocation;
+    DWORD EntryPoint;
+} DOS_EXEC_PARAM_BLOCK, *PDOS_EXEC_PARAM_BLOCK;
+
+#pragma pack(pop)
+
+/* FUNCTIONS ******************************************************************/
+
+extern CALLBACK16 DosContext;
+#define RegisterDosInt32(IntNumber, IntHandler) \
+do { \
+    DosContext.NextOffset += RegisterInt32(MAKELONG(DosContext.NextOffset,   \
+                                                    DosContext.Segment),     \
+                                           (IntNumber), (IntHandler), NULL); \
+} while(0);
+
+/*
+ * DOS BIOS Functions
+ * See bios.c
+ */
+CHAR DosReadCharacter(WORD FileHandle);
+BOOLEAN DosCheckInput(VOID);
+VOID DosPrintCharacter(WORD FileHandle, CHAR Character);
+
+BOOLEAN DosBIOSInitialize(VOID);
+
+
+/*
+ * DOS Kernel Functions
+ * See dos.c
+ */
+BOOL IsConsoleHandle(HANDLE hHandle);
+WORD DosOpenHandle(HANDLE Handle);
+HANDLE DosGetRealHandle(WORD DosHandle);
+
+WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes);
+WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode);
+WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead);
+WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
+WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset);
+BOOL DosFlushFileBuffers(WORD FileHandle);
+
+VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
+DWORD DosLoadExecutable(
+    IN DOS_EXEC_TYPE LoadType,
+    IN LPCSTR ExecutablePath,
+    IN LPCSTR CommandLine,
+    IN PVOID Environment,
+    OUT PDWORD StackLocation OPTIONAL,
+    OUT PDWORD EntryPoint OPTIONAL
+);
+WORD DosCreateProcess(
+    DOS_EXEC_TYPE LoadType,
+    LPCSTR ProgramName,
+    PDOS_EXEC_PARAM_BLOCK Parameters
+);
+DWORD DosStartProcess(IN LPCSTR ExecutablePath,
+                      IN LPCSTR CommandLine,
+                      IN PVOID Environment);
+VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
+BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
+
+VOID WINAPI DosInt20h(LPWORD Stack);
+VOID WINAPI DosInt21h(LPWORD Stack);
+VOID WINAPI DosBreakInterrupt(LPWORD Stack);
+VOID WINAPI DosInt2Fh(LPWORD Stack);
+
+BOOLEAN DosKRNLInitialize(VOID);
+
+#endif // _DOS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/dos/dos32krnl/dosfiles.c b/subsystems/ntvdm/dos/dos32krnl/dosfiles.c
new file mode 100644 (file)
index 0000000..03a5df8
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dos/dos32krnl/dosfiles.c
+ * PURPOSE:         DOS Files
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+// #include "callback.h"
+
+#include "dos.h"
+#include "dos/dem.h"
+
+#include "bios/bios.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes)
+{
+    HANDLE FileHandle;
+    WORD DosHandle;
+
+    DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n",
+            FilePath,
+            Attributes);
+
+    /* Create the file */
+    FileHandle = CreateFileA(FilePath,
+                             GENERIC_READ | GENERIC_WRITE,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                             NULL,
+                             CREATE_ALWAYS,
+                             Attributes,
+                             NULL);
+
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Return the error code */
+        return (WORD)GetLastError();
+    }
+
+    /* Open the DOS handle */
+    DosHandle = DosOpenHandle(FileHandle);
+
+    if (DosHandle == INVALID_DOS_HANDLE)
+    {
+        /* Close the handle */
+        CloseHandle(FileHandle);
+
+        /* Return the error code */
+        return ERROR_TOO_MANY_OPEN_FILES;
+    }
+
+    /* It was successful */
+    *Handle = DosHandle;
+    return ERROR_SUCCESS;
+}
+
+WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode)
+{
+    HANDLE FileHandle;
+    ACCESS_MASK Access = 0;
+    WORD DosHandle;
+
+    DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n",
+            FilePath,
+            AccessMode);
+
+    /* Parse the access mode */
+    switch (AccessMode & 3)
+    {
+        case 0:
+        {
+            /* Read-only */
+            Access = GENERIC_READ;
+            break;
+        }
+
+        case 1:
+        {
+            /* Write only */
+            Access = GENERIC_WRITE;
+            break;
+        }
+
+        case 2:
+        {
+            /* Read and write */
+            Access = GENERIC_READ | GENERIC_WRITE;
+            break;
+        }
+
+        default:
+        {
+            /* Invalid */
+            return ERROR_INVALID_PARAMETER;
+        }
+    }
+
+    /* Open the file */
+    FileHandle = CreateFileA(FilePath,
+                             Access,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                             NULL,
+                             OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL,
+                             NULL);
+
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Return the error code */
+        return (WORD)GetLastError();
+    }
+
+    /* Open the DOS handle */
+    DosHandle = DosOpenHandle(FileHandle);
+
+    if (DosHandle == INVALID_DOS_HANDLE)
+    {
+        /* Close the handle */
+        CloseHandle(FileHandle);
+
+        /* Return the error code */
+        return ERROR_TOO_MANY_OPEN_FILES;
+    }
+
+    /* It was successful */
+    *Handle = DosHandle;
+    return ERROR_SUCCESS;
+}
+
+WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD BytesRead32 = 0;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT1("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    if (IsConsoleHandle(Handle))
+    {
+        CHAR Character;
+
+        /*
+         * Use BIOS Get Keystroke function
+         */
+
+        /* Save AX */
+        USHORT AX = getAX();
+
+        for (BytesRead32 = 0; BytesRead32 < Count; BytesRead32++)
+        {
+            /* Call the BIOS INT 16h, AH=00h "Get Keystroke" */
+            setAH(0x00);
+            Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
+
+            /* Retrieve the character in AL (scan code is in AH) */
+            Character = getAL();
+
+            // FIXME: Sometimes we need echo, some other times not.
+            // DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+
+            ((PCHAR)Buffer)[BytesRead32] = Character;
+
+            /* Stop on first carriage return */
+            if (Character == '\r')
+            {
+                // DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n');
+                break;
+            }
+
+            // BytesRead32++;
+        }
+
+        /* Restore AX */
+        setAX(AX);
+    }
+    else
+    {
+        /* Read the file */
+        if (!ReadFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesRead32, NULL))
+        {
+            /* Store the error code */
+            Result = (WORD)GetLastError();
+        }
+    }
+
+    /* The number of bytes read is always 16-bit */
+    *BytesRead = LOWORD(BytesRead32);
+
+    /* Return the error code */
+    return Result;
+}
+
+WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD BytesWritten32 = 0;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT1("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n",
+           FileHandle,
+           Count);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    if (IsConsoleHandle(Handle))
+    {
+        /*
+         * Use BIOS Teletype function
+         */
+
+        /* Save AX and BX */
+        USHORT AX = getAX();
+        USHORT BX = getBX();
+
+        // FIXME: Use BIOS Write String function INT 10h, AH=13h ??
+
+        for (BytesWritten32 = 0; BytesWritten32 < Count; BytesWritten32++)
+        {
+            /* Set the parameters */
+            setAL(((PCHAR)Buffer)[BytesWritten32]);
+            setBL(DOS_CHAR_ATTRIBUTE);
+            setBH(Bda->VideoPage);
+
+            /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
+            setAH(0x0E);
+            Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT);
+
+            // BytesWritten32++;
+        }
+
+        /* Restore AX and BX */
+        setBX(BX);
+        setAX(AX);
+    }
+    else
+    {
+        /* Write the file */
+        if (!WriteFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesWritten32, NULL))
+        {
+            /* Store the error code */
+            Result = (WORD)GetLastError();
+        }
+    }
+
+    /* The number of bytes written is always 16-bit */
+    *BytesWritten = LOWORD(BytesWritten32);
+
+    /* Return the error code */
+    return Result;
+}
+
+WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD FilePointer;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
+           FileHandle,
+           Offset,
+           Origin);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    /* Check if the origin is valid */
+    if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END)
+    {
+        return ERROR_INVALID_FUNCTION;
+    }
+
+    /* Move the file pointer */
+    if (IsConsoleHandle(Handle))
+    {
+        /* Always succeeds when seeking a console handle */
+        FilePointer = 0;
+        Result = ERROR_SUCCESS;
+    }
+    else
+    {
+        FilePointer = SetFilePointer(Handle, Offset, NULL, Origin);
+    }
+
+    /* Check if there's a possibility the operation failed */
+    if (FilePointer == INVALID_SET_FILE_POINTER)
+    {
+        /* Get the real error code */
+        Result = (WORD)GetLastError();
+    }
+
+    if (Result != ERROR_SUCCESS)
+    {
+        /* The operation did fail */
+        return Result;
+    }
+
+    /* Return the file pointer, if requested */
+    if (NewOffset) *NewOffset = FilePointer;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+// This function is almost exclusively used as a DosFlushInputBuffer
+BOOL DosFlushFileBuffers(WORD FileHandle)
+{
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return FALSE;
+
+    /*
+     * No need to check whether the handle is a console handle since
+     * FlushFileBuffers() automatically does this check and calls
+     * FlushConsoleInputBuffer() for us.
+     */
+    return FlushFileBuffers(Handle);
+}
diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c
new file mode 100644 (file)
index 0000000..094d156
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            emulator.c
+ * PURPOSE:         Minimal x86 machine emulator for the VDM
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "clock.h"
+#include "bios/rom.h"
+#include "hardware/cmos.h"
+#include "hardware/pic.h"
+#include "hardware/ps2.h"
+#include "hardware/speaker.h"
+#include "hardware/timer.h"
+#include "hardware/vga.h"
+
+#include "bop.h"
+#include "vddsup.h"
+#include "io.h"
+
+#include <isvbop.h>
+
+/* PRIVATE VARIABLES **********************************************************/
+
+FAST486_STATE EmulatorContext;
+BOOLEAN CpuSimulate = FALSE;
+
+/* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */
+static const INT MaxCpuCallLevel = 32;
+static INT CpuCallLevel = 0;
+
+LPVOID  BaseAddress = NULL;
+BOOLEAN VdmRunning  = TRUE;
+
+static BOOLEAN A20Line   = FALSE;
+static BYTE Port61hState = 0x00;
+
+static HANDLE InputThread = NULL;
+
+LPCWSTR ExceptionName[] =
+{
+    L"Division By Zero",
+    L"Debug",
+    L"Unexpected Error",
+    L"Breakpoint",
+    L"Integer Overflow",
+    L"Bound Range Exceeded",
+    L"Invalid Opcode",
+    L"FPU Not Available"
+};
+
+/* BOP Identifiers */
+#define BOP_DEBUGGER    0x56    // Break into the debugger from a 16-bit app
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    // BIG HACK!!!! To make BIOS images working correctly,
+    // until Aleksander rewrites memory management!!
+    if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
+
+    /* If the A20 line is disabled, mask bit 20 */
+    if (!A20Line) Address &= ~(1 << 20);
+
+    /* Make sure the requested address is valid */
+    if ((Address + Size) >= MAX_ADDRESS) return;
+
+    /*
+     * Check if we are going to read the VGA memory and
+     * copy it into the virtual address space if needed.
+     */
+    if (((Address + Size) >= VgaGetVideoBaseAddress())
+        && (Address < VgaGetVideoLimitAddress()))
+    {
+        DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
+                           - VgaAddress + 1;
+        LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
+
+        /* Read from the VGA memory */
+        VgaReadMemory(VgaAddress, DestBuffer, ActualSize);
+    }
+
+    /* Read the data from the virtual address space and store it in the buffer */
+    RtlCopyMemory(Buffer, REAL_TO_PHYS(Address), Size);
+}
+
+VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    // BIG HACK!!!! To make BIOS images working correctly,
+    // until Aleksander rewrites memory management!!
+    if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
+
+    /* If the A20 line is disabled, mask bit 20 */
+    if (!A20Line) Address &= ~(1 << 20);
+
+    /* Make sure the requested address is valid */
+    if ((Address + Size) >= MAX_ADDRESS) return;
+
+    /* Make sure we don't write to the ROM area */
+    if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;
+
+    /* Read the data from the buffer and store it in the virtual address space */
+    RtlCopyMemory(REAL_TO_PHYS(Address), Buffer, Size);
+
+    /*
+     * Check if we modified the VGA memory.
+     */
+    if (((Address + Size) >= VgaGetVideoBaseAddress())
+        && (Address < VgaGetVideoLimitAddress()))
+    {
+        DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
+                           - VgaAddress + 1;
+        LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
+
+        /* Write to the VGA memory */
+        VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
+    }
+}
+
+UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    /* Get the interrupt number from the PIC */
+    return PicGetInterrupt();
+}
+
+VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
+{
+    WORD CodeSegment, InstructionPointer;
+    PBYTE Opcode;
+
+    ASSERT(ExceptionNumber < 8);
+
+    /* Get the CS:IP */
+    InstructionPointer = Stack[STACK_IP];
+    CodeSegment = Stack[STACK_CS];
+    Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
+
+    /* Display a message to the user */
+    DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
+                   L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
+                   ExceptionName[ExceptionNumber],
+                   CodeSegment,
+                   InstructionPointer,
+                   Opcode[0],
+                   Opcode[1],
+                   Opcode[2],
+                   Opcode[3],
+                   Opcode[4],
+                   Opcode[5],
+                   Opcode[6],
+                   Opcode[7],
+                   Opcode[8],
+                   Opcode[9]);
+
+    /* Stop the VDM */
+    EmulatorTerminate();
+    return;
+}
+
+// FIXME: This function assumes 16-bit mode!!!
+VOID EmulatorExecute(WORD Segment, WORD Offset)
+{
+    /* Tell Fast486 to move the instruction pointer */
+    Fast486ExecuteAt(&EmulatorContext, Segment, Offset);
+}
+
+VOID EmulatorStep(VOID)
+{
+    /* Dump the state for debugging purposes */
+    // Fast486DumpState(&EmulatorContext);
+
+    /* Execute the next instruction */
+    Fast486StepInto(&EmulatorContext);
+}
+
+VOID EmulatorSimulate(VOID)
+{
+    if (CpuCallLevel > MaxCpuCallLevel)
+    {
+        DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)",
+                       CpuCallLevel, MaxCpuCallLevel);
+
+        /* Stop the VDM */
+        EmulatorTerminate();
+        return;
+    }
+    CpuCallLevel++;
+
+    CpuSimulate = TRUE;
+    while (VdmRunning && CpuSimulate) ClockUpdate();
+
+    CpuCallLevel--;
+    if (CpuCallLevel < 0) CpuCallLevel = 0;
+
+    /* This takes into account for reentrance */
+    CpuSimulate = TRUE;
+}
+
+VOID EmulatorUnsimulate(VOID)
+{
+    /* Stop simulation */
+    CpuSimulate = FALSE;
+}
+
+VOID EmulatorTerminate(VOID)
+{
+    /* Stop the VDM */
+    VdmRunning = FALSE;
+}
+
+VOID EmulatorInterrupt(BYTE Number)
+{
+    /* Call the Fast486 API */
+    Fast486Interrupt(&EmulatorContext, Number);
+}
+
+VOID EmulatorInterruptSignal(VOID)
+{
+    /* Call the Fast486 API */
+    Fast486InterruptSignal(&EmulatorContext);
+}
+
+VOID EmulatorSetA20(BOOLEAN Enabled)
+{
+    A20Line = Enabled;
+}
+
+static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
+{
+    DPRINT1("NTVDM: BOP_DEBUGGER\n");
+    DebugBreak();
+}
+
+static VOID WINAPI EmulatorUnsimulateBop(LPWORD Stack)
+{
+    EmulatorUnsimulate();
+}
+
+static BYTE WINAPI Port61hRead(ULONG Port)
+{
+    return Port61hState;
+}
+
+static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
+{
+    // BOOLEAN SpeakerChange = FALSE;
+    BYTE OldPort61hState = Port61hState;
+
+    /* Only the four lowest bytes can be written */
+    Port61hState = (Port61hState & 0xF0) | (Data & 0x0F);
+
+    if ((OldPort61hState ^ Port61hState) & 0x01)
+    {
+        DPRINT("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off");
+        // SpeakerChange = TRUE;
+    }
+
+    PitSetGate(2, !!(Port61hState & 0x01));
+
+    if ((OldPort61hState ^ Port61hState) & 0x02)
+    {
+        /* There were some change for the speaker... */
+        DPRINT("Speaker %s\n", Port61hState & 0x02 ? "on" : "off");
+        // SpeakerChange = TRUE;
+    }
+    // if (SpeakerChange) SpeakerChange();
+    SpeakerChange();
+}
+
+static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State)
+{
+    if (State)
+    {
+        DPRINT("PicInterruptRequest\n");
+        PicInterruptRequest(0); // Raise IRQ 0
+    }
+    // else < Lower IRQ 0 >
+}
+
+static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
+{
+#if 0
+    if (State)
+    {
+        /* Set bit 4 of Port 61h */
+        Port61hState |= 1 << 4;
+    }
+    else
+    {
+        /* Clear bit 4 of Port 61h */
+        Port61hState &= ~(1 << 4);
+    }
+#else
+    Port61hState = (Port61hState & 0xEF) | (State << 4);
+#endif
+}
+
+static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
+{
+    // BYTE OldPort61hState = Port61hState;
+
+#if 0
+    if (State)
+    {
+        /* Set bit 5 of Port 61h */
+        Port61hState |= 1 << 5;
+    }
+    else
+    {
+        /* Clear bit 5 of Port 61h */
+        Port61hState &= ~(1 << 5);
+    }
+#else
+    Port61hState = (Port61hState & 0xDF) | (State << 5);
+#endif
+    DPRINT("Speaker PIT out\n");
+    // if ((OldPort61hState ^ Port61hState) & 0x20)
+        // SpeakerChange();
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+DWORD WINAPI PumpConsoleInput(LPVOID Parameter);
+
+BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
+{
+    /* Allocate memory for the 16-bit address space */
+    BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
+    if (BaseAddress == NULL)
+    {
+        wprintf(L"FATAL: Failed to allocate VDM memory.\n");
+        return FALSE;
+    }
+
+    /* Initialize I/O ports */
+    /* Initialize RAM */
+
+    /* Initialize the internal clock */
+    if (!ClockInitialize())
+    {
+        wprintf(L"FATAL: Failed to initialize the clock\n");
+        return FALSE;
+    }
+
+    /* Initialize the CPU */
+    Fast486Initialize(&EmulatorContext,
+                      EmulatorReadMemory,
+                      EmulatorWriteMemory,
+                      EmulatorReadIo,
+                      EmulatorWriteIo,
+                      NULL,
+                      EmulatorBiosOperation,
+                      EmulatorIntAcknowledge,
+                      NULL /* TODO: Use a TLB */);
+
+    /* Initialize DMA */
+
+    /* Initialize the PIC, the PIT, the CMOS and the PC Speaker */
+    PicInitialize();
+    PitInitialize();
+    CmosInitialize();
+    SpeakerInitialize();
+
+    /* Set output functions */
+    PitSetOutFunction(0, NULL, PitChan0Out);
+    PitSetOutFunction(1, NULL, PitChan1Out);
+    PitSetOutFunction(2, NULL, PitChan2Out);
+
+    /* Register the I/O Ports */
+    RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite);
+
+    /* Set the console input mode */
+    // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions
+    // upon console window events (screen buffer resize, ...).
+    SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */);
+    // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+
+    /* Initialize the PS2 port */
+    PS2Initialize(ConsoleInput);
+
+    /**************** ATTACH INPUT WITH CONSOLE *****************/
+    /* Start the input thread */
+    InputThread = CreateThread(NULL, 0, &PumpConsoleInput, ConsoleInput, 0, NULL);
+    if (InputThread == NULL)
+    {
+        DisplayMessage(L"Failed to create the console input thread.");
+        return FALSE;
+    }
+    /************************************************************/
+
+    /* Initialize the VGA */
+    if (!VgaInitialize(ConsoleOutput))
+    {
+        DisplayMessage(L"Failed to initialize VGA support.");
+        return FALSE;
+    }
+
+    /* Initialize the software callback system and register the emulator BOPs */
+    InitializeCallbacks();
+    RegisterBop(BOP_DEBUGGER  , EmulatorDebugBreakBop);
+    RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop);
+
+    /* Initialize VDD support */
+    VDDSupInitialize();
+
+    return TRUE;
+}
+
+VOID EmulatorCleanup(VOID)
+{
+    VgaCleanup();
+
+    /* Close the input thread handle */
+    if (InputThread != NULL) CloseHandle(InputThread);
+    InputThread = NULL;
+
+    PS2Cleanup();
+
+    SpeakerCleanup();
+    CmosCleanup();
+    // PitCleanup();
+    // PicCleanup();
+
+    // Fast486Cleanup();
+
+    /* Free the memory allocated for the 16-bit address space */
+    if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
+}
+
+
+
+VOID
+WINAPI
+VDDSimulate16(VOID)
+{
+    EmulatorSimulate();
+}
+
+VOID
+WINAPI
+VDDTerminateVDM(VOID)
+{
+    /* Stop the VDM */
+    EmulatorTerminate();
+}
+
+PBYTE
+WINAPI
+Sim32pGetVDMPointer(IN ULONG   Address,
+                    IN BOOLEAN ProtectedMode)
+{
+    // FIXME
+    UNREFERENCED_PARAMETER(ProtectedMode);
+
+    /*
+     * HIWORD(Address) == Segment  (if ProtectedMode == FALSE)
+     *                 or Selector (if ProtectedMode == TRUE )
+     * LOWORD(Address) == Offset
+     */
+    return (PBYTE)FAR_POINTER(Address);
+}
+
+PBYTE
+WINAPI
+MGetVdmPointer(IN ULONG   Address,
+               IN ULONG   Size,
+               IN BOOLEAN ProtectedMode)
+{
+    UNREFERENCED_PARAMETER(Size);
+    return Sim32pGetVDMPointer(Address, ProtectedMode);
+}
+
+PVOID
+WINAPI
+VdmMapFlat(IN USHORT   Segment,
+           IN ULONG    Offset,
+           IN VDM_MODE Mode)
+{
+    // FIXME
+    UNREFERENCED_PARAMETER(Mode);
+
+    return SEG_OFF_TO_PTR(Segment, Offset);
+}
+
+BOOL
+WINAPI
+VdmFlushCache(IN USHORT   Segment,
+              IN ULONG    Offset,
+              IN ULONG    Size,
+              IN VDM_MODE Mode)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return TRUE;
+}
+
+BOOL
+WINAPI
+VdmUnmapFlat(IN USHORT   Segment,
+             IN ULONG    Offset,
+             IN PVOID    Buffer,
+             IN VDM_MODE Mode)
+{
+    // FIXME
+    UNIMPLEMENTED;
+    return TRUE;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h
new file mode 100644 (file)
index 0000000..1b1337f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            emulator.h
+ * PURPOSE:         Minimal x86 machine emulator for the VDM
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _EMULATOR_H_
+#define _EMULATOR_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include <fast486.h>
+
+/* DEFINES ********************************************************************/
+
+/* FLAGS */
+#define EMULATOR_FLAG_CF (1 << 0)
+#define EMULATOR_FLAG_PF (1 << 2)
+#define EMULATOR_FLAG_AF (1 << 4)
+#define EMULATOR_FLAG_ZF (1 << 6)
+#define EMULATOR_FLAG_SF (1 << 7)
+#define EMULATOR_FLAG_TF (1 << 8)
+#define EMULATOR_FLAG_IF (1 << 9)
+#define EMULATOR_FLAG_DF (1 << 10)
+#define EMULATOR_FLAG_OF (1 << 11)
+#define EMULATOR_FLAG_NT (1 << 14)
+#define EMULATOR_FLAG_RF (1 << 16)
+#define EMULATOR_FLAG_VM (1 << 17)
+#define EMULATOR_FLAG_AC (1 << 18)
+#define EMULATOR_FLAG_VIF (1 << 19)
+#define EMULATOR_FLAG_VIP (1 << 20)
+#define EMULATOR_FLAG_ID (1 << 21)
+
+//
+// WARNING WARNING!!
+// If you're changing the indices here, you then need to
+// also fix the BOP code in callback.c !!!!!!!!!!!!!!!!!
+//
+#define STACK_INT_NUM   0
+#define STACK_IP        1
+#define STACK_CS        2
+#define STACK_FLAGS     3
+
+
+/* Basic Memory Management */
+#define MEM_ALIGN_UP(ptr, align)    MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align))
+#define MEM_ALIGN_DOWN(ptr, align)  (PVOID)((ULONG_PTR)(ptr) & ~((align) - 1l))
+
+#define TO_LINEAR(seg, off) (((seg) << 4) + (off))
+#define MAX_SEGMENT 0xFFFF
+#define MAX_OFFSET  0xFFFF
+#define MAX_ADDRESS 0x1000000 // 16 MB of RAM
+
+#define FAR_POINTER(x)  \
+    (PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR(HIWORD(x), LOWORD(x)))
+
+#define SEG_OFF_TO_PTR(seg, off)    \
+    (PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), (off)))
+
+#define REAL_TO_PHYS(ptr)   (PVOID)((ULONG_PTR)(ptr) + (ULONG_PTR)BaseAddress)
+#define PHYS_TO_REAL(ptr)   (PVOID)((ULONG_PTR)(ptr) - (ULONG_PTR)BaseAddress)
+
+
+/* BCD-Binary conversion */
+#define BINARY_TO_BCD(x) ((((x) / 1000) << 12) + (((x) / 100) << 8) + (((x) / 10) << 4) + ((x) % 10))
+#define BCD_TO_BINARY(x) (((x) >> 12) * 1000 + ((x) >> 8) * 100 + ((x) >> 4) * 10 + ((x) & 0x0F))
+
+
+/* System I/O ports */
+#define CONTROL_SYSTEM_PORT61H  0x61
+
+
+enum
+{
+    EMULATOR_EXCEPTION_DIVISION_BY_ZERO,
+    EMULATOR_EXCEPTION_DEBUG,
+    EMULATOR_EXCEPTION_NMI,
+    EMULATOR_EXCEPTION_BREAKPOINT,
+    EMULATOR_EXCEPTION_OVERFLOW,
+    EMULATOR_EXCEPTION_BOUND,
+    EMULATOR_EXCEPTION_INVALID_OPCODE,
+    EMULATOR_EXCEPTION_NO_FPU,
+    EMULATOR_EXCEPTION_DOUBLE_FAULT,
+    EMULATOR_EXCEPTION_FPU_SEGMENT,
+    EMULATOR_EXCEPTION_INVALID_TSS,
+    EMULATOR_EXCEPTION_NO_SEGMENT,
+    EMULATOR_EXCEPTION_STACK_SEGMENT,
+    EMULATOR_EXCEPTION_GPF,
+    EMULATOR_EXCEPTION_PAGE_FAULT
+};
+
+extern FAST486_STATE EmulatorContext;
+extern LPVOID  BaseAddress;
+extern BOOLEAN VdmRunning;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID WINAPI EmulatorReadMemory
+(
+    PFAST486_STATE State,
+    ULONG Address,
+    PVOID Buffer,
+    ULONG Size
+);
+
+VOID WINAPI EmulatorWriteMemory
+(
+    PFAST486_STATE State,
+    ULONG Address,
+    PVOID Buffer,
+    ULONG Size
+);
+
+UCHAR WINAPI EmulatorIntAcknowledge
+(
+    PFAST486_STATE State
+);
+
+VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack);
+
+VOID EmulatorExecute(WORD Segment, WORD Offset);
+VOID EmulatorStep(VOID);
+VOID EmulatorSimulate(VOID);
+VOID EmulatorUnsimulate(VOID);
+VOID EmulatorTerminate(VOID);
+
+VOID EmulatorInterrupt(BYTE Number);
+VOID EmulatorInterruptSignal(VOID);
+VOID EmulatorSetA20(BOOLEAN Enabled);
+
+BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput);
+VOID EmulatorCleanup(VOID);
+
+#endif // _EMULATOR_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/cmos.c b/subsystems/ntvdm/hardware/cmos.c
new file mode 100644 (file)
index 0000000..4f86467
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            cmos.c
+ * PURPOSE:         CMOS Real Time Clock emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "cmos.h"
+
+#include "io.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static HANDLE hCmosRam = INVALID_HANDLE_VALUE;
+static CMOS_MEMORY CmosMemory;
+
+static BOOLEAN NmiEnabled = TRUE;
+static CMOS_REGISTERS SelectedRegister = CMOS_REG_STATUS_D;
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN IsNmiEnabled(VOID)
+{
+    return NmiEnabled;
+}
+
+VOID CmosWriteAddress(BYTE Value)
+{
+    /* Update the NMI enabled flag */
+    NmiEnabled = !(Value & CMOS_DISABLE_NMI);
+    
+    /* Get the register number */
+    Value &= ~CMOS_DISABLE_NMI;
+
+    if (Value < CMOS_REG_MAX)
+    {
+        /* Select the new register */
+        SelectedRegister = Value;
+    }
+    else
+    {
+        /* Default to Status Register D */
+        SelectedRegister = CMOS_REG_STATUS_D;
+    }
+}
+
+BYTE CmosReadData(VOID)
+{
+    SYSTEMTIME CurrentTime;
+
+    /* Get the current time */
+    GetLocalTime(&CurrentTime);
+
+    switch (SelectedRegister)
+    {
+        case CMOS_REG_SECONDS:
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wSecond);
+
+        case CMOS_REG_ALARM_SEC:
+            return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmSecond);
+
+        case CMOS_REG_MINUTES:
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wMinute);
+
+        case CMOS_REG_ALARM_MIN:
+            return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmMinute);
+
+        case CMOS_REG_HOURS:
+        {
+            BOOLEAN Afternoon = FALSE;
+            BYTE Value = CurrentTime.wHour;
+
+            if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
+            {
+                Value -= 12;
+                Afternoon = TRUE;
+            }
+
+            Value = READ_CMOS_DATA(CmosMemory, Value);
+
+            /* Convert to 12-hour */
+            if (Afternoon) Value |= 0x80;
+
+            return Value;
+        }
+
+        case CMOS_REG_ALARM_HRS:
+        {
+            BOOLEAN Afternoon = FALSE;
+            BYTE Value = CmosMemory.AlarmHour;
+
+            if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
+            {
+                Value -= 12;
+                Afternoon = TRUE;
+            }
+
+            Value = READ_CMOS_DATA(CmosMemory, Value);
+
+            /* Convert to 12-hour */
+            if (Afternoon) Value |= 0x80;
+
+            return Value;
+        }
+
+        case CMOS_REG_DAY_OF_WEEK:
+            /*
+             * The CMOS value is 1-based but the
+             * GetLocalTime API value is 0-based.
+             * Correct it.
+             */
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wDayOfWeek + 1);
+
+        case CMOS_REG_DAY:
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wDay);
+
+        case CMOS_REG_MONTH:
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wMonth);
+
+        case CMOS_REG_YEAR:
+            return READ_CMOS_DATA(CmosMemory, CurrentTime.wYear % 100);
+
+        case CMOS_REG_STATUS_C:
+        {
+            BYTE Value = CmosMemory.StatusRegC;
+
+            /* Clear status register C */
+            CmosMemory.StatusRegC = 0x00;
+
+            /* Return the old value */
+            return Value;
+        }
+
+        case CMOS_REG_STATUS_A:
+        case CMOS_REG_STATUS_B:
+        case CMOS_REG_STATUS_D:
+        case CMOS_REG_DIAGNOSTICS:
+        case CMOS_REG_SHUTDOWN_STATUS:
+        default:
+        {
+            // ASSERT(SelectedRegister < CMOS_REG_MAX);
+            return CmosMemory.Regs[SelectedRegister];
+        }
+    }
+
+    /* Return to Status Register D */
+    SelectedRegister = CMOS_REG_STATUS_D;
+}
+
+VOID CmosWriteData(BYTE Value)
+{
+    BOOLEAN ChangeTime = FALSE;
+    SYSTEMTIME CurrentTime;
+
+    /* Get the current time */
+    GetLocalTime(&CurrentTime);
+
+    switch (SelectedRegister)
+    {
+        case CMOS_REG_SECONDS:
+        {
+            ChangeTime = TRUE;
+            CurrentTime.wSecond = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_ALARM_SEC:
+        {
+            CmosMemory.AlarmSecond = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_MINUTES:
+        {
+            ChangeTime = TRUE;
+            CurrentTime.wMinute = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_ALARM_MIN:
+        {
+            CmosMemory.AlarmMinute = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_HOURS:
+        {
+            BOOLEAN Afternoon = FALSE;
+
+            ChangeTime = TRUE;
+
+            if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
+            {
+                Value &= ~0x80;
+                Afternoon = TRUE;
+            }
+
+            CurrentTime.wHour = WRITE_CMOS_DATA(CmosMemory, Value);
+
+            /* Convert to 24-hour format */
+            if (Afternoon) CurrentTime.wHour += 12;
+
+            break;
+        }
+
+        case CMOS_REG_ALARM_HRS:
+        {
+            BOOLEAN Afternoon = FALSE;
+
+            if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
+            {
+                Value &= ~0x80;
+                Afternoon = TRUE;
+            }
+
+            CmosMemory.AlarmHour = WRITE_CMOS_DATA(CmosMemory, Value);
+
+            /* Convert to 24-hour format */
+            if (Afternoon) CmosMemory.AlarmHour += 12;
+
+            break;
+        }
+
+        case CMOS_REG_DAY_OF_WEEK:
+        {
+            ChangeTime = TRUE;
+            /*
+             * The CMOS value is 1-based but the
+             * SetLocalTime API value is 0-based.
+             * Correct it.
+             */
+            Value -= 1;
+            CurrentTime.wDayOfWeek = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_DAY:
+        {
+            ChangeTime = TRUE;
+            CurrentTime.wDay = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_MONTH:
+        {
+            ChangeTime = TRUE;
+            CurrentTime.wMonth = WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_YEAR:
+        {
+            ChangeTime = TRUE;
+
+            /* Clear everything except the century */
+            CurrentTime.wYear = (CurrentTime.wYear / 100) * 100;
+
+            CurrentTime.wYear += WRITE_CMOS_DATA(CmosMemory, Value);
+            break;
+        }
+
+        case CMOS_REG_STATUS_A:
+        {
+            CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only
+            break;
+        }
+
+        case CMOS_REG_STATUS_B:
+        {
+            CmosMemory.StatusRegB = Value;
+            break;
+        }
+
+        case CMOS_REG_STATUS_C:
+        case CMOS_REG_STATUS_D:
+            // Status registers C and D are read-only
+            break;
+
+        /* Is the following correct? */
+        case CMOS_REG_EXT_MEMORY_LOW:
+        case CMOS_REG_ACTUAL_EXT_MEMORY_LOW:
+        {
+            /* Sync EMS and UMS */
+            CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW]        =
+            CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = Value;
+            break;
+        }
+
+        /* Is the following correct? */
+        case CMOS_REG_EXT_MEMORY_HIGH:
+        case CMOS_REG_ACTUAL_EXT_MEMORY_HIGH:
+        {
+            /* Sync EMS and UMS */
+            CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH]        =
+            CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = Value;
+            break;
+        }
+
+        default:
+        {
+            CmosMemory.Regs[SelectedRegister] = Value;
+        }
+    }
+
+    if (ChangeTime) SetLocalTime(&CurrentTime);
+
+    /* Return to Status Register D */
+    SelectedRegister = CMOS_REG_STATUS_D;
+}
+
+BYTE WINAPI CmosReadPort(ULONG Port)
+{
+    ASSERT(Port == CMOS_DATA_PORT);
+    return CmosReadData();
+}
+
+VOID WINAPI CmosWritePort(ULONG Port, BYTE Data)
+{
+    if (Port == CMOS_ADDRESS_PORT)
+        CmosWriteAddress(Data);
+    else if (Port == CMOS_DATA_PORT)
+        CmosWriteData(Data);
+}
+
+DWORD RtcGetTicksPerSecond(VOID)
+{
+    BYTE RateSelect = CmosMemory.StatusRegB & 0x0F;
+
+    if (RateSelect == 0)
+    {
+        /* No periodic interrupt */
+        return 0;
+    }
+
+    /* 1 and 2 act like 8 and 9 */
+    if (RateSelect <= 2) RateSelect += 7;
+
+    return 1 << (16 - RateSelect);
+}
+
+VOID RtcPeriodicTick(VOID)
+{
+    /* Set PF */
+    CmosMemory.StatusRegC |= CMOS_STC_PF;
+
+    /* Check if there should be an interrupt on a periodic timer tick */
+    if (CmosMemory.StatusRegB & CMOS_STB_INT_PERIODIC)
+    {
+        CmosMemory.StatusRegC |= CMOS_STC_IRQF;
+
+        /* Interrupt! */
+        PicInterruptRequest(RTC_IRQ_NUMBER);
+    }
+}
+
+/* Should be called every second */
+VOID RtcTimeUpdate(VOID)
+{
+    SYSTEMTIME CurrentTime;
+
+    /* Get the current time */
+    GetLocalTime(&CurrentTime);
+
+    /* Set UF */
+    CmosMemory.StatusRegC |= CMOS_STC_UF;
+
+    /* Check if the time matches the alarm time */
+    if ((CurrentTime.wHour   == CmosMemory.AlarmHour  ) &&
+        (CurrentTime.wMinute == CmosMemory.AlarmMinute) &&
+        (CurrentTime.wSecond == CmosMemory.AlarmSecond))
+    {
+        /* Set the alarm flag */
+        CmosMemory.StatusRegC |= CMOS_STC_AF;
+
+        /* Set IRQF if there should be an interrupt */
+        if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_ALARM) CmosMemory.StatusRegC |= CMOS_STC_IRQF;
+    }
+
+    /* Check if there should be an interrupt on update */
+    if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_UPDATE) CmosMemory.StatusRegC |= CMOS_STC_IRQF;
+
+    if (CmosMemory.StatusRegC & CMOS_STC_IRQF)
+    {
+        /* Interrupt! */
+        PicInterruptRequest(RTC_IRQ_NUMBER);
+    }
+}
+
+VOID CmosInitialize(VOID)
+{
+    DWORD CmosSize = sizeof(CmosMemory);
+
+    /* File must not be opened before */
+    ASSERT(hCmosRam == INVALID_HANDLE_VALUE);
+
+    /* Clear the CMOS memory */
+    ZeroMemory(&CmosMemory, sizeof(CmosMemory));
+
+    /* Always open (and if needed, create) a RAM file with shared access */
+    SetLastError(0); // For debugging purposes
+    hCmosRam = CreateFileW(L"cmos.ram",
+                           GENERIC_READ | GENERIC_WRITE,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           NULL,
+                           OPEN_ALWAYS,
+                           FILE_ATTRIBUTE_NORMAL,
+                           NULL);
+    DPRINT1("CMOS opening %s ; GetLastError() = %u\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError());
+
+    if (hCmosRam != INVALID_HANDLE_VALUE)
+    {
+        BOOL Success;
+
+        /* Attempt to fill the CMOS memory with the RAM file */
+        SetLastError(0); // For debugging purposes
+        Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
+        if (CmosSize != sizeof(CmosMemory))
+        {
+            /* Bad CMOS Ram file. Reinitialize the CMOS memory. */
+            DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n", CmosSize, sizeof(CmosMemory));
+            ZeroMemory(&CmosMemory, sizeof(CmosMemory));
+        }
+        DPRINT1("CMOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+        SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
+    }
+
+    /* Overwrite some registers with default values */
+    CmosMemory.StatusRegA     = CMOS_DEFAULT_STA;
+    CmosMemory.StatusRegB     = CMOS_DEFAULT_STB;
+    CmosMemory.StatusRegC     = 0x00;
+    CmosMemory.StatusRegD     = CMOS_BATTERY_OK; // Our CMOS battery works perfectly forever.
+    CmosMemory.Diagnostics    = 0x00;            // Diagnostics must not find any errors.
+    CmosMemory.ShutdownStatus = 0x00;
+
+    /* Memory settings */
+
+    /*
+     * Conventional memory size is 640 kB,
+     * see: http://webpages.charter.net/danrollins/techhelp/0184.HTM
+     * and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm
+     * for more information.
+     */
+    CmosMemory.Regs[CMOS_REG_BASE_MEMORY_LOW ] = LOBYTE(0x0280);
+    CmosMemory.Regs[CMOS_REG_BASE_MEMORY_HIGH] = HIBYTE(0x0280);
+
+    CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW]         =
+    CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW]  = LOBYTE((MAX_ADDRESS - 0x100000) / 1024);
+
+    CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH]        =
+    CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = HIBYTE((MAX_ADDRESS - 0x100000) / 1024);
+
+    /* Register the I/O Ports */
+    RegisterIoPort(CMOS_ADDRESS_PORT, NULL        , CmosWritePort);
+    RegisterIoPort(CMOS_DATA_PORT   , CmosReadPort, CmosWritePort);
+}
+
+VOID CmosCleanup(VOID)
+{
+    DWORD CmosSize = sizeof(CmosMemory);
+
+    if (hCmosRam == INVALID_HANDLE_VALUE) return;
+
+    /* Flush the CMOS memory back to the RAM file and close it */
+    SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
+    WriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
+
+    CloseHandle(hCmosRam);
+    hCmosRam = INVALID_HANDLE_VALUE;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/cmos.h b/subsystems/ntvdm/hardware/cmos.h
new file mode 100644 (file)
index 0000000..f84d27c
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            cmos.h
+ * PURPOSE:         CMOS Real Time Clock emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _CMOS_H_
+#define _CMOS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define RTC_IRQ_NUMBER      8
+#define CMOS_ADDRESS_PORT   0x70
+#define CMOS_DATA_PORT      0x71
+#define CMOS_DISABLE_NMI    (1 << 7)
+#define CMOS_BATTERY_OK     0x80
+
+/* Status Register B flags */
+#define CMOS_STB_24HOUR         (1 << 1)
+#define CMOS_STB_BINARY         (1 << 2)
+#define CMOS_STB_SQUARE_WAVE    (1 << 3)
+#define CMOS_STB_INT_ON_UPDATE  (1 << 4)
+#define CMOS_STB_INT_ON_ALARM   (1 << 5)
+#define CMOS_STB_INT_PERIODIC   (1 << 6)
+
+/* Status Register C flags */
+#define CMOS_STC_UF     CMOS_STB_INT_ON_UPDATE
+#define CMOS_STC_AF     CMOS_STB_INT_ON_ALARM
+#define CMOS_STC_PF     CMOS_STB_INT_PERIODIC
+#define CMOS_STC_IRQF   (1 << 7)
+
+/* Default register values */
+#define CMOS_DEFAULT_STA 0x26
+#define CMOS_DEFAULT_STB CMOS_STB_24HOUR
+
+#define WRITE_CMOS_DATA(Cmos, Value)    \
+    ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value)
+
+#define READ_CMOS_DATA(Cmos, Value)     \
+    ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BINARY_TO_BCD(Value)
+
+typedef enum _CMOS_REGISTERS
+{
+    CMOS_REG_SECONDS,
+    CMOS_REG_ALARM_SEC,
+    CMOS_REG_MINUTES,
+    CMOS_REG_ALARM_MIN,
+    CMOS_REG_HOURS,
+    CMOS_REG_ALARM_HRS,
+    CMOS_REG_DAY_OF_WEEK,
+    CMOS_REG_DAY,
+    CMOS_REG_MONTH,
+    CMOS_REG_YEAR,
+    CMOS_REG_STATUS_A,
+    CMOS_REG_STATUS_B,
+    CMOS_REG_STATUS_C,
+    CMOS_REG_STATUS_D,
+    CMOS_REG_DIAGNOSTICS,
+    CMOS_REG_SHUTDOWN_STATUS,
+    CMOS_REG_BASE_MEMORY_LOW        = 0x15,
+    CMOS_REG_BASE_MEMORY_HIGH       = 0x16,
+    CMOS_REG_EXT_MEMORY_LOW         = 0x17,
+    CMOS_REG_EXT_MEMORY_HIGH        = 0x18,
+    CMOS_REG_ACTUAL_EXT_MEMORY_LOW  = 0x30,
+    CMOS_REG_ACTUAL_EXT_MEMORY_HIGH = 0x31,
+    CMOS_REG_MAX                    = 0x40
+} CMOS_REGISTERS, *PCMOS_REGISTERS;
+
+/*
+ * CMOS Memory Map
+ *
+ * See the following documentation for more information:
+ * http://www.intel-assembler.it/portale/5/cmos-memory-map-123/cmos-memory-map-123.asp
+ * http://wiki.osdev.org/CMOS
+ * http://www.walshcomptech.com/ohlandl/config/cmos_registers.html
+ * http://www.fysnet.net/cmosinfo.htm
+ * http://www.bioscentral.com/misc/cmosmap.htm
+ */
+#pragma pack(push, 1)
+typedef struct
+{
+    BYTE Second;        // 0x00
+    BYTE AlarmSecond;   // 0x01
+    BYTE Minute;        // 0x02
+    BYTE AlarmMinute;   // 0x03
+    BYTE Hour;          // 0x04
+    BYTE AlarmHour;     // 0x05
+    BYTE DayOfWeek;     // 0x06
+    BYTE Day;           // 0x07
+    BYTE Month;         // 0x08
+    BYTE Year;          // 0x09
+
+    BYTE StatusRegA;    // 0x0a
+    BYTE StatusRegB;    // 0x0b
+} CMOS_CLOCK, *PCMOS_CLOCK;
+
+typedef struct
+{
+    union
+    {
+        struct
+        {
+            CMOS_CLOCK;             // 0x00 - 0x0b
+            BYTE StatusRegC;        // 0x0c
+            BYTE StatusRegD;        // 0x0d
+            BYTE Diagnostics;       // 0x0e
+            BYTE ShutdownStatus;    // 0x0f
+        };
+        BYTE Regs1[0x10];           // 0x00 - 0x0f
+        BYTE Regs [0x40];           // 0x00 - 0x3f
+    };
+
+    /*
+     * Extended information 0x40 - 0x7f
+     */
+} CMOS_MEMORY, *PCMOS_MEMORY;
+#pragma pack(pop)
+
+C_ASSERT(sizeof(CMOS_MEMORY) == 0x40);
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN IsNmiEnabled(VOID);
+DWORD RtcGetTicksPerSecond(VOID);
+VOID RtcPeriodicTick(VOID);
+VOID RtcTimeUpdate(VOID);
+
+VOID CmosInitialize(VOID);
+VOID CmosCleanup(VOID);
+
+#endif // _CMOS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/pic.c b/subsystems/ntvdm/hardware/pic.c
new file mode 100644 (file)
index 0000000..a5b068c
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            pic.c
+ * PURPOSE:         Programmable Interrupt Controller emulation
+ *                  (Interrupt Controller Adapter (ICA) in Windows terminology)
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "io.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static PIC MasterPic, SlavePic;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static BYTE PicReadCommand(BYTE Port)
+{
+    PPIC Pic;
+
+    /* Which PIC are we accessing? */
+    if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
+    else Pic = &SlavePic;
+
+    if (Pic->ReadIsr)
+    {
+        /* Read the in-service register */
+        Pic->ReadIsr = FALSE;
+        return Pic->InServiceRegister;
+    }
+    else
+    {
+        /* Read the interrupt request register */
+        return Pic->IntRequestRegister;
+    }
+}
+
+static VOID PicWriteCommand(BYTE Port, BYTE Value)
+{
+    PPIC Pic;
+
+    /* Which PIC are we accessing? */
+    if (Port == PIC_MASTER_CMD) Pic = &MasterPic;
+    else Pic = &SlavePic;
+
+    if (Value & PIC_ICW1)
+    {
+        /* Start initialization */
+        Pic->Initialization = TRUE;
+        Pic->IntOffset = 0xFF;
+        Pic->CascadeRegisterSet = FALSE;
+        Pic->ConfigRegister = Value;
+        return;
+    }
+
+    if (Value & PIC_OCW3)
+    {
+        /* This is an OCR3 */
+        if (Value == PIC_OCW3_READ_ISR)
+        {
+            /* Return the ISR on next read from command port */
+            Pic->ReadIsr = TRUE;
+        }
+
+        return;
+    }
+
+    /* This is an OCW2 */
+    if (Value & PIC_OCW2_EOI)
+    {
+        if (Value & PIC_OCW2_SL)
+        {
+            /* If the SL bit is set, clear a specific IRQ */
+            Pic->InServiceRegister &= ~(1 << (Value & PIC_OCW2_NUM_MASK));
+        }
+        else
+        {
+            /* Otherwise, clear all of them */
+            Pic->InServiceRegister = 0;
+        }
+    }
+}
+
+static BYTE PicReadData(BYTE Port)
+{
+    /* Read the mask register */
+    if (Port == PIC_MASTER_DATA) return MasterPic.MaskRegister;
+    else return SlavePic.MaskRegister;
+}
+
+static VOID PicWriteData(BYTE Port, BYTE Value)
+{
+    PPIC Pic;
+
+    /* Which PIC are we accessing? */
+    if (Port == PIC_MASTER_DATA) Pic = &MasterPic;
+    else Pic = &SlavePic;
+
+    /* Is the PIC ready? */
+    if (!Pic->Initialization)
+    {
+        /* Yes, this is an OCW1 */
+        Pic->MaskRegister = Value;
+        return;
+    }
+
+    /* Has the interrupt offset been set? */
+    if (Pic->IntOffset == 0xFF)
+    {
+        /* This is an ICW2, set the offset (last three bits always zero) */
+        Pic->IntOffset = Value & 0xF8;
+
+        /* Check if we are in single mode and don't need an ICW4 */
+        if ((Pic->ConfigRegister & PIC_ICW1_SINGLE)
+            && !(Pic->ConfigRegister & PIC_ICW1_ICW4))
+        {
+            /* Yes, done initializing */
+            Pic->Initialization = FALSE;
+        }
+        return;
+    }
+
+    /* Check if we are in cascade mode and the cascade register was not set */
+    if (!(Pic->ConfigRegister & PIC_ICW1_SINGLE) && !Pic->CascadeRegisterSet)
+    {
+        /* This is an ICW3 */
+        Pic->CascadeRegister = Value;
+        Pic->CascadeRegisterSet = TRUE;
+
+        /* Check if we need an ICW4 */
+        if (!(Pic->ConfigRegister & PIC_ICW1_ICW4))
+        {
+            /* No, done initializing */
+            Pic->Initialization = FALSE;
+        }
+        return;
+    }
+
+    /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */
+    if (Value & PIC_ICW4_AEOI)
+    {
+        /* Use automatic end-of-interrupt */
+        Pic->AutoEoi = TRUE;
+    }
+
+    /* Done initializing */
+    Pic->Initialization = FALSE;
+}
+
+static BYTE WINAPI PicReadPort(ULONG Port)
+{
+    switch (Port)
+    {
+        case PIC_MASTER_CMD:
+        case PIC_SLAVE_CMD:
+        {
+            return PicReadCommand(Port);
+        }
+
+        case PIC_MASTER_DATA:
+        case PIC_SLAVE_DATA:
+        {
+            return PicReadData(Port);
+        }
+    }
+
+    return 0;
+}
+
+static VOID WINAPI PicWritePort(ULONG Port, BYTE Data)
+{
+    switch (Port)
+    {
+        case PIC_MASTER_CMD:
+        case PIC_SLAVE_CMD:
+        {
+            PicWriteCommand(Port, Data);
+            break;
+        }
+
+        case PIC_MASTER_DATA:
+        case PIC_SLAVE_DATA:
+        {
+            PicWriteData(Port, Data);
+            break;
+        }
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID PicInterruptRequest(BYTE Number)
+{
+    BYTE i;
+
+    if (/* Number >= 0 && */ Number < 8)
+    {
+        /* Check if any of the higher-priority interrupts are busy */
+        for (i = 0; i <= Number; i++)
+        {
+            if (MasterPic.InServiceRegister & (1 << Number)) return;
+        }
+
+        /* Check if the interrupt is masked */
+        if (MasterPic.MaskRegister & (1 << Number)) return;
+
+        /* Set the appropriate bit in the IRR and interrupt the CPU */
+        MasterPic.IntRequestRegister |= 1 << Number;
+        EmulatorInterruptSignal();
+    }
+    else if (Number >= 8 && Number < 16)
+    {
+        Number -= 8;
+
+        /*
+         * The slave PIC is connected to IRQ 2, always! If the master PIC
+         * was misconfigured, don't do anything.
+         */
+        if (!(MasterPic.CascadeRegister & (1 << 2))
+            || SlavePic.CascadeRegister != 2)
+        {
+            return;
+        }
+
+        /* Check if any of the higher-priority interrupts are busy */
+        if (MasterPic.InServiceRegister != 0) return;
+        for (i = 0; i <= Number; i++)
+        {
+            if (SlavePic.InServiceRegister & (1 << Number)) return;
+        }
+
+        /* Check if the interrupt is masked */
+        if (SlavePic.MaskRegister & (1 << Number)) return;
+
+        /* Set the IRQ 2 bit in the master ISR */
+        if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << 2);
+
+        /* Set the appropriate bit in the IRR and interrupt the CPU */
+        SlavePic.IntRequestRegister |= 1 << Number;
+        EmulatorInterruptSignal();
+    }
+}
+
+BYTE PicGetInterrupt(VOID)
+{
+    INT i, j;
+
+    /* Search interrupts by priority */
+    for (i = 0; i < 8; i++)
+    {
+        /* Check if this line is cascaded to the slave PIC */
+        if ((i == 2)
+            && MasterPic.CascadeRegister & (1 << 2)
+            && SlavePic.Slave
+            && (SlavePic.CascadeRegister == 2))
+        {
+            /* Search the slave PIC interrupts by priority */
+            for (j = 0; j < 8; j++) if ((j != 1) && SlavePic.IntRequestRegister & (1 << j))
+            {
+                /* Clear the IRR flag */
+                SlavePic.IntRequestRegister &= ~(1 << j);
+
+                /* Set the ISR flag, unless AEOI is enabled */
+                if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= (1 << j);
+    
+                /* Return the interrupt number */
+                return SlavePic.IntOffset + j;
+            }
+        }
+
+        if (MasterPic.IntRequestRegister & (1 << i))
+        {
+            /* Clear the IRR flag */
+            MasterPic.IntRequestRegister &= ~(1 << i);
+
+            /* Set the ISR flag, unless AEOI is enabled */
+            if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << i);
+
+            /* Return the interrupt number */
+            return MasterPic.IntOffset + i;
+        }
+    }
+    
+    /* Spurious interrupt */
+    if (MasterPic.InServiceRegister & (1 << 2)) return SlavePic.IntOffset + 7;
+    else return MasterPic.IntOffset + 7;
+}
+
+VOID PicInitialize(VOID)
+{
+    /* Register the I/O Ports */
+    RegisterIoPort(PIC_MASTER_CMD , PicReadPort, PicWritePort);
+    RegisterIoPort(PIC_SLAVE_CMD  , PicReadPort, PicWritePort);
+    RegisterIoPort(PIC_MASTER_DATA, PicReadPort, PicWritePort);
+    RegisterIoPort(PIC_SLAVE_DATA , PicReadPort, PicWritePort);
+}
+
+
+
+VOID
+WINAPI
+call_ica_hw_interrupt(INT  ms,
+                      BYTE line,
+                      INT  count)
+{
+    BYTE InterruptNumber = line;
+
+    /* Check for PIC validity */
+    if (ms != ICA_MASTER && ms != ICA_SLAVE) return;
+
+    /*
+     * Adjust the interrupt request number according to the parameters,
+     * by adding an offset == 8 to the interrupt number.
+     * 
+     * Indeed VDDs calling this function usually subtracts 8 so that they give:
+     *
+     *      ms     |  line  | corresponding interrupt number
+     * ------------+--------+--------------------------------
+     *  ICA_MASTER | 0 -- 7 |            0 -- 7
+     *  ICA_SLAVE  | 0 -- 7 |            8 -- 15
+     *
+     * and PicInterruptRequest subtracts again 8 to the interrupt number
+     * if it is greater or equal than 8 (so that it determines which PIC
+     * to use via the interrupt number).
+     */
+    if (ms == ICA_SLAVE) InterruptNumber += 8;
+
+    /* Send the specified number of interrupt requests */
+    while (count-- > 0)
+    {
+        PicInterruptRequest(InterruptNumber);
+    }
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/pic.h b/subsystems/ntvdm/hardware/pic.h
new file mode 100644 (file)
index 0000000..03d7dd1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            pic.h
+ * PURPOSE:         Programmable Interrupt Controller emulation
+ *                  (Interrupt Controller Adapter (ICA) in Windows terminology)
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _PIC_H_
+#define _PIC_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define PIC_MASTER_CMD  0x20
+#define PIC_MASTER_DATA 0x21
+#define PIC_SLAVE_CMD   0xA0
+#define PIC_SLAVE_DATA  0xA1
+
+#define PIC_ICW1        0x10
+#define PIC_ICW1_ICW4   (1 << 0)
+#define PIC_ICW1_SINGLE (1 << 1)
+#define PIC_ICW4_8086   (1 << 0)
+#define PIC_ICW4_AEOI   (1 << 1)
+
+#define PIC_OCW2_NUM_MASK   0x07
+#define PIC_OCW2_EOI        (1 << 5)
+#define PIC_OCW2_SL         (1 << 6)
+
+#define PIC_OCW3            (1 << 3)
+#define PIC_OCW3_READ_ISR   0x0B
+
+typedef struct _PIC
+{
+    BOOLEAN Initialization;
+    BYTE MaskRegister;
+    BYTE IntRequestRegister;
+    BYTE InServiceRegister;
+    BYTE IntOffset;
+    BYTE ConfigRegister;
+    BYTE CascadeRegister;
+    BOOLEAN CascadeRegisterSet;
+    BOOLEAN AutoEoi;
+    BOOLEAN Slave;
+    BOOLEAN ReadIsr;
+} PIC, *PPIC;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID PicInterruptRequest(BYTE Number);
+BYTE PicGetInterrupt(VOID);
+
+VOID PicInitialize(VOID);
+
+#endif // _PIC_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/ps2.c b/subsystems/ntvdm/hardware/ps2.c
new file mode 100644 (file)
index 0000000..c98d32e
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            ps2.c
+ * PURPOSE:         PS/2 controller emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "io.h"
+#include "ps2.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE];
+static BOOLEAN KeyboardQueueEmpty = TRUE;
+static UINT KeyboardQueueStart = 0;
+static UINT KeyboardQueueEnd = 0;
+static BYTE KeyboardData = 0, KeyboardResponse = 0;
+static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE;
+static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG;
+static HANDLE QueueMutex = NULL;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
+{
+    BOOLEAN Result = TRUE;
+
+    WaitForSingleObject(QueueMutex, INFINITE);
+
+    /* Check if the keyboard queue is full */
+    if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
+    {
+        Result = FALSE;
+        goto Done;
+    }
+
+    /* Insert the value in the queue */
+    KeyboardQueue[KeyboardQueueEnd] = ScanCode;
+    KeyboardQueueEnd++;
+    KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE;
+
+    /* Since we inserted a value, it's not empty anymore */
+    KeyboardQueueEmpty = FALSE;
+
+Done:
+    ReleaseMutex(QueueMutex);
+    return Result;
+}
+
+static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
+{
+    BOOLEAN Result = TRUE;
+
+    /* Make sure the keyboard queue is not empty (fast check) */
+    if (KeyboardQueueEmpty) return FALSE;
+
+    WaitForSingleObject(QueueMutex, INFINITE);
+
+    /*
+     * Recheck whether keyboard queue is not empty (it
+     * may have changed after having grabbed the mutex).
+     */
+    if (KeyboardQueueEmpty)
+    {
+        Result = FALSE;
+        goto Done;
+    }
+
+    /* Get the scan code */
+    *ScanCode = KeyboardQueue[KeyboardQueueStart];
+
+    /* Remove the value from the queue */
+    KeyboardQueueStart++;
+    KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE;
+
+    /* Check if the queue is now empty */
+    if (KeyboardQueueStart == KeyboardQueueEnd)
+    {
+        KeyboardQueueEmpty = TRUE;
+    }
+
+Done:
+    ReleaseMutex(QueueMutex);
+    return Result;
+}
+
+static BYTE WINAPI PS2ReadPort(ULONG Port)
+{
+    if (Port == PS2_CONTROL_PORT)
+    {
+        BYTE Status = 0;
+
+        /* Set the first bit if the data can be read */
+        if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0;
+
+        /* Always set bit 2 */
+        Status |= 1 << 2;
+
+        /* Set bit 3 if the next byte goes to the controller */
+        if (KeyboardWriteResponse) Status |= 1 << 3;
+
+        return Status;
+    }
+    else if (Port == PS2_DATA_PORT)
+    {
+        /* If there was a response byte from the controller, return it */
+        if (KeyboardReadResponse)
+        {
+            KeyboardReadResponse = FALSE;
+            KeyboardData = KeyboardResponse;
+        }
+
+        return KeyboardData;
+    }
+    else return 0;
+}
+
+static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
+{
+    if (Port == PS2_CONTROL_PORT)
+    {
+        switch (Data)
+        {
+            /* Read configuration byte */
+            case 0x20:
+            {
+                KeyboardResponse = KeyboardConfig;
+                KeyboardReadResponse = TRUE;
+                break;
+            }
+
+            /* Write configuration byte */
+            case 0x60:
+            /* Write controller output port */
+            case 0xD1:
+            /* Write keyboard output buffer */
+            case 0xD2:
+            /* Write mouse output buffer */
+            case 0xD3:
+            /* Write mouse input buffer */
+            case 0xD4:
+            {
+                /* These commands require a response */
+                KeyboardResponse = Data;
+                KeyboardWriteResponse = TRUE;
+                break;
+            }
+
+            /* Disable mouse */
+            case 0xA7:
+            {
+                // TODO: Mouse support
+                break;
+            }
+
+            /* Enable mouse */
+            case 0xA8:
+            {
+                // TODO: Mouse support
+                break;
+            }
+
+            /* Test mouse port */
+            case 0xA9:
+            {
+                KeyboardResponse = 0;
+                KeyboardReadResponse = TRUE;
+                break;
+            }
+
+            /* Test PS/2 controller */
+            case 0xAA:
+            {
+                KeyboardResponse = 0x55;
+                KeyboardReadResponse = TRUE;
+                break;
+            }
+
+            /* Disable keyboard */
+            case 0xAD:
+            {
+                // TODO: Not implemented
+                break;
+            }
+
+            /* Enable keyboard */
+            case 0xAE:
+            {
+                // TODO: Not implemented
+                break;
+            }
+
+            /* Read controller output port */
+            case 0xD0:
+            {
+                // TODO: Not implemented
+                break;
+            }
+
+            /* CPU Reset */
+            case 0xF0:
+            case 0xF2:
+            case 0xF4:
+            case 0xF6:
+            case 0xF8:
+            case 0xFA:
+            case 0xFC:
+            case 0xFE:
+            {
+                /* Stop the VDM */
+                EmulatorTerminate();
+                break;
+            }
+        }
+    }
+    else if (Port == PS2_DATA_PORT)
+    {
+        /* Check if the controller is waiting for a response */
+        if (KeyboardWriteResponse)
+        {
+            KeyboardWriteResponse = FALSE;
+
+            /* Check which command it was */
+            switch (KeyboardResponse)
+            {
+                /* Write configuration byte */
+                case 0x60:
+                {
+                    KeyboardConfig = Data;
+                    break;
+                }
+
+                /* Write controller output */
+                case 0xD1:
+                {
+                    /* Check if bit 0 is unset */
+                    if (!(Data & (1 << 0)))
+                    {
+                        /* CPU disabled - Stop the VDM */
+                        EmulatorTerminate();
+                    }
+
+                    /* Update the A20 line setting */
+                    EmulatorSetA20(Data & (1 << 1));
+
+                    break;
+                }
+            
+                case 0xD2:
+                {
+                    /* Push the data byte to the keyboard queue */
+                    KeyboardQueuePush(Data);
+                    break;
+                }
+
+                case 0xD3:
+                {
+                    // TODO: Mouse support
+                    break;
+                }
+
+                case 0xD4:
+                {
+                    // TODO: Mouse support
+                    break;
+                }
+            }
+
+            return;
+        }
+
+        // TODO: Implement PS/2 device commands
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID PS2Dispatch(PINPUT_RECORD InputRecord)
+{
+    /* Check the event type */
+    switch (InputRecord->EventType)
+    {
+        case KEY_EVENT:
+        {
+            WORD i;
+            BYTE ScanCode = (BYTE)InputRecord->Event.KeyEvent.wVirtualScanCode;
+
+            /* If this is a key release, set the highest bit in the scan code */
+            if (!InputRecord->Event.KeyEvent.bKeyDown) ScanCode |= 0x80;
+
+            /* Push the scan code onto the keyboard queue */
+            for (i = 0; i < InputRecord->Event.KeyEvent.wRepeatCount; i++)
+            {
+                KeyboardQueuePush(ScanCode);
+            }
+
+            break;
+        }
+
+        case MOUSE_EVENT:
+        {
+            // TODO: NOT IMPLEMENTED
+            UNIMPLEMENTED;
+            break;
+        }
+
+        /* We ignore all the rest */
+        default:
+            break;
+    }
+}
+
+VOID GenerateKeyboardInterrupts(VOID)
+{
+    /* Generate an IRQ 1 if there is a key ready in the queue */
+    if (KeyboardQueuePop(&KeyboardData)) PicInterruptRequest(1);
+}
+
+BOOLEAN PS2Initialize(HANDLE ConsoleInput)
+{
+#if 0
+    DWORD ConInMode;
+#endif
+
+    /* Create the mutex */
+    QueueMutex = CreateMutex(NULL, FALSE, NULL);
+
+    /* Register the I/O Ports */
+    RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort);
+    RegisterIoPort(PS2_DATA_PORT   , PS2ReadPort, PS2WritePort);
+
+#if 0
+    if (GetConsoleMode(ConsoleInput, &ConInMode))
+    {
+        if (MousePresent)
+        {
+            /* Support mouse input events if there is a mouse on the system */
+            ConInMode |= ENABLE_MOUSE_INPUT;
+        }
+        else
+        {
+            /* Do not support mouse input events if there is no mouse on the system */
+            ConInMode &= ~ENABLE_MOUSE_INPUT;
+        }
+
+        SetConsoleMode(ConsoleInput, ConInMode);
+    }
+#endif
+
+    return TRUE;
+}
+
+VOID PS2Cleanup(VOID)
+{
+    CloseHandle(QueueMutex);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/ps2.h b/subsystems/ntvdm/hardware/ps2.h
new file mode 100644 (file)
index 0000000..119e9bd
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            ps2.h
+ * PURPOSE:         PS/2 controller emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _PS2_H_
+#define _PS2_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define KEYBOARD_BUFFER_SIZE 32
+#define PS2_DATA_PORT 0x60
+#define PS2_CONTROL_PORT 0x64
+#define PS2_DEFAULT_CONFIG 0x05
+#define KEYBOARD_ACK 0xFA
+#define KEYBOARD_RESEND 0xFE
+
+/* FUNCTIONS ******************************************************************/
+
+VOID PS2Dispatch(PINPUT_RECORD InputRecord);
+VOID GenerateKeyboardInterrupts(VOID);
+
+BOOLEAN PS2Initialize(HANDLE ConsoleInput);
+VOID PS2Cleanup(VOID);
+
+#endif // _PS2_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/speaker.c b/subsystems/ntvdm/hardware/speaker.c
new file mode 100644 (file)
index 0000000..03bf25c
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            speaker.c
+ * PURPOSE:         PC Speaker emulation
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "speaker.h"
+#include "io.h"
+#include "timer.h"
+
+/* Extra PSDK/NDK Headers */
+#include <ndk/iofuncs.h>
+#include <ndk/obfuncs.h>
+#include <ndk/rtlfuncs.h>
+
+/* DDK Driver Headers */
+#include <ntddbeep.h>
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static HANDLE hBeep = NULL;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID SpeakerChange(VOID)
+{
+    BYTE    Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H);
+    BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01);
+    BOOLEAN SpeakerDataOn = !!(Port61hState & 0x02);
+
+    if (PitChannel2 && IsConnectedToPITChannel2 && SpeakerDataOn)
+    {
+        /* Start beeping - Adapted from kernel32:Beep() */
+        NTSTATUS Status;
+        IO_STATUS_BLOCK IoStatusBlock;
+        BEEP_SET_PARAMETERS BeepSetParameters;
+
+        DWORD PitChannel2ReloadValue = PitChannel2->ReloadValue;
+        if (PitChannel2ReloadValue == 0) PitChannel2ReloadValue = 65536;
+
+        /* Set beep data */
+        BeepSetParameters.Frequency = (PIT_BASE_FREQUENCY / PitChannel2ReloadValue) *
+                                      (PitChannel2->Mode == PIT_MODE_SQUARE_WAVE ? 2 : 1);
+        BeepSetParameters.Duration  = INFINITE;
+
+        /* Send the beep */
+        Status = NtDeviceIoControlFile(hBeep,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &IoStatusBlock,
+                                       IOCTL_BEEP_SET,
+                                       &BeepSetParameters,
+                                       sizeof(BeepSetParameters),
+                                       NULL,
+                                       0);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n",
+                    BeepSetParameters.Frequency,
+                    BeepSetParameters.Duration,
+                    Status);
+        }
+    }
+    else
+    {
+        /* Stop beeping */
+        NTSTATUS Status;
+        IO_STATUS_BLOCK IoStatusBlock;
+        BEEP_SET_PARAMETERS BeepSetParameters;
+
+        /* Set beep data */
+        BeepSetParameters.Frequency = 0x00;
+        BeepSetParameters.Duration  = 0x00;
+
+        /* Send the beep */
+        Status = NtDeviceIoControlFile(hBeep,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &IoStatusBlock,
+                                       IOCTL_BEEP_SET,
+                                       &BeepSetParameters,
+                                       sizeof(BeepSetParameters),
+                                       NULL,
+                                       0);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n",
+                    BeepSetParameters.Frequency,
+                    BeepSetParameters.Duration,
+                    Status);
+        }
+    }
+}
+
+VOID SpeakerInitialize(VOID)
+{
+    NTSTATUS Status;
+    UNICODE_STRING BeepDevice;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+
+    /* Adapted from kernel32:Beep() */
+
+    //
+    // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen
+    // after doing a GetProcAddress for it
+    //
+
+    /* Open the device */
+    RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep");
+    InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL);
+    Status = NtCreateFile(&hBeep,
+                          FILE_READ_DATA | FILE_WRITE_DATA,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          0,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE,
+                          FILE_OPEN_IF,
+                          0,
+                          NULL,
+                          0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status);
+    }
+}
+
+VOID SpeakerCleanup(VOID)
+{
+    NtClose(hBeep);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/speaker.h b/subsystems/ntvdm/hardware/speaker.h
new file mode 100644 (file)
index 0000000..94c9fc0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            speaker.h
+ * PURPOSE:         PC Speaker emulation
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _SPEAKER_H_
+#define _SPEAKER_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+VOID SpeakerChange(VOID);
+
+VOID SpeakerInitialize(VOID);
+VOID SpeakerCleanup(VOID);
+
+#endif // _SPEAKER_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/timer.c b/subsystems/ntvdm/hardware/timer.c
new file mode 100644 (file)
index 0000000..87f6863
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            timer.c
+ * PURPOSE:         Programmable Interval Timer emulation -
+ *                  i82C54/8254 compatible
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "io.h"
+#include "timer.h"
+#include "pic.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static PIT_CHANNEL PitChannels[PIT_CHANNELS];
+PPIT_CHANNEL PitChannel2 = &PitChannels[2];
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static VOID PitLatchChannelStatus(BYTE Channel)
+{
+    if (Channel >= PIT_CHANNELS) return;
+
+    /*
+     * A given counter can be latched only one time until it gets unlatched.
+     * If the counter is latched and then is latched again later before the
+     * value is read, then this last latch command is ignored and the value
+     * will be the value at the time the first command was issued.
+     */
+    if (PitChannels[Channel].LatchStatusSet == FALSE)
+    {
+        BYTE StatusLatch = 0;
+        /** HACK!! **/BYTE NullCount = 0;/** HACK!! **/
+
+        StatusLatch  =  PitChannels[Channel].Out << 7 | NullCount  << 6;
+        StatusLatch |= (PitChannels[Channel].ReadWriteMode & 0x03) << 4;
+        StatusLatch |= (PitChannels[Channel].Mode & 0x07) << 1;
+        StatusLatch |= (PitChannels[Channel].Bcd  & 0x01);
+
+        /* Latch the counter's status */
+        PitChannels[Channel].LatchStatusSet = TRUE;
+        PitChannels[Channel].StatusLatch    = StatusLatch;
+    }
+}
+
+static VOID PitLatchChannelCount(BYTE Channel)
+{
+    if (Channel >= PIT_CHANNELS) return;
+
+    /*
+     * A given counter can be latched only one time until it gets unlatched.
+     * If the counter is latched and then is latched again later before the
+     * value is read, then this last latch command is ignored and the value
+     * will be the value at the time the first command was issued.
+     */
+    if (PitChannels[Channel].ReadStatus == 0x00)
+    {
+        /* Latch the counter's value */
+        PitChannels[Channel].ReadStatus  = PitChannels[Channel].ReadWriteMode;
+
+        /* Convert the current value to BCD if needed */
+        PitChannels[Channel].OutputLatch =
+            READ_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CurrentValue);
+    }
+}
+
+static VOID PitSetOut(PPIT_CHANNEL Channel, BOOLEAN State)
+{
+    /** HACK!! **\ if (State == Channel->Out) return; \** HACK!! **/
+
+    /* Set the new state of the OUT pin */
+    Channel->Out = State;
+
+    /* Call the callback */
+    if (Channel->OutFunction) Channel->OutFunction(Channel->OutParam, State);
+}
+
+static VOID PitInitCounter(PPIT_CHANNEL Channel)
+{
+    switch (Channel->Mode)
+    {
+        case PIT_MODE_INT_ON_TERMINAL_COUNT:
+            PitSetOut(Channel, FALSE);
+            break;
+
+        case PIT_MODE_HARDWARE_ONE_SHOT:
+        case PIT_MODE_RATE_GENERATOR:
+        case PIT_MODE_SQUARE_WAVE:
+        case PIT_MODE_SOFTWARE_STROBE:
+        case PIT_MODE_HARDWARE_STROBE:
+            PitSetOut(Channel, TRUE);
+            break;
+    }
+}
+
+static VOID PitWriteCommand(BYTE Value)
+{
+    BYTE Channel       = (Value >> 6) & 0x03;
+    BYTE ReadWriteMode = (Value >> 4) & 0x03;
+    BYTE Mode     = (Value >> 1) & 0x07;
+    BOOLEAN IsBcd = Value & 0x01;
+
+    /*
+     * Check for valid PIT channel - Possible values: 0, 1, 2.
+     * A value of 3 is for Read-Back Command.
+     */
+    if (Channel > PIT_CHANNELS) return;
+
+    /* Read-Back Command */
+    if (Channel == PIT_CHANNELS)
+    {
+        if ((Value & 0x20) == 0) // Bit 5 (Count) == 0: We latch multiple counters' counts
+        {
+            if (Value & 0x02) PitLatchChannelCount(0);
+            if (Value & 0x04) PitLatchChannelCount(1);
+            if (Value & 0x08) PitLatchChannelCount(2);
+        }
+        if ((Value & 0x10) == 0) // Bit 4 (Status) == 0: We latch multiple counters' statuses
+        {
+            if (Value & 0x02) PitLatchChannelStatus(0);
+            if (Value & 0x04) PitLatchChannelStatus(1);
+            if (Value & 0x08) PitLatchChannelStatus(2);
+        }
+        return;
+    }
+
+    /* Check if this is a counter latch command... */
+    if (ReadWriteMode == 0)
+    {
+        PitLatchChannelCount(Channel);
+        return;
+    }
+
+    /* ... otherwise, set the modes and reset flip-flops */
+    PitChannels[Channel].ReadWriteMode = ReadWriteMode;
+    PitChannels[Channel].ReadStatus    = 0x00;
+    PitChannels[Channel].WriteStatus   = 0x00;
+
+    PitChannels[Channel].LatchStatusSet = FALSE;
+    PitChannels[Channel].StatusLatch    = 0x00;
+
+    PitChannels[Channel].CountRegister = 0x00;
+    PitChannels[Channel].OutputLatch   = 0x00;
+
+    /** HACK!! **/PitChannels[Channel].FlipFlop = FALSE;/** HACK!! **/
+
+    /* Fix the current value if we switch to BCD counting */
+    PitChannels[Channel].Bcd = IsBcd;
+    if (IsBcd && PitChannels[Channel].CurrentValue > 9999)
+        PitChannels[Channel].CurrentValue = 9999;
+
+    switch (Mode)
+    {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+        {
+            PitChannels[Channel].Mode = Mode;
+            break;
+        }
+
+        case 6:
+        case 7:
+        {
+            /*
+             * Modes 6 and 7 become PIT_MODE_RATE_GENERATOR
+             * and PIT_MODE_SQUARE_WAVE respectively.
+             */
+            PitChannels[Channel].Mode = Mode - 4;
+            break;
+        }
+    }
+
+    PitInitCounter(&PitChannels[Channel]);
+}
+
+static BYTE PitReadData(BYTE Channel)
+{
+    LPBYTE ReadWriteMode = NULL;
+    LPWORD CurrentValue  = NULL;
+
+    /*
+     * If the status was latched, the first read operation will return the
+     * latched status, whichever value (count or status) was latched first.
+     */
+    if (PitChannels[Channel].LatchStatusSet)
+    {
+        PitChannels[Channel].LatchStatusSet = FALSE;
+        return PitChannels[Channel].StatusLatch;
+    }
+
+    /* To be able to read the count asynchronously, latch it first if needed */
+    if (PitChannels[Channel].ReadStatus == 0) PitLatchChannelCount(Channel);
+
+    /* The count is now latched */
+    ASSERT(PitChannels[Channel].ReadStatus != 0);
+
+    ReadWriteMode = &PitChannels[Channel].ReadStatus ;
+    CurrentValue  = &PitChannels[Channel].OutputLatch;
+
+    if (*ReadWriteMode & 1)
+    {
+        /* Read LSB */
+        *ReadWriteMode &= ~1;
+        return LOBYTE(*CurrentValue);
+    }
+
+    if (*ReadWriteMode & 2)
+    {
+        /* Read MSB */
+        *ReadWriteMode &= ~2;
+        return HIBYTE(*CurrentValue);
+    }
+
+    /* Shouldn't get here */
+    ASSERT(FALSE);
+    return 0;
+}
+
+static VOID PitWriteData(BYTE Channel, BYTE Value)
+{
+    LPBYTE ReadWriteMode = NULL;
+
+    if (PitChannels[Channel].WriteStatus == 0x00)
+    {
+        PitChannels[Channel].WriteStatus = PitChannels[Channel].ReadWriteMode;
+    }
+
+    ASSERT(PitChannels[Channel].WriteStatus != 0);
+
+    ReadWriteMode = &PitChannels[Channel].WriteStatus;
+
+    if (*ReadWriteMode & 1)
+    {
+        /* Write LSB */
+        *ReadWriteMode &= ~1;
+        PitChannels[Channel].CountRegister &= 0xFF00;
+        PitChannels[Channel].CountRegister |= Value;
+    }
+    else if (*ReadWriteMode & 2)
+    {
+        /* Write MSB */
+        *ReadWriteMode &= ~2;
+        PitChannels[Channel].CountRegister &= 0x00FF;
+        PitChannels[Channel].CountRegister |= Value << 8;
+    }
+
+    /* ReadWriteMode went to zero: we are going to load the new count */
+    if (*ReadWriteMode == 0x00)
+    {
+        if (PitChannels[Channel].CountRegister == 0x0000)
+        {
+            /* Wrap around to the highest count */
+            if (PitChannels[Channel].Bcd)
+                PitChannels[Channel].CountRegister = 9999;
+            else
+                PitChannels[Channel].CountRegister = 0xFFFF; // 0x10000; // 65536
+        }
+
+        /* Convert the current value from BCD if needed */
+        PitChannels[Channel].CountRegister =
+            WRITE_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CountRegister);
+        PitChannels[Channel].ReloadValue = PitChannels[Channel].CountRegister;
+    }
+}
+
+static BYTE WINAPI PitReadPort(ULONG Port)
+{
+    switch (Port)
+    {
+        case PIT_DATA_PORT(0):
+        case PIT_DATA_PORT(1):
+        case PIT_DATA_PORT(2):
+        {
+            return PitReadData(Port - PIT_DATA_PORT(0));
+        }
+    }
+
+    return 0;
+}
+
+static VOID WINAPI PitWritePort(ULONG Port, BYTE Data)
+{
+    switch (Port)
+    {
+        case PIT_COMMAND_PORT:
+        {
+            PitWriteCommand(Data);
+            break;
+        }
+
+        case PIT_DATA_PORT(0):
+        case PIT_DATA_PORT(1):
+        case PIT_DATA_PORT(2):
+        {
+            PitWriteData(Port - PIT_DATA_PORT(0), Data);
+            break;
+        }
+    }
+}
+
+static VOID PitDecrementCount(PPIT_CHANNEL Channel, DWORD Count)
+{
+    if (Count == 0) return;
+
+    switch (Channel->Mode)
+    {
+        case PIT_MODE_INT_ON_TERMINAL_COUNT:
+        {
+            /* Decrement the value */
+            if (Count > Channel->CurrentValue)
+            {
+                /* The value does not reload in this case */
+                Channel->CurrentValue = 0;
+            }
+            else Channel->CurrentValue -= Count;
+
+            /* Did it fall to the terminal count? */
+            if (Channel->CurrentValue == 0 && !Channel->Out)
+            {
+                /* Yes, raise the output line */
+                PitSetOut(Channel, TRUE);
+            }
+            break;
+        }
+
+        case PIT_MODE_RATE_GENERATOR:
+        {
+            BOOLEAN Reloaded = FALSE;
+
+            while (Count)
+            {
+                if ((Count > Channel->CurrentValue)
+                    && (Channel->CurrentValue != 0))
+                {
+                    /* Decrement the count */
+                    Count -= Channel->CurrentValue;
+
+                    /* Reload the value */
+                    Channel->CurrentValue = Channel->ReloadValue;
+
+                    /* Set the flag */
+                    Reloaded = TRUE;
+                }
+                else
+                {
+                    /* Decrement the value */
+                    Channel->CurrentValue -= Count;
+
+                    /* Clear the count */
+                    Count = 0;
+
+                    /* Did it fall to zero? */
+                    if (Channel->CurrentValue == 0)
+                    {
+                        Channel->CurrentValue = Channel->ReloadValue;
+                        Reloaded = TRUE;
+                    }
+                }
+            }
+
+            /* If there was a reload, raise the output line */
+            if (Reloaded) PitSetOut(Channel, TRUE);
+
+            break;
+        }
+
+        case PIT_MODE_SQUARE_WAVE:
+        {
+            INT ReloadCount = 0;
+            WORD ReloadValue = Channel->ReloadValue;
+
+            /* The reload value must be even */
+            ReloadValue &= ~1;
+
+            while (Count)
+            {
+                if (((Count * 2) > Channel->CurrentValue)
+                    && (Channel->CurrentValue != 0))
+                {
+                    /* Decrement the count */
+                    Count -= Channel->CurrentValue / 2;
+
+                    /* Reload the value */
+                    Channel->CurrentValue = ReloadValue;
+
+                    /* Increment the reload count */
+                    ReloadCount++;
+                }
+                else
+                {
+                    /* Decrement the value */
+                    Channel->CurrentValue -= Count * 2;
+
+                    /* Clear the count */
+                    Count = 0;
+
+                    /* Did it fall to zero? */
+                    if (Channel->CurrentValue == 0)
+                    {
+                        /* Reload the value */
+                        Channel->CurrentValue = ReloadValue;
+
+                        /* Increment the reload count */
+                        ReloadCount++;
+                    }
+                }
+            }
+
+            if (ReloadCount == 0) break;
+
+            /* Toggle the flip-flop if the number of reloads was odd */
+            if (ReloadCount & 1)
+            {
+                Channel->FlipFlop = !Channel->FlipFlop;
+                // PitSetOut(Channel, !Channel->Out);
+            }
+
+            /* Was there any rising edge? */
+            if ((Channel->FlipFlop && (ReloadCount == 1)) || (ReloadCount > 1))
+            {
+                /* Yes, raise the output line */
+                PitSetOut(Channel, TRUE);
+            }
+
+            break;
+        }
+
+        case PIT_MODE_SOFTWARE_STROBE:
+        {
+            // TODO: NOT IMPLEMENTED
+            break;
+        }
+
+        case PIT_MODE_HARDWARE_ONE_SHOT:
+        case PIT_MODE_HARDWARE_STROBE:
+        {
+            /* These modes do not work on x86 PCs */
+            break;
+        }
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction)
+{
+    if (Channel >= PIT_CHANNELS) return;
+
+    PitChannels[Channel].OutParam    = Param;
+    PitChannels[Channel].OutFunction = OutFunction;
+}
+
+VOID PitSetGate(BYTE Channel, BOOLEAN State)
+{
+    if (Channel >= PIT_CHANNELS) return;
+    if (State == PitChannels[Channel].Gate) return;
+
+    /* UNIMPLEMENTED */
+    PitChannels[Channel].Gate = State;
+}
+
+VOID PitClock(DWORD Count)
+{
+    UINT i;
+
+    if (Count == 0) return;
+
+    for (i = 0; i < PIT_CHANNELS; i++)
+    {
+        // if (!PitChannels[i].Counting) continue;
+        PitDecrementCount(&PitChannels[i], Count);
+    }
+}
+
+DWORD PitGetResolution(VOID)
+{
+    INT i;
+    DWORD MinReloadValue = 65536;
+
+    for (i = 0; i < PIT_CHANNELS; i++)
+    {
+        DWORD ReloadValue = PitChannels[i].ReloadValue;
+
+        /* 0 means 65536 */
+        if (ReloadValue == 0) ReloadValue = 65536;
+
+        if (ReloadValue < MinReloadValue) MinReloadValue = ReloadValue;
+    }
+
+    /* Return the frequency resolution */
+    return PIT_BASE_FREQUENCY / MinReloadValue;
+}
+
+VOID PitInitialize(VOID)
+{
+    /* Set up the timers to their default value */
+    PitSetOutFunction(0, NULL, NULL);
+    PitSetGate(0, TRUE);
+    PitSetOutFunction(1, NULL, NULL);
+    PitSetGate(1, TRUE);
+    PitSetOutFunction(2, NULL, NULL);
+    PitSetGate(2, FALSE);
+
+    /* Register the I/O Ports */
+    RegisterIoPort(PIT_COMMAND_PORT, NULL       , PitWritePort);
+    RegisterIoPort(PIT_DATA_PORT(0), PitReadPort, PitWritePort);
+    RegisterIoPort(PIT_DATA_PORT(1), PitReadPort, PitWritePort);
+    RegisterIoPort(PIT_DATA_PORT(2), PitReadPort, PitWritePort);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/timer.h b/subsystems/ntvdm/hardware/timer.h
new file mode 100644 (file)
index 0000000..21f7f8e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            timer.h
+ * PURPOSE:         Programmable Interval Timer emulation -
+ *                  i82C54/8254 compatible
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define PIT_CHANNELS 3
+#define PIT_BASE_FREQUENCY 1193182LL
+#define PIT_DATA_PORT(x) (0x40 + (x))
+#define PIT_COMMAND_PORT 0x43
+
+#define WRITE_PIT_VALUE(PitChannel, Value)    \
+    (PitChannel).Bcd ? BCD_TO_BINARY(Value) : (Value)
+
+#define READ_PIT_VALUE(PitChannel, Value)     \
+    (PitChannel).Bcd ? BINARY_TO_BCD(Value) : (Value)
+
+typedef enum _PIT_MODE
+{
+    PIT_MODE_INT_ON_TERMINAL_COUNT,
+    PIT_MODE_HARDWARE_ONE_SHOT,
+    PIT_MODE_RATE_GENERATOR,
+    PIT_MODE_SQUARE_WAVE,
+    PIT_MODE_SOFTWARE_STROBE,
+    PIT_MODE_HARDWARE_STROBE
+} PIT_MODE, *PPIT_MODE;
+
+typedef VOID (WINAPI *PIT_OUT_FUNCTION)(LPVOID Param, BOOLEAN State);
+
+typedef struct _PIT_CHANNEL
+{
+    /* PIT Status fields */
+    PIT_MODE Mode;
+    BOOLEAN  Bcd;
+    BYTE     ReadWriteMode; // 0 --> Counter Latch ; 1 --> LSB R/W ; 2 --> MSB R/W ; 3 --> LSB then MSB R/W
+
+    /* For interleaved reading and writing in 2-byte RW mode */
+    BYTE    ReadStatus;     // Same convention as ReadWriteMode
+    BYTE    WriteStatus;    // Same convention as ReadWriteMode
+
+    /* For reading the PIT status byte */
+    BOOLEAN LatchStatusSet;
+    BYTE    StatusLatch;
+
+    /* Counting */
+    BOOLEAN Gate;
+
+    /**/WORD    CountRegister;/**/  // Our ReloadValue ???
+    WORD OutputLatch;
+    /*******************************/
+
+    WORD    ReloadValue;    // Max value of the counter
+    WORD    CurrentValue;   // Real value of the counter
+
+    /* PIT Output */
+    BOOLEAN Out;    // 0: Low ; 1: High
+    /** HACK!! **/BOOLEAN FlipFlop;/** HACK!! **/
+    LPVOID           OutParam;
+    PIT_OUT_FUNCTION OutFunction;
+
+} PIT_CHANNEL, *PPIT_CHANNEL;
+
+extern PPIT_CHANNEL PitChannel2;    // Needed for PC Speaker
+
+/* FUNCTIONS ******************************************************************/
+
+VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction);
+VOID PitSetGate(BYTE Channel, BOOLEAN State);
+
+VOID PitClock(DWORD Count);
+DWORD PitGetResolution(VOID);
+
+VOID PitInitialize(VOID);
+
+#endif // _TIMER_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/vga.c b/subsystems/ntvdm/hardware/vga.c
new file mode 100644 (file)
index 0000000..590ff05
--- /dev/null
@@ -0,0 +1,1970 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vga.c
+ * PURPOSE:         VGA hardware emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "vga.h"
+#include "../bios/vidbios.h"
+
+#include "io.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static CONST DWORD MemoryBase[]  = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
+static CONST DWORD MemoryLimit[] = { 0xAFFFF, 0xAFFFF, 0xB7FFF, 0xBFFFF };
+
+#define USE_REACTOS_COLORS
+// #define USE_DOSBOX_COLORS
+
+#if defined(USE_REACTOS_COLORS)
+
+// ReactOS colors
+static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
+    RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
+    RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
+    RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
+    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
+    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
+    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
+    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
+    RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
+    RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
+    RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
+    RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
+    RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
+    RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
+    RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
+    RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
+    RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
+    RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
+    RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
+    RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
+    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
+    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
+    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
+    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
+    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
+    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
+    RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
+    RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
+    RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
+    RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
+    RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
+    RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
+    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
+    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
+    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
+    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
+    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
+    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
+    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
+    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
+    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
+    RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
+    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
+    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
+    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
+    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
+    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
+    RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
+    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
+    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
+    RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
+    RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
+    RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
+    RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
+    RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
+    RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
+};
+
+#elif defined(USE_DOSBOX_COLORS)
+
+// DOSBox colors
+static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] =
+{
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
+    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
+    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
+    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
+    RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
+    RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
+    RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
+    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
+    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
+    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
+    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
+    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
+    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
+    RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
+    RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
+
+    RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
+    RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
+    RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
+    RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
+    RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
+    RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
+    RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
+    RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
+    RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
+    RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
+    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
+    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
+    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
+    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
+    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
+    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
+
+    RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
+    RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
+    RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
+    RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
+    RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
+    RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
+    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
+    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
+    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
+    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
+    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
+    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
+    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
+    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
+    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
+    RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
+
+    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
+    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
+    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
+    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
+    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
+    RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
+    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
+    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
+    RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
+    RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
+    RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
+    RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
+    RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
+    RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
+    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
+};
+
+#endif
+
+/*
+ * Console interface -- VGA-mode-agnostic
+ */
+typedef struct _CHAR_CELL
+{
+    CHAR Char;
+    BYTE Attributes;
+} CHAR_CELL, *PCHAR_CELL;
+C_ASSERT(sizeof(CHAR_CELL) == 2);
+
+static LPVOID ConsoleFramebuffer = NULL; // Active framebuffer, points to
+                                         // either TextFramebuffer or a valid
+                                         // graphics framebuffer.
+static HPALETTE PaletteHandle = NULL;
+
+static HANDLE StartEvent = NULL;
+static HANDLE EndEvent   = NULL;
+static HANDLE AnotherEvent = NULL;
+
+static CONSOLE_CURSOR_INFO         OrgConsoleCursorInfo;
+static CONSOLE_SCREEN_BUFFER_INFO  OrgConsoleBufferInfo;
+
+
+/*
+ * Text mode -- we always keep a valid text mode framebuffer
+ * even if we are in graphics mode. This is needed in order to
+ * keep a consistent VGA state.
+ */
+static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+static COORD  TextResolution = {0};
+static PCHAR_CELL TextFramebuffer = NULL;
+static HANDLE TextConsoleBuffer = NULL;
+
+/* Graphics mode */
+static HANDLE GraphicsConsoleBuffer = NULL;
+static HANDLE ConsoleMutex = NULL;
+static BOOLEAN DoubleVision = FALSE;
+
+/*
+ * VGA Hardware
+ */
+static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE];
+
+static BYTE VgaLatchRegisters[VGA_NUM_BANKS] = {0, 0, 0, 0};
+
+static BYTE VgaMiscRegister;
+static BYTE VgaFeatureRegister;
+
+static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG;
+static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG];
+
+static BYTE VgaCrtcIndex = VGA_CRTC_HORZ_TOTAL_REG;
+static BYTE VgaCrtcRegisters[VGA_CRTC_MAX_REG];
+
+static BYTE VgaGcIndex = VGA_GC_RESET_REG;
+static BYTE VgaGcRegisters[VGA_GC_MAX_REG];
+
+static BOOLEAN VgaAcLatch = FALSE;
+static BOOLEAN VgaAcPalDisable = TRUE;
+static BYTE VgaAcIndex = VGA_AC_PAL_0_REG;
+static BYTE VgaAcRegisters[VGA_AC_MAX_REG];
+
+// static VGA_REGISTERS VgaRegisters;
+
+static BYTE VgaDacMask = 0xFF;
+static WORD VgaDacIndex = 0;
+static BOOLEAN VgaDacReadWrite = FALSE;
+static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
+
+static BOOLEAN InVerticalRetrace = FALSE;
+static BOOLEAN InHorizontalRetrace = FALSE;
+
+static BOOLEAN NeedsUpdate = FALSE;
+static BOOLEAN ModeChanged = FALSE;
+static BOOLEAN CursorMoved = FALSE;
+static BOOLEAN PaletteChanged = FALSE;
+
+static
+enum SCREEN_MODE
+{
+    TEXT_MODE,
+    GRAPHICS_MODE
+} ScreenMode = TEXT_MODE;
+
+static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
+
+/* RegisterConsoleVDM EMULATION ***********************************************/
+
+#include <ntddvdeo.h>
+
+typedef
+BOOL
+(WINAPI *pRegisterConsoleVDM)
+(
+    BOOL IsDosVDM_flag,
+    HANDLE EventHandle_1,
+    HANDLE EventHandle_2,
+    HANDLE EventHandle_3,
+    int Unused1,
+    PVOID returned_val_1,
+    PVOID *returned_val_2,
+    PVOID lpUnknownBuffer,
+    DWORD theUnknownBufferLength,
+    COORD theVDMBufferSize,
+    PCHAR *lpVDMBuffer
+);
+
+#if 0
+BOOL
+WINAPI
+RegisterConsoleVDM
+(
+    BOOL IsDosVDM_flag,
+    HANDLE EventHandle_1,
+    HANDLE EventHandle_2,
+    HANDLE EventHandle_3,
+    int Unused1,
+    PVOID returned_val_1,
+    PVOID *returned_val_2,
+    PVOID lpUnknownBuffer,
+    DWORD theUnknownBufferLength,
+    COORD theVDMBufferSize,
+    PVOID *lpVDMBuffer
+);
+
+HMODULE hKernel32 = NULL;
+pRegisterConsoleVDM RegisterConsoleVDM = NULL;
+#endif
+
+/*
+ * This private buffer, per-console, is used by
+ * RegisterConsoleVDM and InvalidateConsoleDIBits.
+ */
+static COORD VDMBufferSize  = {0};
+static PCHAR_CELL VDMBuffer = NULL;
+
+static PCHAR_INFO CharBuff  = NULL; // This is a hack, which is unneeded
+                                    // for the real RegisterConsoleVDM and
+                                    // InvalidateConsoleDIBits
+
+BOOL
+WINAPI
+__RegisterConsoleVDM(BOOL IsDosVDM_flag,
+                     HANDLE EventHandle_1,
+                     HANDLE EventHandle_2,
+                     HANDLE EventHandle_3,
+                     int Unused1,
+                     PVOID returned_val_1,
+                     PVOID *returned_val_2,
+                     PVOID lpUnknownBuffer,
+                     DWORD theUnknownBufferLength,
+                     COORD theVDMBufferSize,
+                     PCHAR *lpVDMBuffer)
+{
+    UNREFERENCED_PARAMETER(EventHandle_3);
+    UNREFERENCED_PARAMETER(Unused1);
+    UNREFERENCED_PARAMETER(returned_val_1);
+    UNREFERENCED_PARAMETER(returned_val_2);
+    UNREFERENCED_PARAMETER(lpUnknownBuffer);
+    UNREFERENCED_PARAMETER(theUnknownBufferLength);
+
+    SetLastError(0);
+    DPRINT1("__RegisterConsoleVDM(%d)\n", IsDosVDM_flag);
+
+    if (lpVDMBuffer == NULL) return FALSE;
+
+    if (IsDosVDM_flag)
+    {
+        // if (EventHandle_1 == NULL || EventHandle_2 == NULL) return FALSE;
+        if (VDMBuffer != NULL) return FALSE;
+
+        VDMBufferSize = theVDMBufferSize;
+
+        /* HACK: Cache -- to be removed in the real implementation */
+        CharBuff = HeapAlloc(GetProcessHeap(),
+                             HEAP_ZERO_MEMORY,
+                             theVDMBufferSize.X * theVDMBufferSize.Y
+                                                * sizeof(CHAR_INFO));
+        ASSERT(CharBuff);
+
+        VDMBuffer = HeapAlloc(GetProcessHeap(),
+                              HEAP_ZERO_MEMORY,
+                              theVDMBufferSize.X * theVDMBufferSize.Y
+                                                 * sizeof(CHAR_CELL));
+        *lpVDMBuffer = (PCHAR)VDMBuffer;
+        return (VDMBuffer != NULL);
+    }
+    else
+    {
+        /* HACK: Cache -- to be removed in the real implementation */
+        if (CharBuff) HeapFree(GetProcessHeap(), 0, CharBuff);
+        CharBuff = NULL;
+
+        if (VDMBuffer) HeapFree(GetProcessHeap(), 0, VDMBuffer);
+        VDMBuffer = NULL;
+
+        VDMBufferSize.X = VDMBufferSize.Y = 0;
+
+        return TRUE;
+    }
+}
+
+BOOL
+__InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,
+                          IN PSMALL_RECT lpRect)
+{
+    if ((hConsoleOutput == TextConsoleBuffer) && (VDMBuffer != NULL))
+    {
+        /* HACK: Write the cached data to the console */
+
+        COORD Origin = { lpRect->Left, lpRect->Top };
+        SHORT i, j;
+
+        ASSERT(CharBuff);
+
+        for (i = 0; i < VDMBufferSize.Y; i++)
+        {
+            for (j = 0; j < VDMBufferSize.X; j++)
+            {
+                CharBuff[i * VDMBufferSize.X + j].Char.AsciiChar = VDMBuffer[i * VDMBufferSize.X + j].Char;
+                CharBuff[i * VDMBufferSize.X + j].Attributes     = VDMBuffer[i * VDMBufferSize.X + j].Attributes;
+            }
+        }
+
+        WriteConsoleOutputA(hConsoleOutput,
+                            CharBuff,
+                            VDMBufferSize,
+                            Origin,
+                            lpRect);
+    }
+
+    return InvalidateConsoleDIBits(hConsoleOutput, lpRect);
+}
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static inline DWORD VgaGetAddressSize(VOID);
+static VOID VgaUpdateTextCursor(VOID);
+
+static VOID VgaUpdateCursorPosition(VOID)
+{
+    /*
+     * Update the cursor position in the VGA registers.
+     */
+    WORD Offset = ConsoleInfo.dwCursorPosition.Y * TextResolution.X +
+                  ConsoleInfo.dwCursorPosition.X;
+
+    VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG]  = LOBYTE(Offset);
+    VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset);
+
+    // VidBiosSyncCursorPosition();
+    VgaUpdateTextCursor();
+}
+
+static BOOL VgaAttachToConsoleInternal(PCOORD Resolution)
+{
+    BOOL Success;
+    ULONG Length = 0;
+    PVIDEO_HARDWARE_STATE_HEADER State;
+
+    SHORT i, j;
+    DWORD AddressSize, ScanlineSize;
+    DWORD Address = 0;
+    DWORD CurrentAddr;
+    SMALL_RECT ConRect;
+    COORD Origin = { 0, 0 };
+
+    ASSERT(TextFramebuffer == NULL);
+
+    TextResolution = *Resolution;
+
+    /*
+     * Windows 2k3 winsrv.dll calls NtVdmControl(VdmQueryVdmProcess == 14, &ConsoleHandle);
+     * in the two following APIs:
+     * SrvRegisterConsoleVDM  (corresponding win32 API: RegisterConsoleVDM)
+     * SrvVDMConsoleOperation (corresponding Win32 API: )
+     * to check whether the current process is a VDM process, and fails otherwise with the
+     * error 0xC0000022 ().
+     *
+     * It is worth it to notice that also basesrv.dll does the same only for the
+     * BaseSrvIsFirstVDM API...
+     */
+
+    Success =
+    __RegisterConsoleVDM(1,
+                         StartEvent,
+                         EndEvent,
+                         AnotherEvent, // NULL,
+                         0,
+                         &Length, // NULL, <-- putting this (and null in the next var) makes the API returning error 12 "ERROR_INVALID_ACCESS"
+                         (PVOID*)&State, // NULL,
+                         NULL,
+                         0,
+                         TextResolution,
+                         (PCHAR*)&TextFramebuffer);
+    if (!Success)
+    {
+        DisplayMessage(L"RegisterConsoleVDM failed with error %d\n", GetLastError());
+        EmulatorTerminate();
+        return FALSE;
+    }
+
+    /*
+     * Resize the console
+     */
+    ConRect.Left   = 0;
+    ConRect.Top    = ConsoleInfo.srWindow.Top;
+    ConRect.Right  = ConRect.Left + Resolution->X - 1;
+    ConRect.Bottom = ConRect.Top  + Resolution->Y - 1;
+    /*
+     * Use this trick to effectively resize the console buffer and window,
+     * because:
+     * - SetConsoleScreenBufferSize fails if the new console screen buffer size
+     *   is smaller than the current console window size, and:
+     * - SetConsoleWindowInfo fails if the new console window size is larger
+     *   than the current console screen buffer size.
+     */
+    SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
+    SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
+    SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
+    /* Update the saved console information */
+    GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo);
+
+    /*
+     * Copy console data into VGA memory
+     */
+
+    /* Get the data */
+    AddressSize = VgaGetAddressSize();
+    ConRect.Left   = ConRect.Top = 0;
+    ConRect.Right  = TextResolution.X;
+    ConRect.Bottom = TextResolution.Y;
+    ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
+
+    /* Read the data from the console into the framebuffer... */
+    ReadConsoleOutputA(TextConsoleBuffer,
+                       CharBuff,
+                       TextResolution,
+                       Origin,
+                       &ConRect);
+
+    /* ... and copy the framebuffer into the VGA memory */
+
+    /* Loop through the scanlines */
+    for (i = 0; i < TextResolution.Y; i++)
+    {
+        /* Loop through the characters */
+        for (j = 0; j < TextResolution.X; j++)
+        {
+            CurrentAddr = LOWORD((Address + j) * AddressSize);
+
+            /* Store the character in plane 0 */
+            VgaMemory[CurrentAddr] = CharBuff[i * TextResolution.X + j].Char.AsciiChar;
+
+            /* Store the attribute in plane 1 */
+            VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuff[i * TextResolution.X + j].Attributes;
+        }
+
+        /* Move to the next scanline */
+        Address += ScanlineSize;
+    }
+
+    VgaUpdateCursorPosition();
+
+    return TRUE;
+}
+
+static BOOL IsConsoleHandle(HANDLE hHandle)
+{
+    DWORD dwMode;
+
+    /* Check whether the handle may be that of a console... */
+    if ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR)
+        return FALSE;
+
+    /*
+     * It may be. Perform another test... The idea comes from the
+     * MSDN description of the WriteConsole API:
+     *
+     * "WriteConsole fails if it is used with a standard handle
+     *  that is redirected to a file. If an application processes
+     *  multilingual output that can be redirected, determine whether
+     *  the output handle is a console handle (one method is to call
+     *  the GetConsoleMode function and check whether it succeeds).
+     *  If the handle is a console handle, call WriteConsole. If the
+     *  handle is not a console handle, the output is redirected and
+     *  you should call WriteFile to perform the I/O."
+     */
+    return GetConsoleMode(hHandle, &dwMode);
+}
+
+static inline DWORD VgaGetAddressSize(VOID)
+{
+    if (VgaCrtcRegisters[VGA_CRTC_UNDERLINE_REG] & VGA_CRTC_UNDERLINE_DWORD)
+    {
+        /* Double-word addressing */
+        return 4; // sizeof(DWORD)
+    }
+    else if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE)
+    {
+        /* Byte addressing */
+        return 1; // sizeof(BYTE)
+    }
+    else
+    {
+        /* Word addressing */
+        return 2; // sizeof(WORD)
+    }
+}
+
+static inline DWORD VgaTranslateReadAddress(DWORD Address)
+{
+    DWORD Offset = Address - VgaGetVideoBaseAddress();
+    BYTE Plane;
+
+    /* Check for chain-4 and odd-even mode */
+    if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+    {
+        /* The lowest two bits are the plane number */
+        Plane = Offset & 3;
+        Offset >>= 2;
+    }
+    else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+    {
+        /* The LSB is the plane number */
+        Plane = Offset & 1;
+        Offset >>= 1;
+    }
+    else
+    {
+        /* Use the read mode */
+        Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03;
+    }
+
+    /* Multiply the offset by the address size */
+    Offset *= VgaGetAddressSize();
+    
+    return Offset + Plane * VGA_BANK_SIZE;
+}
+
+static inline DWORD VgaTranslateWriteAddress(DWORD Address)
+{
+    DWORD Offset = Address - VgaGetVideoBaseAddress();
+
+    /* Check for chain-4 and odd-even mode */
+    if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+    {
+        /* Shift the offset to the right by 2 */
+        Offset >>= 2;
+    }
+    else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+    {
+        /* Shift the offset to the right by 1 */
+        Offset >>= 1;
+    }
+
+    /* Multiply the offset by the address size */
+    Offset *= VgaGetAddressSize();
+
+    /* Return the offset on plane 0 */
+    return Offset;
+}
+
+static inline BYTE VgaTranslateByteForWriting(BYTE Data, BYTE Plane)
+{
+    BYTE WriteMode = VgaGcRegisters[VGA_GC_MODE_REG] & 3;
+    BYTE BitMask = VgaGcRegisters[VGA_GC_BITMASK_REG];
+
+    if (WriteMode == 1)
+    {
+        /* In write mode 1 just return the latch register */
+        return VgaLatchRegisters[Plane];
+    }
+
+    if (WriteMode != 2)
+    {
+        /* Write modes 0 and 3 rotate the data to the right first */
+        BYTE RotateCount = VgaGcRegisters[VGA_GC_ROTATE_REG] & 7;
+        Data = LOBYTE(((DWORD)Data >> RotateCount) | ((DWORD)Data << (8 - RotateCount)));
+    }
+    else
+    {
+        /* Write mode 2 expands the appropriate bit to all 8 bits */
+        Data = (Data & (1 << Plane)) ? 0xFF : 0x00;
+    }
+
+    if (WriteMode == 0)
+    {
+        /*
+         * In write mode 0, the enable set/reset register decides if the
+         * set/reset bit should be expanded to all 8 bits.
+         */
+        if (VgaGcRegisters[VGA_GC_ENABLE_RESET_REG] & (1 << Plane))
+        {
+            /* Copy the bit from the set/reset register to all 8 bits */
+            Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00;
+        }
+    }
+
+    if (WriteMode != 3)
+    {
+        /* Write modes 0 and 2 then perform a logical operation on the data and latch */
+        BYTE LogicalOperation = (VgaGcRegisters[VGA_GC_ROTATE_REG] >> 3) & 3;
+
+        if (LogicalOperation == 1) Data &= VgaLatchRegisters[Plane];
+        else if (LogicalOperation == 2) Data |= VgaLatchRegisters[Plane];
+        else if (LogicalOperation == 3) Data ^= VgaLatchRegisters[Plane];
+    }
+    else
+    {
+        /* For write mode 3, we AND the bitmask with the data, which is used as the new bitmask */
+        BitMask &= Data;
+
+        /* Then we expand the bit in the set/reset field */
+        Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00;
+    }
+
+    /* Bits cleared in the bitmask are replaced with latch register bits */
+    Data = (Data & BitMask) | (VgaLatchRegisters[Plane] & (~BitMask));
+
+    /* Return the byte */
+    return Data;
+}
+
+static inline VOID VgaMarkForUpdate(SHORT Row, SHORT Column)
+{
+    /* Check if this is the first time the rectangle is updated */
+    if (!NeedsUpdate)
+    {
+        UpdateRectangle.Left = UpdateRectangle.Top = MAXSHORT;
+        UpdateRectangle.Right = UpdateRectangle.Bottom = MINSHORT;
+    }
+
+    /* Expand the rectangle to include the point */
+    UpdateRectangle.Left = min(UpdateRectangle.Left, Column);
+    UpdateRectangle.Right = max(UpdateRectangle.Right, Column);
+    UpdateRectangle.Top = min(UpdateRectangle.Top, Row);
+    UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Row);
+
+    /* Set the update request flag */
+    NeedsUpdate = TRUE;
+}
+
+static VOID VgaWriteSequencer(BYTE Data)
+{
+    ASSERT(VgaSeqIndex < VGA_SEQ_MAX_REG);
+
+    /* Save the value */
+    VgaSeqRegisters[VgaSeqIndex] = Data;
+}
+
+static VOID VgaWriteGc(BYTE Data)
+{
+    ASSERT(VgaGcIndex < VGA_GC_MAX_REG);
+
+    /* Save the value */
+    VgaGcRegisters[VgaGcIndex] = Data;
+
+    /* Check the index */
+    switch (VgaGcIndex)
+    {
+        case VGA_GC_MISC_REG:
+        {
+            /* The GC misc register decides if it's text or graphics mode */
+            ModeChanged = TRUE;
+            break;
+        }
+    }
+}
+
+static VOID VgaWriteCrtc(BYTE Data)
+{
+    ASSERT(VgaGcIndex < VGA_CRTC_MAX_REG);
+
+    /* Save the value */
+    VgaCrtcRegisters[VgaCrtcIndex] = Data;
+
+    /* Check the index */
+    switch (VgaCrtcIndex)
+    {
+        case VGA_CRTC_END_HORZ_DISP_REG:
+        case VGA_CRTC_VERT_DISP_END_REG:
+        case VGA_CRTC_OVERFLOW_REG:
+        {
+            /* The video mode has changed */
+            ModeChanged = TRUE;
+            break;
+        }
+
+        case VGA_CRTC_CURSOR_LOC_LOW_REG:
+        case VGA_CRTC_CURSOR_LOC_HIGH_REG:
+        case VGA_CRTC_CURSOR_START_REG:
+        case VGA_CRTC_CURSOR_END_REG:
+        {
+            /* Set the cursor moved flag */
+            CursorMoved = TRUE;
+            break;
+        }
+    }
+}
+
+static VOID VgaWriteDac(BYTE Data)
+{
+    INT PaletteIndex;
+    PALETTEENTRY Entry;
+
+    /* Set the value */
+    VgaDacRegisters[VgaDacIndex] = Data;
+
+    /* Find the palette index */
+    PaletteIndex = VgaDacIndex / 3;
+
+    /* Fill the entry structure */
+    Entry.peRed = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3]);
+    Entry.peGreen = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 1]);
+    Entry.peBlue = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 2]);
+    Entry.peFlags = 0;
+
+    /* Update the palette entry and set the palette change flag */
+    SetPaletteEntries(PaletteHandle, PaletteIndex, 1, &Entry);
+    PaletteChanged = TRUE;
+
+    /* Update the index */
+    VgaDacIndex++;
+    VgaDacIndex %= VGA_PALETTE_SIZE;
+}
+
+static VOID VgaWriteAc(BYTE Data)
+{
+    ASSERT(VgaAcIndex < VGA_AC_MAX_REG);
+
+    /* Save the value */
+    if (VgaAcIndex <= VGA_AC_PAL_F_REG)
+    {
+        if (VgaAcPalDisable) return;
+
+        // DbgPrint("    AC Palette Writing %d to index %d\n", Data, VgaAcIndex);
+        if (VgaAcRegisters[VgaAcIndex] != Data)
+        {
+            /* Update the AC register and set the palette change flag */
+            VgaAcRegisters[VgaAcIndex] = Data;
+            PaletteChanged = TRUE;
+        }
+    }
+    else
+    {
+        VgaAcRegisters[VgaAcIndex] = Data;
+    }
+}
+
+static VOID VgaRestoreDefaultPalette(PPALETTEENTRY Entries, USHORT NumOfEntries)
+{
+    USHORT i;
+
+    /* Copy the colors of the default palette to the DAC and console palette */
+    for (i = 0; i < NumOfEntries; i++)
+    {
+        /* Set the palette entries */
+        Entries[i].peRed   = GetRValue(VgaDefaultPalette[i]);
+        Entries[i].peGreen = GetGValue(VgaDefaultPalette[i]);
+        Entries[i].peBlue  = GetBValue(VgaDefaultPalette[i]);
+        Entries[i].peFlags = 0;
+
+        /* Set the DAC registers */
+        VgaDacRegisters[i * 3]     = VGA_COLOR_TO_DAC(GetRValue(VgaDefaultPalette[i]));
+        VgaDacRegisters[i * 3 + 1] = VGA_COLOR_TO_DAC(GetGValue(VgaDefaultPalette[i]));
+        VgaDacRegisters[i * 3 + 2] = VGA_COLOR_TO_DAC(GetBValue(VgaDefaultPalette[i]));
+    }
+}
+
+static BOOLEAN VgaInitializePalette(VOID)
+{
+    LPLOGPALETTE Palette;
+
+    /* Allocate storage space for the palette */
+    Palette = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(),
+                                      HEAP_ZERO_MEMORY,
+                                      sizeof(LOGPALETTE) +
+                                        VGA_MAX_COLORS * sizeof(PALETTEENTRY));
+    if (Palette == NULL) return FALSE;
+
+    /* Initialize the palette */
+    Palette->palVersion = 0x0300;
+    Palette->palNumEntries = VGA_MAX_COLORS;
+
+    /* Restore the default palette */
+    VgaRestoreDefaultPalette(Palette->palPalEntry, Palette->palNumEntries);
+
+    /* Create the palette */
+    PaletteHandle = CreatePalette(Palette);
+
+    /* Free the palette */
+    HeapFree(GetProcessHeap(), 0, Palette);
+
+    /* Fail if the palette wasn't successfully created... */
+    if (PaletteHandle == NULL) return FALSE;
+
+    /* ... otherwise return success */
+    return TRUE;
+}
+
+static BOOL VgaEnterGraphicsMode(PCOORD Resolution)
+{
+    DWORD i;
+    CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
+    BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE];
+    LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer;
+    LPWORD PaletteIndex = (LPWORD)(BitmapInfo->bmiColors);
+
+    LONG Width  = Resolution->X;
+    LONG Height = Resolution->Y;
+
+    /* Use DoubleVision mode if the resolution is too small */
+    if (Width < VGA_MINIMUM_WIDTH && Height < VGA_MINIMUM_HEIGHT)
+    {
+        DoubleVision = TRUE;
+        Width  *= 2;
+        Height *= 2;
+    }
+    else
+    {
+        DoubleVision = FALSE;
+    }
+
+    /* Fill the bitmap info header */
+    ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER));
+    BitmapInfo->bmiHeader.biSize   = sizeof(BITMAPINFOHEADER);
+    BitmapInfo->bmiHeader.biWidth  = Width;
+    BitmapInfo->bmiHeader.biHeight = Height;
+    BitmapInfo->bmiHeader.biBitCount = 8;
+    BitmapInfo->bmiHeader.biPlanes   = 1;
+    BitmapInfo->bmiHeader.biCompression = BI_RGB;
+    BitmapInfo->bmiHeader.biSizeImage   = Width * Height /* * 1 == biBitCount / 8 */;
+
+    /* Fill the palette data */
+    for (i = 0; i < (VGA_PALETTE_SIZE / 3); i++) PaletteIndex[i] = (WORD)i;
+
+    /* Fill the console graphics buffer info */
+    GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE;
+    GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
+    GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
+
+    /* Create the buffer */
+    GraphicsConsoleBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+                                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                                      NULL,
+                                                      CONSOLE_GRAPHICS_BUFFER,
+                                                      &GraphicsBufferInfo);
+    if (GraphicsConsoleBuffer == INVALID_HANDLE_VALUE) return FALSE;
+
+    /* Save the framebuffer address and mutex */
+    ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap;
+    ConsoleMutex = GraphicsBufferInfo.hMutex;
+
+    /* Clear the framebuffer */
+    ZeroMemory(ConsoleFramebuffer, BitmapInfo->bmiHeader.biSizeImage);
+
+    /* Set the active buffer */
+    SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer);
+
+    /* Set the graphics mode palette */
+    SetConsolePalette(GraphicsConsoleBuffer,
+                      PaletteHandle,
+                      SYSPAL_NOSTATIC256);
+
+    /* Set the screen mode flag */
+    ScreenMode = GRAPHICS_MODE;
+
+    return TRUE;
+}
+
+static VOID VgaLeaveGraphicsMode(VOID)
+{
+    /* Release the console framebuffer mutex */
+    ReleaseMutex(ConsoleMutex);
+
+    /* Switch back to the default console text buffer */
+    // SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+    /* Cleanup the video data */
+    CloseHandle(ConsoleMutex);
+    ConsoleMutex = NULL;
+    ConsoleFramebuffer = NULL;
+    CloseHandle(GraphicsConsoleBuffer);
+    GraphicsConsoleBuffer = NULL;
+    DoubleVision = FALSE;
+}
+
+static BOOL VgaEnterTextMode(PCOORD Resolution)
+{
+    DPRINT1("VgaEnterTextMode\n");
+
+    /* Switch to the text buffer */
+    SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+    /* Adjust the text framebuffer if we changed the resolution */
+    if (TextResolution.X != Resolution->X ||
+        TextResolution.Y != Resolution->Y)
+    {
+        VgaDetachFromConsole(TRUE);
+
+        /*
+         * VgaAttachToConsoleInternal sets TextResolution to the
+         * new resolution and updates ConsoleInfo.
+         */
+        if (!VgaAttachToConsoleInternal(Resolution))
+        {
+            DisplayMessage(L"An unexpected error occurred!\n");
+            EmulatorTerminate();
+            return FALSE;
+        }
+    }
+    else
+    {
+        VgaUpdateCursorPosition();
+    }
+
+    /* The active framebuffer is now the text framebuffer */
+    ConsoleFramebuffer = TextFramebuffer;
+
+    /*
+     * Set the text mode palette.
+     *
+     * WARNING: This call should fail on Windows (and therefore
+     * we get the default palette and our external behaviour is
+     * just like Windows' one), but it should success on ReactOS
+     * (so that we get console palette changes even for text-mode
+     * screen-buffers, which is a new feature on ReactOS).
+     */
+    SetConsolePalette(TextConsoleBuffer,
+                      PaletteHandle,
+                      SYSPAL_NOSTATIC256);
+
+    /* Set the screen mode flag */
+    ScreenMode = TEXT_MODE;
+
+    return TRUE;
+}
+
+static VOID VgaLeaveTextMode(VOID)
+{
+    /* Reset the active framebuffer */
+    ConsoleFramebuffer = NULL;
+}
+
+static VOID VgaChangeMode(VOID)
+{
+    COORD Resolution = VgaGetDisplayResolution();
+
+    if (ScreenMode == GRAPHICS_MODE)
+    {
+        /* Leave the current graphics mode */
+        VgaLeaveGraphicsMode();
+    }
+    else
+    {
+        /* Leave the current text mode */
+        VgaLeaveTextMode();
+    }
+
+    /* Check if the new mode is alphanumeric */
+    if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA))
+    {
+        /* Enter new text mode */
+        if (!VgaEnterTextMode(&Resolution))
+        {
+            DisplayMessage(L"An unexpected VGA error occurred while switching into text mode.");
+            EmulatorTerminate();
+            return;
+        }
+    }
+    else
+    {
+        /* Enter graphics mode */
+        if (!VgaEnterGraphicsMode(&Resolution))
+        {
+            DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode.");
+            EmulatorTerminate();
+            return;
+        }
+    }
+
+    /* Trigger a full update of the screen */
+    NeedsUpdate = TRUE;
+    UpdateRectangle.Left = 0;
+    UpdateRectangle.Top = 0;
+    UpdateRectangle.Right = Resolution.X;
+    UpdateRectangle.Bottom = Resolution.Y;
+
+    /* Reset the mode change flag */
+    ModeChanged = FALSE;
+}
+
+static VOID VgaUpdateFramebuffer(VOID)
+{
+    SHORT i, j, k;
+    COORD Resolution = VgaGetDisplayResolution();
+    DWORD AddressSize = VgaGetAddressSize();
+    DWORD Address = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG],
+                             VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG]);
+    DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
+
+    /*
+     * If console framebuffer is NULL, that means something went wrong
+     * earlier and this is the final display refresh.
+     */
+    if (ConsoleFramebuffer == NULL) return;
+
+    /* Check if this is text mode or graphics mode */
+    if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+    {
+        /* Graphics mode */
+        PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer;
+        DWORD InterlaceHighBit = VGA_INTERLACE_HIGH_BIT;
+
+        /*
+         * Synchronize access to the graphics framebuffer
+         * with the console framebuffer mutex.
+         */
+        WaitForSingleObject(ConsoleMutex, INFINITE);
+
+        /* Shift the high bit right by 1 in odd/even mode */
+        if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+        {
+            InterlaceHighBit >>= 1;
+        }
+
+        /* Loop through the scanlines */
+        for (i = 0; i < Resolution.Y; i++)
+        {
+            if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) && (i & 1))
+            {
+                /* Odd-numbered line in interlaced mode - set the high bit */
+                Address |= InterlaceHighBit;
+            }
+
+            /* Loop through the pixels */
+            for (j = 0; j < Resolution.X; j++)
+            {
+                BYTE PixelData = 0;
+
+                /* Check the shifting mode */
+                if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFT256)
+                {
+                    /* 4 bits shifted from each plane */
+
+                    /* Check if this is 16 or 256 color mode */
+                    if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+                    {
+                        /* One byte per pixel */
+                        PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
+                                              + (Address + (j / VGA_NUM_BANKS))
+                                                * AddressSize];
+                    }
+                    else
+                    {
+                        /* 4-bits per pixel */
+
+                        PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
+                                              + (Address + (j / (VGA_NUM_BANKS * 2)))
+                                                * AddressSize];
+
+                        /* Check if we should use the highest 4 bits or lowest 4 */
+                        if (((j / VGA_NUM_BANKS) % 2) == 0)
+                        {
+                            /* Highest 4 */
+                            PixelData >>= 4;
+                        }
+                        else
+                        {
+                            /* Lowest 4 */
+                            PixelData &= 0x0F;
+                        }
+                    }
+                }
+                else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFTREG)
+                {
+                    /* Check if this is 16 or 256 color mode */
+                    if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+                    {
+                        // TODO: NOT IMPLEMENTED
+                        DPRINT1("8-bit interleaved mode is not implemented!\n");
+                    }
+                    else
+                    {
+                        /*
+                         * 2 bits shifted from plane 0 and 2 for the first 4 pixels,
+                         * then 2 bits shifted from plane 1 and 3 for the next 4
+                         */
+                        DWORD BankNumber = (j / 4) % 2;
+                        DWORD Offset = Address + (j / 8);
+                        BYTE LowPlaneData = VgaMemory[BankNumber * VGA_BANK_SIZE + Offset * AddressSize];
+                        BYTE HighPlaneData = VgaMemory[(BankNumber + 2) * VGA_BANK_SIZE + Offset * AddressSize];
+
+                        /* Extract the two bits from each plane */
+                        LowPlaneData = (LowPlaneData >> (6 - ((j % 4) * 2))) & 3;
+                        HighPlaneData = (HighPlaneData >> (6 - ((j % 4) * 2))) & 3;
+
+                        /* Combine them into the pixel */
+                        PixelData = LowPlaneData | (HighPlaneData << 2);
+                    }
+                }
+                else
+                {
+                    /* 1 bit shifted from each plane */
+
+                    /* Check if this is 16 or 256 color mode */
+                    if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+                    {
+                        /* 8 bits per pixel, 2 on each plane */
+
+                        for (k = 0; k < VGA_NUM_BANKS; k++)
+                        {
+                            /* The data is on plane k, 4 pixels per byte */
+                            BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
+                                                       + (Address + (j / VGA_NUM_BANKS))
+                                                         * AddressSize];
+
+                            /* The mask of the first bit in the pair */
+                            BYTE BitMask = 1 << (((3 - (j % VGA_NUM_BANKS)) * 2) + 1);
+
+                            /* Bits 0, 1, 2 and 3 come from the first bit of the pair */
+                            if (PlaneData & BitMask) PixelData |= 1 << k;
+
+                            /* Bits 4, 5, 6 and 7 come from the second bit of the pair */
+                            if (PlaneData & (BitMask >> 1)) PixelData |= 1 << (k + 4);
+                        }
+                    }
+                    else
+                    {
+                        /* 4 bits per pixel, 1 on each plane */
+
+                        for (k = 0; k < VGA_NUM_BANKS; k++)
+                        {
+                            BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
+                                                       + (Address + (j / (VGA_NUM_BANKS * 2)))
+                                                         * AddressSize];
+
+                            /* If the bit on that plane is set, set it */
+                            if (PlaneData & (1 << (7 - (j % 8)))) PixelData |= 1 << k;
+                        }
+                    }
+                }
+
+                if (!(VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT))
+                {
+                    /*
+                     * In 16 color mode, the value is an index to the AC registers
+                     * if external palette access is disabled, otherwise (in case
+                     * of palette loading) it is a blank pixel.
+                     */
+                    PixelData = (VgaAcPalDisable ? VgaAcRegisters[PixelData & 0x0F]
+                                                 : 0);
+                }
+
+                /* Take into account DoubleVision mode when checking for pixel updates */
+                if (DoubleVision)
+                {
+                    /* Now check if the resulting pixel data has changed */
+                    if (GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] != PixelData)
+                    {
+                        /* Yes, write the new value */
+                        GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] = PixelData;
+                        GraphicsBuffer[(i * Resolution.X * 4) + (j * 2 + 1)] = PixelData;
+                        GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2)] = PixelData;
+                        GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2 + 1)] = PixelData;
+
+                        /* Mark the specified pixel as changed */
+                        VgaMarkForUpdate(i, j);
+                    }
+                }
+                else
+                {
+                    /* Now check if the resulting pixel data has changed */
+                    if (GraphicsBuffer[i * Resolution.X + j] != PixelData)
+                    {
+                        /* Yes, write the new value */
+                        GraphicsBuffer[i * Resolution.X + j] = PixelData;
+
+                        /* Mark the specified pixel as changed */
+                        VgaMarkForUpdate(i, j);
+                    }
+                }
+            }
+
+            if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) && (i & 1))
+            {
+                /* Clear the high bit */
+                Address &= ~InterlaceHighBit;
+            }
+
+            if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) || (i & 1))
+            {
+                /* Move to the next scanline */
+                Address += ScanlineSize;
+            }
+        }
+
+        /*
+         * Release the console framebuffer mutex
+         * so that we allow for repainting.
+         */
+        ReleaseMutex(ConsoleMutex);
+    }
+    else
+    {
+        /* Text mode */
+        DWORD CurrentAddr;
+        PCHAR_CELL CharBuffer = (PCHAR_CELL)ConsoleFramebuffer;
+        CHAR_CELL CharInfo;
+
+        /* Loop through the scanlines */
+        for (i = 0; i < Resolution.Y; i++)
+        {
+            /* Loop through the characters */
+            for (j = 0; j < Resolution.X; j++)
+            {
+                CurrentAddr = LOWORD((Address + j) * AddressSize);
+
+                /* Plane 0 holds the character itself */
+                CharInfo.Char = VgaMemory[CurrentAddr];
+
+                /* Plane 1 holds the attribute */
+                CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE];
+
+                /* Now check if the resulting character data has changed */
+                if ((CharBuffer[i * Resolution.X + j].Char != CharInfo.Char) ||
+                    (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes))
+                {
+                    /* Yes, write the new value */
+                    CharBuffer[i * Resolution.X + j] = CharInfo;
+
+                    /* Mark the specified cell as changed */
+                    VgaMarkForUpdate(i, j);
+                }
+            }
+
+            /* Move to the next scanline */
+            Address += ScanlineSize;
+        }
+    }
+}
+
+static VOID VgaUpdateTextCursor(VOID)
+{
+    COORD Position;
+    CONSOLE_CURSOR_INFO CursorInfo;
+    BYTE CursorStart = VgaCrtcRegisters[VGA_CRTC_CURSOR_START_REG] & 0x3F;
+    BYTE CursorEnd = VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] & 0x1F;
+    DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
+    BYTE TextSize = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F);
+    WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG],
+                             VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]);
+
+    /* Just return if we are not in text mode */
+    if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) return;
+
+    if (CursorStart < CursorEnd)
+    {
+        /* Visible cursor */
+        CursorInfo.bVisible = TRUE;
+        CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) / TextSize;
+    }
+    else
+    {
+        /* No cursor */
+        CursorInfo.bVisible = FALSE;
+        CursorInfo.dwSize = 0;
+    }
+
+    /* Add the cursor skew to the location */
+    Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3;
+
+    /* Find the coordinates of the new position */
+    Position.X = (SHORT)(Location % ScanlineSize);
+    Position.Y = (SHORT)(Location / ScanlineSize);
+
+    DPRINT1("VgaUpdateTextCursor: X = %d ; Y = %d\n", Position.X, Position.Y);
+
+    /* Update the physical cursor */
+    SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo);
+    SetConsoleCursorPosition(TextConsoleBuffer, Position);
+
+    /* Reset the cursor move flag */
+    CursorMoved = FALSE;
+}
+
+static BYTE WINAPI VgaReadPort(ULONG Port)
+{
+    DPRINT("VgaReadPort: Port 0x%X\n", Port);
+
+    switch (Port)
+    {
+        case VGA_MISC_READ:
+            return VgaMiscRegister;
+
+        case VGA_INSTAT0_READ:
+            return 0; // Not implemented
+
+        case VGA_INSTAT1_READ_MONO:
+        case VGA_INSTAT1_READ_COLOR:
+        {
+            BYTE Result = 0;
+
+            /* Reset the AC latch */
+            VgaAcLatch = FALSE;
+
+            /* Set a flag if there is a vertical or horizontal retrace */
+            if (InVerticalRetrace || InHorizontalRetrace) Result |= VGA_STAT_DD;
+
+            /* Set an additional flag if there was a vertical retrace */
+            if (InVerticalRetrace) Result |= VGA_STAT_VRETRACE;
+
+            /* Clear the flags */
+            InHorizontalRetrace = InVerticalRetrace = FALSE;
+
+            return Result;
+        }
+
+        case VGA_FEATURE_READ:
+            return VgaFeatureRegister;
+
+        case VGA_AC_INDEX:
+            return VgaAcIndex;
+
+        case VGA_AC_READ:
+            return VgaAcRegisters[VgaAcIndex];
+
+        case VGA_SEQ_INDEX:
+            return VgaSeqIndex;
+        
+        case VGA_SEQ_DATA:
+            return VgaSeqRegisters[VgaSeqIndex];
+
+        case VGA_DAC_MASK:
+            return VgaDacMask;
+
+        case VGA_DAC_READ_INDEX:
+            /* This returns the read/write state */
+            return (VgaDacReadWrite ? 0 : 3);
+
+        case VGA_DAC_WRITE_INDEX:
+            return (VgaDacIndex / 3);
+
+        case VGA_DAC_DATA:
+        {
+            /* Ignore reads in write mode */
+            if (!VgaDacReadWrite)
+            {
+                BYTE Data = VgaDacRegisters[VgaDacIndex++];
+                VgaDacIndex %= VGA_PALETTE_SIZE;
+                return Data;
+            }
+
+            break;
+        }
+
+        case VGA_CRTC_INDEX_MONO:
+        case VGA_CRTC_INDEX_COLOR:
+            return VgaCrtcIndex;
+
+        case VGA_CRTC_DATA_MONO:
+        case VGA_CRTC_DATA_COLOR:
+            return VgaCrtcRegisters[VgaCrtcIndex];
+
+        case VGA_GC_INDEX:
+            return VgaGcIndex;
+
+        case VGA_GC_DATA:
+            return VgaGcRegisters[VgaGcIndex];
+
+        default:
+            DPRINT1("VgaReadPort: Unknown port 0x%X\n", Port);
+            break;
+    }
+
+    return 0;
+}
+
+static VOID WINAPI VgaWritePort(ULONG Port, BYTE Data)
+{
+    DPRINT("VgaWritePort: Port 0x%X, Data 0x%02X\n", Port, Data);
+
+    switch (Port)
+    {
+        case VGA_MISC_WRITE:
+        {
+            VgaMiscRegister = Data;
+
+            if (VgaMiscRegister & 0x01)
+            {
+                /* Color emulation */
+                DPRINT1("Color emulation\n");
+
+                /* Register the new I/O Ports */
+                RegisterIoPort(0x3D4, VgaReadPort, VgaWritePort);   // VGA_CRTC_INDEX_COLOR
+                RegisterIoPort(0x3D5, VgaReadPort, VgaWritePort);   // VGA_CRTC_DATA_COLOR
+                RegisterIoPort(0x3DA, VgaReadPort, VgaWritePort);   // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
+
+                /* Unregister the old ones */
+                UnregisterIoPort(0x3B4);    // VGA_CRTC_INDEX_MONO
+                UnregisterIoPort(0x3B5);    // VGA_CRTC_DATA_MONO
+                UnregisterIoPort(0x3BA);    // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
+            }
+            else
+            {
+                /* Monochrome emulation */
+                DPRINT1("Monochrome emulation\n");
+
+                /* Register the new I/O Ports */
+                RegisterIoPort(0x3B4, VgaReadPort, VgaWritePort);   // VGA_CRTC_INDEX_MONO
+                RegisterIoPort(0x3B5, VgaReadPort, VgaWritePort);   // VGA_CRTC_DATA_MONO
+                RegisterIoPort(0x3BA, VgaReadPort, VgaWritePort);   // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
+
+                /* Unregister the old ones */
+                UnregisterIoPort(0x3D4);    // VGA_CRTC_INDEX_COLOR
+                UnregisterIoPort(0x3D5);    // VGA_CRTC_DATA_COLOR
+                UnregisterIoPort(0x3DA);    // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
+            }
+
+            // if (VgaMiscRegister & 0x02) { /* Enable RAM access */ } else { /* Disable RAM access */ }
+            break;
+        }
+
+        case VGA_FEATURE_WRITE_MONO:
+        case VGA_FEATURE_WRITE_COLOR:
+        {
+            VgaFeatureRegister = Data;
+            break;
+        }
+
+        case VGA_AC_INDEX:
+        // case VGA_AC_WRITE:
+        {
+            if (!VgaAcLatch)
+            {
+                /* Change the index */
+                BYTE Index = Data & 0x1F;
+                if (Index < VGA_AC_MAX_REG) VgaAcIndex = Index;
+
+                /*
+                 * Change palette protection by checking for
+                 * the Palette Address Source bit.
+                 */
+                VgaAcPalDisable = (Data & 0x20) ? TRUE : FALSE;
+            }
+            else
+            {
+                /* Write the data */
+                VgaWriteAc(Data);
+            }
+
+            /* Toggle the latch */
+            VgaAcLatch = !VgaAcLatch;
+            break;
+        }
+
+        case VGA_SEQ_INDEX:
+        {
+            /* Set the sequencer index register */
+            if (Data < VGA_SEQ_MAX_REG) VgaSeqIndex = Data;
+            break;
+        }
+
+        case VGA_SEQ_DATA:
+        {
+            /* Call the sequencer function */
+            VgaWriteSequencer(Data);
+            break;
+        }
+
+        case VGA_DAC_MASK:
+        {
+            VgaDacMask = Data;
+            break;
+        }
+
+        case VGA_DAC_READ_INDEX:
+        {
+            VgaDacReadWrite = FALSE;
+            VgaDacIndex = Data * 3;
+            break;
+        }
+
+        case VGA_DAC_WRITE_INDEX:
+        {
+            VgaDacReadWrite = TRUE;
+            VgaDacIndex = Data * 3;
+            break;
+        }
+
+        case VGA_DAC_DATA:
+        {
+            /* Ignore writes in read mode */
+            if (VgaDacReadWrite) VgaWriteDac(Data & 0x3F);
+            break;
+        }
+
+        case VGA_CRTC_INDEX_MONO:
+        case VGA_CRTC_INDEX_COLOR:
+        {
+            /* Set the CRTC index register */
+            if (Data < VGA_CRTC_MAX_REG) VgaCrtcIndex = Data;
+            break;
+        }
+
+        case VGA_CRTC_DATA_MONO:
+        case VGA_CRTC_DATA_COLOR:
+        {
+            /* Call the CRTC function */
+            VgaWriteCrtc(Data);
+            break;
+        }
+
+        case VGA_GC_INDEX:
+        {
+            /* Set the GC index register */
+            if (Data < VGA_GC_MAX_REG) VgaGcIndex = Data;
+            break;
+        }
+
+        case VGA_GC_DATA:
+        {
+            /* Call the GC function */
+            VgaWriteGc(Data);
+            break;
+        }
+
+        default:
+            DPRINT1("VgaWritePort: Unknown port 0x%X\n", Port);
+            break;
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+DWORD VgaGetVideoBaseAddress(VOID)
+{
+    return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
+}
+
+DWORD VgaGetVideoLimitAddress(VOID)
+{
+    return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
+}
+
+COORD VgaGetDisplayResolution(VOID)
+{
+    COORD Resolution;
+    BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F);
+
+    /* The low 8 bits are in the display registers */
+    Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG];
+    Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG];
+
+    /* Set the top bits from the overflow register */
+    if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8)
+    {
+        Resolution.Y |= 1 << 8;
+    }
+    if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9)
+    {
+        Resolution.Y |= 1 << 9;
+    }
+
+    /* Increase the values by 1 */
+    Resolution.X++;
+    Resolution.Y++;
+
+    if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+    {
+        /* Multiply the horizontal resolution by the 9/8 dot mode */
+        Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM)
+                        ? 8 : 9;
+
+        /* The horizontal resolution is halved in 8-bit mode */
+        if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2;
+    }
+
+    if (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & VGA_CRTC_MAXSCANLINE_DOUBLE)
+    {
+        /* Halve the vertical resolution */
+        Resolution.Y >>= 1;
+    }
+    else
+    {
+        /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */
+        Resolution.Y /= MaximumScanLine;
+    }
+
+    /* Return the resolution */
+    return Resolution;
+}
+
+VOID VgaRefreshDisplay(VOID)
+{
+    HANDLE ConsoleBufferHandle = NULL;
+    COORD Resolution;
+
+    /* Set the vertical retrace flag */
+    InVerticalRetrace = TRUE;
+
+    /* If nothing has changed, just return */
+    // if (!ModeChanged && !CursorMoved && !PaletteChanged && !NeedsUpdate)
+        // return;
+
+    /* Change the display mode */
+    if (ModeChanged) VgaChangeMode();
+
+    /* Change the text cursor location */
+    if (CursorMoved) VgaUpdateTextCursor();
+
+    /* Retrieve the current resolution */
+    Resolution = VgaGetDisplayResolution();
+
+    if (PaletteChanged)
+    {
+        /* Trigger a full update of the screen */
+        NeedsUpdate = TRUE;
+        UpdateRectangle.Left = 0;
+        UpdateRectangle.Top = 0;
+        UpdateRectangle.Right = Resolution.X;
+        UpdateRectangle.Bottom = Resolution.Y;
+
+        PaletteChanged = FALSE;
+    }
+
+    /* Update the contents of the framebuffer */
+    VgaUpdateFramebuffer();
+
+    /* Ignore if there's nothing to update */
+    if (!NeedsUpdate) return;
+
+    DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n",
+           UpdateRectangle.Left,
+           UpdateRectangle.Top,
+           UpdateRectangle.Right,
+           UpdateRectangle.Bottom);
+
+    /* Check if this is text mode or graphics mode */
+    if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+    {
+        /* Graphics mode */
+        ConsoleBufferHandle = GraphicsConsoleBuffer;
+
+        /* In DoubleVision mode, scale the update rectangle */
+        if (DoubleVision)
+        {
+            UpdateRectangle.Left *= 2;
+            UpdateRectangle.Top  *= 2;
+            UpdateRectangle.Right  = UpdateRectangle.Right  * 2 + 1;
+            UpdateRectangle.Bottom = UpdateRectangle.Bottom * 2 + 1;
+        }
+    }
+    else
+    {
+        /* Text mode */
+        ConsoleBufferHandle = TextConsoleBuffer;
+    }
+
+    /* Redraw the screen */
+    __InvalidateConsoleDIBits(ConsoleBufferHandle, &UpdateRectangle);
+
+    /* Clear the update flag */
+    NeedsUpdate = FALSE;
+}
+
+VOID VgaHorizontalRetrace(VOID)
+{
+    /* Set the flag */
+    InHorizontalRetrace = TRUE;
+}
+
+VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
+{
+    DWORD i;
+    DWORD VideoAddress;
+
+    DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size);
+
+    /* Ignore if video RAM access is disabled */
+    if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
+
+    /* Loop through each byte */
+    for (i = 0; i < Size; i++)
+    {
+        VideoAddress = VgaTranslateReadAddress(Address + i);
+
+        /* Load the latch registers */
+        VgaLatchRegisters[0] = VgaMemory[LOWORD(VideoAddress)];
+        VgaLatchRegisters[1] = VgaMemory[VGA_BANK_SIZE + LOWORD(VideoAddress)];
+        VgaLatchRegisters[2] = VgaMemory[(2 * VGA_BANK_SIZE) + LOWORD(VideoAddress)];
+        VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)];
+
+        /* Copy the value to the buffer */
+        Buffer[i] = VgaMemory[VideoAddress];
+    }
+}
+
+VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
+{
+    DWORD i, j;
+    DWORD VideoAddress;
+
+    DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size);
+
+    /* Ignore if video RAM access is disabled */
+    if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
+
+    /* Also ignore if write access to all planes is disabled */
+    if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return;
+
+    /* Loop through each byte */
+    for (i = 0; i < Size; i++)
+    {
+        VideoAddress = VgaTranslateWriteAddress(Address + i);
+
+        for (j = 0; j < VGA_NUM_BANKS; j++)
+        {
+            /* Make sure the page is writeable */
+            if (!(VgaSeqRegisters[VGA_SEQ_MASK_REG] & (1 << j))) continue;
+
+            /* Check if this is chain-4 mode */
+            if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+            {
+                if (((Address + i) & 3) != j)
+                {
+                    /* This plane will not be accessed */
+                    continue;
+                }
+            }
+
+            /* Check if this is odd-even mode */
+            if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+            {
+                if (((Address + i) & 1) != (j & 1))
+                {
+                    /* This plane will not be accessed */
+                    continue;
+                }
+            }
+
+            /* Copy the value to the VGA memory */
+            VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j);
+        }
+    }
+}
+
+VOID VgaClearMemory(VOID)
+{
+    ZeroMemory(VgaMemory, sizeof(VgaMemory));
+}
+
+VOID VgaResetPalette(VOID)
+{
+    PALETTEENTRY Entries[VGA_MAX_COLORS];
+
+    /* Restore the default palette */
+    VgaRestoreDefaultPalette(Entries, VGA_MAX_COLORS);
+    SetPaletteEntries(PaletteHandle, 0, VGA_MAX_COLORS, Entries);
+    PaletteChanged = TRUE;
+}
+
+
+
+
+BOOL VgaAttachToConsole(VOID)
+{
+    //
+    // FIXME: We should go back to the saved screen state
+    //
+    if (TextResolution.X == 0 || TextResolution.Y == 0)
+        DPRINT1("VgaAttachToConsole -- TextResolution uninitialized\n");
+
+    if (TextResolution.X == 0) TextResolution.X = 80;
+    if (TextResolution.Y == 0) TextResolution.Y = 25;
+
+    return VgaAttachToConsoleInternal(&TextResolution);
+}
+
+VOID VgaDetachFromConsole(BOOL ChangingMode)
+{
+    ULONG dummyLength;
+    PVOID dummyPtr;
+    COORD dummySize = {0};
+
+    //
+    // FIXME: We should save the screen state
+    //
+
+    __RegisterConsoleVDM(0,
+                         NULL,
+                         NULL,
+                         NULL,
+                         0,
+                         &dummyLength,
+                         &dummyPtr,
+                         NULL,
+                         0,
+                         dummySize,
+                         (PCHAR*)&dummyPtr);
+
+    TextFramebuffer = NULL;
+
+    if (!ChangingMode)
+    {
+        SMALL_RECT ConRect;
+
+        /* Restore the old screen buffer */
+        SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+        /* Restore the original console size */
+        ConRect.Left   = 0;
+        ConRect.Top    = 0;
+        ConRect.Right  = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right  - OrgConsoleBufferInfo.srWindow.Left;
+        ConRect.Bottom = ConRect.Top  + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ;
+        /*
+         * See the following trick explanation in VgaAttachToConsoleInternal.
+         */
+        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
+        SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
+        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
+
+        /* Restore the original cursor shape */
+        SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo);
+    }
+}
+
+BOOLEAN VgaInitialize(HANDLE TextHandle)
+{
+    /* Save the default text-mode console output handle */
+    if (!IsConsoleHandle(TextHandle)) return FALSE;
+    TextConsoleBuffer = TextHandle;
+
+    /* Save the original cursor and console screen buffer information */
+    if (!GetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo) ||
+        !GetConsoleScreenBufferInfo(TextConsoleBuffer, &OrgConsoleBufferInfo))
+    {
+        return FALSE;
+    }
+    ConsoleInfo = OrgConsoleBufferInfo;
+
+    /* Initialize the VGA palette and fail if it isn't successfully created */
+    if (!VgaInitializePalette()) return FALSE;
+    /***/ VgaResetPalette(); /***/
+
+    /* Switch to the text buffer */
+    SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+    /* Clear the VGA memory */
+    VgaClearMemory();
+
+    /* Register the I/O Ports */
+    RegisterIoPort(0x3CC, VgaReadPort, NULL);           // VGA_MISC_READ
+    RegisterIoPort(0x3C2, VgaReadPort, VgaWritePort);   // VGA_MISC_WRITE, VGA_INSTAT0_READ
+    RegisterIoPort(0x3CA, VgaReadPort, NULL);           // VGA_FEATURE_READ
+    RegisterIoPort(0x3C0, VgaReadPort, VgaWritePort);   // VGA_AC_INDEX, VGA_AC_WRITE
+    RegisterIoPort(0x3C1, VgaReadPort, NULL);           // VGA_AC_READ
+    RegisterIoPort(0x3C4, VgaReadPort, VgaWritePort);   // VGA_SEQ_INDEX
+    RegisterIoPort(0x3C5, VgaReadPort, VgaWritePort);   // VGA_SEQ_DATA
+    RegisterIoPort(0x3C6, VgaReadPort, VgaWritePort);   // VGA_DAC_MASK
+    RegisterIoPort(0x3C7, VgaReadPort, VgaWritePort);   // VGA_DAC_READ_INDEX
+    RegisterIoPort(0x3C8, VgaReadPort, VgaWritePort);   // VGA_DAC_WRITE_INDEX
+    RegisterIoPort(0x3C9, VgaReadPort, VgaWritePort);   // VGA_DAC_DATA
+    RegisterIoPort(0x3CE, VgaReadPort, VgaWritePort);   // VGA_GC_INDEX
+    RegisterIoPort(0x3CF, VgaReadPort, VgaWritePort);   // VGA_GC_DATA
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID VgaCleanup(VOID)
+{
+    if (ScreenMode == GRAPHICS_MODE)
+    {
+        /* Leave the current graphics mode */
+        VgaLeaveGraphicsMode();
+    }
+    else
+    {
+        /* Leave the current text mode */
+        VgaLeaveTextMode();
+    }
+
+    VgaDetachFromConsole(FALSE);
+
+    CloseHandle(AnotherEvent);
+    CloseHandle(EndEvent);
+    CloseHandle(StartEvent);
+
+#if 0
+    RegisterConsoleVDM = NULL;
+    FreeLibrary(hKernel32);
+#endif
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/hardware/vga.h b/subsystems/ntvdm/hardware/vga.h
new file mode 100644 (file)
index 0000000..ca6de8d
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vga.h
+ * PURPOSE:         VGA hardware emulation
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _VGA_H_
+#define _VGA_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+#define VGA_NUM_BANKS 4
+#define VGA_BANK_SIZE 0x10000
+#define VGA_MAX_COLORS 256
+#define VGA_PALETTE_SIZE (VGA_MAX_COLORS * 3)
+#define VGA_BITMAP_INFO_SIZE (sizeof(BITMAPINFOHEADER) + 2 * (VGA_PALETTE_SIZE / 3))
+#define VGA_MINIMUM_WIDTH 400
+#define VGA_MINIMUM_HEIGHT 300
+#define VGA_DAC_TO_COLOR(x) (((x) << 2) | ((x) >> 4))
+#define VGA_COLOR_TO_DAC(x) ((x) >> 2)
+#define VGA_INTERLACE_HIGH_BIT (1 << 13)
+
+
+/* Register I/O ports */
+
+#define VGA_MISC_READ       0x3CC
+#define VGA_MISC_WRITE      0x3C2
+
+#define VGA_INSTAT0_READ    0x3C2
+
+#define VGA_INSTAT1_READ_MONO   0x3BA
+#define VGA_INSTAT1_READ_COLOR  0x3DA
+
+#define VGA_FEATURE_READ        0x3CA
+#define VGA_FEATURE_WRITE_MONO  0x3BA
+#define VGA_FEATURE_WRITE_COLOR 0x3DA
+
+#define VGA_AC_INDEX        0x3C0
+#define VGA_AC_WRITE        0x3C0
+#define VGA_AC_READ         0x3C1
+
+#define VGA_SEQ_INDEX       0x3C4
+#define VGA_SEQ_DATA        0x3C5
+
+#define VGA_DAC_MASK        0x3C6
+#define VGA_DAC_READ_INDEX  0x3C7
+#define VGA_DAC_WRITE_INDEX 0x3C8
+#define VGA_DAC_DATA        0x3C9
+
+#define VGA_CRTC_INDEX_MONO     0x3B4
+#define VGA_CRTC_DATA_MONO      0x3B5
+#define VGA_CRTC_INDEX_COLOR    0x3D4
+#define VGA_CRTC_DATA_COLOR     0x3D5
+
+#define VGA_GC_INDEX        0x3CE
+#define VGA_GC_DATA         0x3CF
+
+
+
+//
+// Miscellaneous and Status Registers
+//
+
+/* Miscellaneous register bits */
+#define VGA_MISC_COLOR          (1 << 0)
+#define VGA_MISC_RAM_ENABLED    (1 << 1)
+// #define VGA_MISC_CSEL1         (1 << 2)
+// #define VGA_MISC_CSEL2         (1 << 3)
+#define VGA_MISC_OE_INVERT      (1 << 5)
+#define VGA_MISC_HSYNCP         (1 << 6)
+#define VGA_MISC_VSYNCP         (1 << 7)
+
+/* Status register flags */
+#define VGA_STAT_DD             (1 << 0)
+#define VGA_STAT_VRETRACE       (1 << 3)
+
+
+//
+// Sequencer Registers
+//
+
+/* Sequencer reset register bits */
+#define VGA_SEQ_RESET_AR    (1 << 0)
+#define VGA_SEQ_RESET_SR    (1 << 1)
+
+/* Sequencer clock register bits */
+#define VGA_SEQ_CLOCK_98DM  (1 << 0)
+#define VGA_SEQ_CLOCK_SLR   (1 << 2)
+#define VGA_SEQ_CLOCK_DCR   (1 << 3)
+#define VGA_SEQ_CLOCK_S4    (1 << 4)
+#define VGA_SEQ_CLOCK_SD    (1 << 5)
+
+/* Sequencer memory register bits */
+#define VGA_SEQ_MEM_EXT     (1 << 1)
+#define VGA_SEQ_MEM_OE      (1 << 2)
+#define VGA_SEQ_MEM_C4      (1 << 3)
+
+enum
+{
+    VGA_SEQ_RESET_REG,
+    VGA_SEQ_CLOCK_REG,
+    VGA_SEQ_MASK_REG,
+    VGA_SEQ_CHAR_REG,
+    VGA_SEQ_MEM_REG,
+    VGA_SEQ_MAX_REG
+};
+
+
+//
+// CRT Controller Registers
+//
+
+/* CRTC overflow register bits */
+#define VGA_CRTC_OVERFLOW_VT8       (1 << 0)
+#define VGA_CRTC_OVERFLOW_VDE8      (1 << 1)
+#define VGA_CRTC_OVERFLOW_VRS8      (1 << 2)
+#define VGA_CRTC_OVERFLOW_SVB8      (1 << 3)
+#define VGA_CRTC_OVERFLOW_LC8       (1 << 4)
+#define VGA_CRTC_OVERFLOW_VT9       (1 << 5)
+#define VGA_CRTC_OVERFLOW_VDE9      (1 << 6)
+#define VGA_CRTC_OVERFLOW_VRS9      (1 << 7)
+
+/* CRTC underline register bits */
+#define VGA_CRTC_UNDERLINE_DWORD    (1 << 6)
+
+/* CRTC max scanline register bits */
+#define VGA_CRTC_MAXSCANLINE_DOUBLE (1 << 7)
+
+/* CRTC mode control register bits */
+#define VGA_CRTC_MODE_CONTROL_WRAP  (1 << 5)
+#define VGA_CRTC_MODE_CONTROL_BYTE  (1 << 6)
+#define VGA_CRTC_MODE_CONTROL_SYNC  (1 << 7)
+
+enum
+{
+    VGA_CRTC_HORZ_TOTAL_REG,
+    VGA_CRTC_END_HORZ_DISP_REG,
+    VGA_CRTC_START_HORZ_BLANKING_REG,
+    VGA_CRTC_END_HORZ_BLANKING_REG,
+    VGA_CRTC_START_HORZ_RETRACE_REG,
+    VGA_CRTC_END_HORZ_RETRACE_REG,
+    VGA_CRTC_VERT_TOTAL_REG,
+    VGA_CRTC_OVERFLOW_REG,
+    VGA_CRTC_PRESET_ROW_SCAN_REG,
+    VGA_CRTC_MAX_SCAN_LINE_REG,
+    VGA_CRTC_CURSOR_START_REG,
+    VGA_CRTC_CURSOR_END_REG,
+    VGA_CRTC_START_ADDR_HIGH_REG,
+    VGA_CRTC_START_ADDR_LOW_REG,
+    VGA_CRTC_CURSOR_LOC_HIGH_REG,
+    VGA_CRTC_CURSOR_LOC_LOW_REG,
+    VGA_CRTC_VERT_RETRACE_START_REG,
+    VGA_CRTC_VERT_RETRACE_END_REG,
+    VGA_CRTC_VERT_DISP_END_REG,
+    VGA_CRTC_OFFSET_REG,
+    VGA_CRTC_UNDERLINE_REG,
+    VGA_CRTC_START_VERT_BLANKING_REG,
+    VGA_CRTC_END_VERT_BLANKING,
+    VGA_CRTC_MODE_CONTROL_REG,
+    VGA_CRTC_LINE_COMPARE_REG,
+    VGA_CRTC_MAX_REG
+};
+
+
+//
+// Graphics Controller Registers
+//
+
+/* Graphics controller mode register bits */
+#define VGA_GC_MODE_READ        (1 << 3)
+#define VGA_GC_MODE_OE          (1 << 4)
+#define VGA_GC_MODE_SHIFTREG    (1 << 5)
+#define VGA_GC_MODE_SHIFT256    (1 << 6)
+
+/* Graphics controller miscellaneous register bits */
+#define VGA_GC_MISC_NOALPHA     (1 << 0)
+#define VGA_GC_MISC_OE          (1 << 1)
+
+enum
+{
+    VGA_GC_RESET_REG,
+    VGA_GC_ENABLE_RESET_REG,
+    VGA_GC_COLOR_COMPARE_REG,
+    VGA_GC_ROTATE_REG,
+    VGA_GC_READ_MAP_SEL_REG,
+    VGA_GC_MODE_REG,
+    VGA_GC_MISC_REG,
+    VGA_GC_COLOR_IGNORE_REG,
+    VGA_GC_BITMASK_REG,
+    VGA_GC_MAX_REG
+};
+
+
+//
+// Attribute Controller Registers
+// They are a relinquish of the CGA/EGA era.
+//
+
+/* AC mode control register bits */
+#define VGA_AC_CONTROL_ATGE     (1 << 0)
+#define VGA_AC_CONTROL_MONO     (1 << 1)
+#define VGA_AC_CONTROL_LGE      (1 << 2)
+#define VGA_AC_CONTROL_BLINK    (1 << 3)
+#define VGA_AC_CONTROL_PPM      (1 << 5)
+#define VGA_AC_CONTROL_8BIT     (1 << 6)
+#define VGA_AC_CONTROL_P54S     (1 << 7)
+
+enum
+{
+    VGA_AC_PAL_0_REG,
+    VGA_AC_PAL_1_REG,
+    VGA_AC_PAL_2_REG,
+    VGA_AC_PAL_3_REG,
+    VGA_AC_PAL_4_REG,
+    VGA_AC_PAL_5_REG,
+    VGA_AC_PAL_6_REG,
+    VGA_AC_PAL_7_REG,
+    VGA_AC_PAL_8_REG,
+    VGA_AC_PAL_9_REG,
+    VGA_AC_PAL_A_REG,
+    VGA_AC_PAL_B_REG,
+    VGA_AC_PAL_C_REG,
+    VGA_AC_PAL_D_REG,
+    VGA_AC_PAL_E_REG,
+    VGA_AC_PAL_F_REG,
+    VGA_AC_CONTROL_REG,
+    VGA_AC_OVERSCAN_REG,
+    VGA_AC_COLOR_PLANE_REG,
+    VGA_AC_HORZ_PANNING_REG,
+    VGA_AC_COLOR_SEL_REG,
+    VGA_AC_MAX_REG
+};
+
+
+typedef struct _VGA_REGISTERS
+{
+    UCHAR Misc;
+    UCHAR Sequencer[VGA_SEQ_MAX_REG];
+    UCHAR CRT[VGA_CRTC_MAX_REG];
+    UCHAR Graphics[VGA_GC_MAX_REG];
+    UCHAR Attribute[VGA_AC_MAX_REG];
+} VGA_REGISTERS, *PVGA_REGISTERS;
+
+
+/* FUNCTIONS ******************************************************************/
+
+BOOL VgaAttachToConsole(VOID);
+VOID VgaDetachFromConsole(BOOL ChangeMode);
+
+DWORD VgaGetVideoBaseAddress(VOID);
+DWORD VgaGetVideoLimitAddress(VOID);
+COORD VgaGetDisplayResolution(VOID);
+VOID VgaRefreshDisplay(VOID);
+VOID VgaHorizontalRetrace(VOID);
+VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
+VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
+VOID VgaClearMemory(VOID);
+
+BOOLEAN VgaInitialize(HANDLE TextHandle);
+VOID VgaCleanup(VOID);
+
+#endif // _VGA_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/int32.c b/subsystems/ntvdm/int32.c
new file mode 100644 (file)
index 0000000..e139c85
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            int32.c
+ * PURPOSE:         32-bit Interrupt Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+// #define NDEBUG
+
+#include "emulator.h"
+#include "int32.h"
+
+#include "bop.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/*
+ * This is the list of registered 32-bit Interrupt handlers.
+ */
+EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
+
+/* BOP Identifiers */
+#define BOP_CONTROL             0xFF    // Control BOP Handler
+    #define BOP_CONTROL_DEFFUNC 0x00    // Default Control BOP Function
+
+/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
+#define BOP_CONTROL_INT32       0xFF
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID WINAPI Int32Dispatch(LPWORD Stack)
+{
+    /* Get the interrupt number */
+    BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
+
+    /* Call the 32-bit Interrupt handler */
+    if (Int32Proc[IntNum] != NULL)
+        Int32Proc[IntNum](Stack);
+    else
+        DPRINT("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX());
+}
+
+VOID WINAPI ControlBop(LPWORD Stack)
+{
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    if (FuncNum == BOP_CONTROL_INT32)
+        Int32Dispatch(Stack);
+    else
+        DPRINT("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
+}
+
+VOID InitializeInt32(WORD BiosSegment)
+{
+    //
+    // WARNING WARNING!!
+    //
+    // If you modify the code stubs here, think also
+    // about updating them in callback.c too!!
+    //
+
+    LPDWORD IntVecTable = (LPDWORD)BaseAddress;
+    LPBYTE  BiosCode    = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
+    USHORT i;
+    WORD BopSeqOffset, Offset = 0;
+
+    /* Generate ISR stubs and fill the IVT */
+    for (i = 0x00; i <= 0xFF; i++)
+    {
+        Offset = INT_HANDLER_OFFSET + (i << 4);
+        IntVecTable[i] = MAKELONG(Offset, BiosSegment);
+
+        BiosCode[Offset++] = 0xFA; // cli
+
+        BiosCode[Offset++] = 0x6A; // push i
+        BiosCode[Offset++] = (UCHAR)i;
+
+        BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3);
+
+        BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ
+        BiosCode[Offset++] = LOBYTE(BopSeqOffset);
+        BiosCode[Offset++] = HIBYTE(BopSeqOffset);
+    }
+
+    /* Write the common stub code */
+    Offset = COMMON_STUB_OFFSET;
+
+// BOP_SEQ:
+    BiosCode[Offset++] = 0xF8; // clc
+
+    BiosCode[Offset++] = LOBYTE(EMULATOR_BOP);  // BOP sequence
+    BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
+    BiosCode[Offset++] = BOP_CONTROL;           // Control BOP
+    BiosCode[Offset++] = BOP_CONTROL_INT32;     // 32-bit Interrupt dispatcher
+
+    BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4)
+    BiosCode[Offset++] = 0x04;
+
+    BiosCode[Offset++] = 0xFB; // sti
+
+    // HACK: The following instruction should be HLT!
+    BiosCode[Offset++] = 0x90; // nop
+
+    BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11)
+    BiosCode[Offset++] = 0xF5;
+
+// EXIT:
+    BiosCode[Offset++] = 0x44; // inc sp
+    BiosCode[Offset++] = 0x44; // inc sp
+
+    BiosCode[Offset++] = 0xCF; // iret
+
+    /* Register the Control BOP */
+    RegisterBop(BOP_CONTROL, ControlBop);
+}
+
+VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
+{
+    Int32Proc[IntNumber] = IntHandler;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/int32.h b/subsystems/ntvdm/int32.h
new file mode 100644 (file)
index 0000000..d6cced2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            int32.h
+ * PURPOSE:         32-bit Interrupt Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _INT32_H_
+#define _INT32_H_
+
+/* DEFINES ********************************************************************/
+
+/* 32-bit Interrupt Identifiers */
+#define EMULATOR_MAX_INT32_NUM  0xFF + 1
+
+#define INT_HANDLER_OFFSET 0x1000
+#define COMMON_STUB_OFFSET 0x2000
+
+/* FUNCTIONS ******************************************************************/
+
+typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
+
+VOID WINAPI Int32Dispatch(LPWORD Stack);
+VOID InitializeInt32(WORD BiosSegment);
+VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
+
+#endif // _INT32_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/io.c b/subsystems/ntvdm/io.c
new file mode 100644 (file)
index 0000000..9a85a11
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            io.c
+ * PURPOSE:         I/O Port Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "io.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+typedef struct _EMULATOR_IO_HANDLERS
+{
+    EMULATOR_INB_PROC   InB;
+    EMULATOR_INW_PROC   InW;
+    EMULATOR_IND_PROC   InD;
+
+    EMULATOR_INSB_PROC  InsB;
+    EMULATOR_INSW_PROC  InsW;
+    EMULATOR_INSD_PROC  InsD;
+
+    EMULATOR_OUTB_PROC  OutB;
+    EMULATOR_OUTW_PROC  OutW;
+    EMULATOR_OUTD_PROC  OutD;
+
+    EMULATOR_OUTSB_PROC OutsB;
+    EMULATOR_OUTSW_PROC OutsW;
+    EMULATOR_OUTSD_PROC OutsD;
+} EMULATOR_IO_HANDLERS, *PEMULATOR_IO_HANDLERS;
+
+typedef struct _EMULATOR_IOPORT_HANDLERS
+{
+    HANDLE hVdd; // == 0 if unused,
+                 //    INVALID_HANDLE_VALUE if handled internally,
+                 //    a valid VDD handle   if handled externally.
+    union
+    {
+        /* For Windows compatibility only, not used internally... */
+        VDD_IO_HANDLERS VddIoHandlers;
+
+        /* ... we use these members internally */
+        EMULATOR_IO_HANDLERS IoHandlers;
+    };
+} EMULATOR_IOPORT_HANDLERS, *PEMULATOR_IOPORT_HANDLERS;
+
+/*
+ * This is the list of registered I/O Port handlers.
+ */
+EMULATOR_IOPORT_HANDLERS IoPortProc[EMULATOR_MAX_IOPORTS_NUM] = {{NULL}};
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+UCHAR
+IOReadB(ULONG Port)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InB)
+    {
+        return IoPortProc[Port].IoHandlers.InB(Port);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.inb_handler)
+    {
+        UCHAR Data;
+        ASSERT(Port <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.inb_handler((WORD)Port, &Data);
+        return Data;
+    }
+    else
+    {
+        /* Return an empty port byte value */
+        DPRINT("Read from unknown port: 0x%X\n", Port);
+        return 0xFF;
+    }
+}
+
+VOID
+IOReadStrB(ULONG  Port,
+           PUCHAR Buffer,
+           ULONG  Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InsB)
+    {
+        IoPortProc[Port].IoHandlers.InsB(Port, Buffer, Count);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.insb_handler)
+    {
+        ASSERT(Port  <= MAXWORD);
+        ASSERT(Count <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.insb_handler((WORD)Port, Buffer, (WORD)Count);
+    }
+    else
+    {
+        while (Count--)
+            *Buffer++ = IOReadB(Port);
+    }
+}
+
+VOID
+IOWriteB(ULONG Port,
+         UCHAR Buffer)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutB)
+    {
+        IoPortProc[Port].IoHandlers.OutB(Port, Buffer);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.outb_handler)
+    {
+        ASSERT(Port <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.outb_handler((WORD)Port, Buffer);
+    }
+    else
+    {
+        /* Do nothing */
+        DPRINT("Write to unknown port: 0x%X\n", Port);
+    }
+}
+
+VOID
+IOWriteStrB(ULONG  Port,
+            PUCHAR Buffer,
+            ULONG  Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutsB)
+    {
+        IoPortProc[Port].IoHandlers.OutsB(Port, Buffer, Count);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.outsb_handler)
+    {
+        ASSERT(Port  <= MAXWORD);
+        ASSERT(Count <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.outsb_handler((WORD)Port, Buffer, (WORD)Count);
+    }
+    else
+    {
+        while (Count--) IOWriteB(Port, *Buffer++);
+    }
+}
+
+USHORT
+IOReadW(ULONG Port)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InW)
+    {
+        return IoPortProc[Port].IoHandlers.InW(Port);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.inw_handler)
+    {
+        USHORT Data;
+        ASSERT(Port <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.inw_handler((WORD)Port, &Data);
+        return Data;
+    }
+    else
+    {
+        UCHAR Low, High;
+
+        // FIXME: Is it ok on Little endian and Big endian ??
+        Low  = IOReadB(Port);
+        High = IOReadB(Port + sizeof(UCHAR));
+        return MAKEWORD(Low, High);
+    }
+}
+
+VOID
+IOReadStrW(ULONG   Port,
+           PUSHORT Buffer,
+           ULONG   Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InsW)
+    {
+        IoPortProc[Port].IoHandlers.InsW(Port, Buffer, Count);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.insw_handler)
+    {
+        ASSERT(Port  <= MAXWORD);
+        ASSERT(Count <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.insw_handler((WORD)Port, Buffer, (WORD)Count);
+    }
+    else
+    {
+        while (Count--)
+            *Buffer++ = IOReadW(Port);
+    }
+}
+
+VOID
+IOWriteW(ULONG  Port,
+         USHORT Buffer)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutW)
+    {
+        IoPortProc[Port].IoHandlers.OutW(Port, Buffer);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.outw_handler)
+    {
+        ASSERT(Port <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.outw_handler((WORD)Port, Buffer);
+    }
+    else
+    {
+        // FIXME: Is it ok on Little endian and Big endian ??
+        IOWriteB(Port, LOBYTE(Buffer));
+        IOWriteB(Port + sizeof(UCHAR), HIBYTE(Buffer));
+    }
+}
+
+VOID
+IOWriteStrW(ULONG   Port,
+            PUSHORT Buffer,
+            ULONG   Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutsW)
+    {
+        IoPortProc[Port].IoHandlers.OutsW(Port, Buffer, Count);
+    }
+    else if (IoPortProc[Port].hVdd > 0 &&
+             IoPortProc[Port].VddIoHandlers.outsw_handler)
+    {
+        ASSERT(Port  <= MAXWORD);
+        ASSERT(Count <= MAXWORD);
+        IoPortProc[Port].VddIoHandlers.outsw_handler((WORD)Port, Buffer, (WORD)Count);
+    }
+    else
+    {
+        while (Count--) IOWriteW(Port, *Buffer++);
+    }
+}
+
+ULONG
+IOReadD(ULONG Port)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InD)
+    {
+        return IoPortProc[Port].IoHandlers.InD(Port);
+    }
+    else
+    {
+        USHORT Low, High;
+
+        // FIXME: Is it ok on Little endian and Big endian ??
+        Low  = IOReadW(Port);
+        High = IOReadW(Port + sizeof(USHORT));
+        return MAKELONG(Low, High);
+    }
+}
+
+VOID
+IOReadStrD(ULONG  Port,
+           PULONG Buffer,
+           ULONG  Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.InsD)
+    {
+        IoPortProc[Port].IoHandlers.InsD(Port, Buffer, Count);
+    }
+    else
+    {
+        while (Count--)
+            *Buffer++ = IOReadD(Port);
+    }
+}
+
+VOID
+IOWriteD(ULONG Port,
+         ULONG Buffer)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutD)
+    {
+        IoPortProc[Port].IoHandlers.OutD(Port, Buffer);
+    }
+    else
+    {
+        // FIXME: Is it ok on Little endian and Big endian ??
+        IOWriteW(Port, LOWORD(Buffer));
+        IOWriteW(Port + sizeof(USHORT), HIWORD(Buffer));
+    }
+}
+
+VOID
+IOWriteStrD(ULONG  Port,
+            PULONG Buffer,
+            ULONG  Count)
+{
+    if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE &&
+        IoPortProc[Port].IoHandlers.OutsD)
+    {
+        IoPortProc[Port].IoHandlers.OutsD(Port, Buffer, Count);
+    }
+    else
+    {
+        while (Count--) IOWriteD(Port, *Buffer++);
+    }
+}
+
+
+VOID RegisterIoPort(ULONG Port,
+                    EMULATOR_INB_PROC  InHandler,
+                    EMULATOR_OUTB_PROC OutHandler)
+{
+    if (IoPortProc[Port].IoHandlers.InB == NULL)
+        IoPortProc[Port].IoHandlers.InB = InHandler;
+    else
+        DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port);
+
+    if (IoPortProc[Port].IoHandlers.OutB == NULL)
+        IoPortProc[Port].IoHandlers.OutB = OutHandler;
+    else
+        DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port);
+
+    /* We hold the I/O port internally */
+    IoPortProc[Port].hVdd = INVALID_HANDLE_VALUE;
+}
+
+VOID UnregisterIoPort(ULONG Port)
+{
+    /*
+     * Put automagically all the fields to zero:
+     * the hVdd gets unregistered as well as all the handlers.
+     */
+    // IoPortProc[Port] = {NULL};
+    ZeroMemory(&IoPortProc[Port], sizeof(IoPortProc[Port]));
+}
+
+VOID WINAPI
+EmulatorReadIo(PFAST486_STATE State,
+               ULONG Port,
+               PVOID Buffer,
+               ULONG DataCount,
+               UCHAR DataSize)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    if (DataSize == 0 || DataCount == 0) return;
+
+    if (DataSize == sizeof(UCHAR))
+    {
+        if (DataCount == 1)
+            *(PUCHAR)Buffer = IOReadB(Port);
+        else
+            IOReadStrB(Port, Buffer, DataCount);
+    }
+    else if (DataSize == sizeof(USHORT))
+    {
+        if (DataCount == 1)
+            *(PUSHORT)Buffer = IOReadW(Port);
+        else
+            IOReadStrW(Port, Buffer, DataCount);
+    }
+    else if (DataSize == sizeof(ULONG))
+    {
+        if (DataCount == 1)
+            *(PULONG)Buffer = IOReadD(Port);
+        else
+            IOReadStrD(Port, Buffer, DataCount);
+    }
+    else
+    {
+        PBYTE Address = (PBYTE)Buffer;
+
+        while (DataCount--)
+        {
+            ULONG CurrentPort = Port;
+            ULONG Count;
+            UCHAR NewDataSize = DataSize;
+
+            /* Read dword */
+            Count       = NewDataSize / sizeof(ULONG);
+            NewDataSize = NewDataSize % sizeof(ULONG);
+            while (Count--)
+            {
+                *(PULONG)Address = IOReadD(CurrentPort);
+                CurrentPort += sizeof(ULONG);
+                Address     += sizeof(ULONG);
+            }
+
+            /* Read word */
+            Count       = NewDataSize / sizeof(USHORT);
+            NewDataSize = NewDataSize % sizeof(USHORT);
+            while (Count--)
+            {
+                *(PUSHORT)Address = IOReadW(CurrentPort);
+                CurrentPort += sizeof(USHORT);
+                Address     += sizeof(USHORT);
+            }
+
+            /* Read byte */
+            Count       = NewDataSize / sizeof(UCHAR);
+            NewDataSize = NewDataSize % sizeof(UCHAR);
+            while (Count--)
+            {
+                *(PUCHAR)Address = IOReadB(CurrentPort);
+                CurrentPort += sizeof(UCHAR);
+                Address     += sizeof(UCHAR);
+            }
+
+            ASSERT(Count == 0);
+            ASSERT(NewDataSize == 0);
+        }
+    }
+}
+
+VOID WINAPI
+EmulatorWriteIo(PFAST486_STATE State,
+                ULONG Port,
+                PVOID Buffer,
+                ULONG DataCount,
+                UCHAR DataSize)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    if (DataSize == 0 || DataCount == 0) return;
+
+    if (DataSize == sizeof(UCHAR))
+    {
+        if (DataCount == 1)
+            IOWriteB(Port, *(PUCHAR)Buffer);
+        else
+            IOWriteStrB(Port, Buffer, DataCount);
+    }
+    else if (DataSize == sizeof(USHORT))
+    {
+        if (DataCount == 1)
+            IOWriteW(Port, *(PUSHORT)Buffer);
+        else
+            IOWriteStrW(Port, Buffer, DataCount);
+    }
+    else if (DataSize == sizeof(ULONG))
+    {
+        if (DataCount == 1)
+            IOWriteD(Port, *(PULONG)Buffer);
+        else
+            IOWriteStrD(Port, Buffer, DataCount);
+    }
+    else
+    {
+        PBYTE Address = (PBYTE)Buffer;
+
+        while (DataCount--)
+        {
+            ULONG CurrentPort = Port;
+            ULONG Count;
+            UCHAR NewDataSize = DataSize;
+
+            /* Write dword */
+            Count       = NewDataSize / sizeof(ULONG);
+            NewDataSize = NewDataSize % sizeof(ULONG);
+            while (Count--)
+            {
+                IOWriteD(CurrentPort, *(PULONG)Address);
+                CurrentPort += sizeof(ULONG);
+                Address     += sizeof(ULONG);
+            }
+
+            /* Write word */
+            Count       = NewDataSize / sizeof(USHORT);
+            NewDataSize = NewDataSize % sizeof(USHORT);
+            while (Count--)
+            {
+                IOWriteW(CurrentPort, *(PUSHORT)Address);
+                CurrentPort += sizeof(USHORT);
+                Address     += sizeof(USHORT);
+            }
+
+            /* Write byte */
+            Count       = NewDataSize / sizeof(UCHAR);
+            NewDataSize = NewDataSize % sizeof(UCHAR);
+            while (Count--)
+            {
+                IOWriteB(CurrentPort, *(PUCHAR)Address);
+                CurrentPort += sizeof(UCHAR);
+                Address     += sizeof(UCHAR);
+            }
+
+            ASSERT(Count == 0);
+            ASSERT(NewDataSize == 0);
+        }
+    }
+}
+
+
+
+BOOL
+WINAPI
+VDDInstallIOHook(HANDLE            hVdd,
+                 WORD              cPortRange,
+                 PVDD_IO_PORTRANGE pPortRange,
+                 PVDD_IO_HANDLERS  IOhandler)
+{
+    /* Check possible validity of the VDD handle */
+    if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return FALSE;
+
+    /* Loop for each range of I/O ports */
+    while (cPortRange--)
+    {
+        WORD i;
+
+        /* Register the range of I/O ports */
+        for (i = pPortRange->First; i <= pPortRange->Last; ++i)
+        {
+            /*
+             * Don't do anything if the I/O port is already
+             * handled internally or externally.
+             */
+            if (IoPortProc[i].hVdd != 0)
+            {
+                DPRINT1("IoPortProc[0x%X] already registered\n", i);
+                continue;
+            }
+
+            /* Register wrt. the VDD */
+            IoPortProc[i].hVdd = hVdd;
+
+            /* Disable the internal handlers */
+            IoPortProc[i].IoHandlers.InB = NULL;
+            IoPortProc[i].IoHandlers.InW = NULL;
+            IoPortProc[i].IoHandlers.InD = NULL;
+
+            IoPortProc[i].IoHandlers.InsB = NULL;
+            IoPortProc[i].IoHandlers.InsW = NULL;
+            IoPortProc[i].IoHandlers.InsD = NULL;
+
+            IoPortProc[i].IoHandlers.OutB = NULL;
+            IoPortProc[i].IoHandlers.OutW = NULL;
+            IoPortProc[i].IoHandlers.OutD = NULL;
+
+            IoPortProc[i].IoHandlers.OutsB = NULL;
+            IoPortProc[i].IoHandlers.OutsW = NULL;
+            IoPortProc[i].IoHandlers.OutsD = NULL;
+
+            /* Save our handlers */
+            IoPortProc[i].VddIoHandlers = *IOhandler;
+        }
+
+        /* Go to the next range */
+        ++pPortRange;
+        ++IOhandler;
+    }
+
+    return TRUE;
+}
+
+VOID
+WINAPI
+VDDDeInstallIOHook(HANDLE            hVdd,
+                   WORD              cPortRange,
+                   PVDD_IO_PORTRANGE pPortRange)
+{
+    /* Check possible validity of the VDD handle */
+    if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return;
+
+    /* Loop for each range of I/O ports */
+    while (cPortRange--)
+    {
+        WORD i;
+
+        /* Unregister the range of I/O ports */
+        for (i = pPortRange->First; i <= pPortRange->Last; ++i)
+        {
+            /*
+             * Don't do anything if we don't own the I/O port.
+             */
+            if (IoPortProc[i].hVdd != hVdd)
+            {
+                DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i);
+                continue;
+            }
+
+            /*
+             * Put automagically all the fields to zero:
+             * the hVdd gets unregistered as well as all the handlers.
+             */
+            // IoPortProc[i] = {NULL};
+            ZeroMemory(&IoPortProc[i], sizeof(IoPortProc[i]));
+        }
+
+        /* Go to the next range */
+        ++pPortRange;
+    }
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/io.h b/subsystems/ntvdm/io.h
new file mode 100644 (file)
index 0000000..9ed80ec
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            io.c
+ * PURPOSE:         I/O Port Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _IO_H_
+#define _IO_H_
+
+/* DEFINES ********************************************************************/
+
+#define EMULATOR_MAX_IOPORTS_NUM    0x10000
+
+/* FUNCTIONS ******************************************************************/
+
+typedef UCHAR  (WINAPI *EMULATOR_INB_PROC)(ULONG Port);
+typedef USHORT (WINAPI *EMULATOR_INW_PROC)(ULONG Port);
+typedef ULONG  (WINAPI *EMULATOR_IND_PROC)(ULONG Port);
+
+typedef VOID (WINAPI *EMULATOR_INSB_PROC)(ULONG Port, PUCHAR  Buffer, ULONG Count);
+typedef VOID (WINAPI *EMULATOR_INSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count);
+typedef VOID (WINAPI *EMULATOR_INSD_PROC)(ULONG Port, PULONG  Buffer, ULONG Count);
+
+typedef VOID (WINAPI *EMULATOR_OUTB_PROC)(ULONG Port, UCHAR  Data);
+typedef VOID (WINAPI *EMULATOR_OUTW_PROC)(ULONG Port, USHORT Data);
+typedef VOID (WINAPI *EMULATOR_OUTD_PROC)(ULONG Port, ULONG  Data);
+
+typedef VOID (WINAPI *EMULATOR_OUTSB_PROC)(ULONG Port, PUCHAR  Buffer, ULONG Count);
+typedef VOID (WINAPI *EMULATOR_OUTSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count);
+typedef VOID (WINAPI *EMULATOR_OUTSD_PROC)(ULONG Port, PULONG  Buffer, ULONG Count);
+
+
+UCHAR
+IOReadB(ULONG Port);
+VOID
+IOReadStrB(ULONG  Port,
+           PUCHAR Buffer,
+           ULONG  Count);
+
+VOID
+IOWriteB(ULONG Port,
+         UCHAR Buffer);
+VOID
+IOWriteStrB(ULONG  Port,
+            PUCHAR Buffer,
+            ULONG  Count);
+
+USHORT
+IOReadW(ULONG Port);
+VOID
+IOReadStrW(ULONG   Port,
+           PUSHORT Buffer,
+           ULONG   Count);
+
+VOID
+IOWriteW(ULONG  Port,
+         USHORT Buffer);
+VOID
+IOWriteStrW(ULONG   Port,
+            PUSHORT Buffer,
+            ULONG   Count);
+
+ULONG
+IOReadD(ULONG Port);
+VOID
+IOReadStrD(ULONG  Port,
+           PULONG Buffer,
+           ULONG  Count);
+
+VOID
+IOWriteD(ULONG Port,
+         ULONG Buffer);
+VOID
+IOWriteStrD(ULONG  Port,
+            PULONG Buffer,
+            ULONG  Count);
+
+
+VOID RegisterIoPort(ULONG Port,
+                    EMULATOR_INB_PROC  InHandler,
+                    EMULATOR_OUTB_PROC OutHandler);
+
+VOID UnregisterIoPort(ULONG Port);
+
+VOID WINAPI EmulatorReadIo
+(
+    PFAST486_STATE State,
+    ULONG Port,
+    PVOID Buffer,
+    ULONG DataCount,
+    UCHAR DataSize
+);
+
+VOID WINAPI EmulatorWriteIo
+(
+    PFAST486_STATE State,
+    ULONG Port,
+    PVOID Buffer,
+    ULONG DataCount,
+    UCHAR DataSize
+);
+
+#endif // _IO_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/lang/bg-BG.rc b/subsystems/ntvdm/lang/bg-BG.rc
deleted file mode 100644 (file)
index aea51c6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Поддръжка на РеактОС за привидна ДОС машина.\n"
-    STRING_PromptMsg "Напишете r<cr> за пускане, s<cr> за спиране или q<cr> за изход."
-END
index e4dd3a5..b620634 100644 (file)
@@ -1,12 +1,19 @@
-/* FILE:       subsystems/ntvdm/lang/cs-CZ.rc
+/*
+ * FILE:       subsystems/ntvdm/lang/cs-CZ.rc
  * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
- * UPDATED:    2008-06-24
+ * UPDATED:    2014-02-01
  */
-
 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "ReactOS podpora virtuálního DOS stroje.\n"
-    STRING_PromptMsg "Napište r<cr> pro spuštìní, s<cr> pro vypnutí nebo q<cr> pro ukonèení."
+    IDS_HIDE_MOUSE, "&Skrýt ukazatel myši"
+    IDS_SHOW_MOUSE, "&Zobrazit ukazatel myši"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Ukončit ReactOS VDM"
 END
index e8007f8..1f56de3 100644 (file)
@@ -1,13 +1,13 @@
-/*
- * German translate
- * By Rouven Wessling 2005 pentiumforever@gmail.com
- *                    2008 dark_shadow@gmx.at
- */
-
 LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "ReactOS virtuelle DOS-Unterstützung.\n"
-    STRING_PromptMsg "Drücken Sie r<cr> zum Starten, s<cr> zum Herunterfahren oder q<cr> zum Beenden."
+    IDS_HIDE_MOUSE, "Mauszeiger &verstecken"
+    IDS_SHOW_MOUSE, "Mauszeiger &anzeigen"
+    IDS_VDM_MENU  , "&ReactOS VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "ReactOS VDM b&eenden"
 END
index cdb7f06..4ec9d71 100644 (file)
@@ -2,6 +2,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n"
-    STRING_PromptMsg "Type r<cr> to run, s<cr> to shutdown or q<cr> to quit now."
+    IDS_HIDE_MOUSE, "&Hide Mouse Pointer"
+    IDS_SHOW_MOUSE, "&Display Mouse Pointer"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Quit the ReactOS VDM"
 END
index d5b7d15..19d0591 100644 (file)
@@ -1,9 +1,13 @@
-/* Spanish translation by Samuel Serapion */
-
 LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "Maquina virtual de DOS en ReactOS.\n"
-    STRING_PromptMsg "Escriba r<cr> para correr, s<cr> para desactivar or q<cr> para salir ahora."
+    IDS_HIDE_MOUSE, "&Ocultar puntero del ratón"
+    IDS_SHOW_MOUSE, "&Mostrar puntero del ratón"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Salir de ReactOS VDM"
 END
index 702f95a..853aa52 100644 (file)
@@ -2,6 +2,12 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "Aide de la Machine DOS Virtuel de ReactOS.\n"
-    STRING_PromptMsg "Taper r<cr> pour démarrer, s<cr> pour éteindre ou q<cr> pour quitter maintenant."
+    IDS_HIDE_MOUSE, "Mas&quer le pointeur de la souris"
+    IDS_SHOW_MOUSE, "&Afficher le pointeur de la souris"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Quitter la ReactOS VDM"
 END
diff --git a/subsystems/ntvdm/lang/hu-HU.rc b/subsystems/ntvdm/lang/hu-HU.rc
deleted file mode 100644 (file)
index c25b7fb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Hungarian translation by Robert Horvath 2005 - talley at cubeclub.hu */
-
-LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS Virtuális DOS Gép támogatás.\n"
-    STRING_PromptMsg "Futtatáshoz nyomd meg a r<cr>, leállításhoz a s<cr> vagy kilépéshez a q<cr> gombot."
-END
diff --git a/subsystems/ntvdm/lang/id-ID.rc b/subsystems/ntvdm/lang/id-ID.rc
deleted file mode 100644 (file)
index be7b06c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Dukungan ReactOS Virtual DOS Machine.\n"
-    STRING_PromptMsg "Ketik r<cr> untuk menjalankan, s<cr> untuk mematikan atau q<cr> untuk keluar sekarang."
-END
index 305c914..ff3a096 100644 (file)
@@ -1,15 +1,13 @@
-/*
-* PROJECT:    ReactOS Virtual DOS Machine
-* LICENSE:    GPL - See COPYING in the top level directory
-* FILE:       subsystems/ntvdm/it-IT.rc
-* PURPOSE:    Italian Translation of subsystems/ntvdm/en-US.rc
-* TRANSLATOR: Daniele Forsi (dforsi at gmail.com)
-*/
-
 LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "Supporto di ReactOS per la macchina virtuale DOS.\n"
-    STRING_PromptMsg "Digitare r<invio> per avviare, s<invio> per arrestare o q<invio> per abbandonare ora."
+    IDS_HIDE_MOUSE, "&Nascondi il mouse"
+    IDS_SHOW_MOUSE, "&Mostra il mouse"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Esci da ReactOS VDM"
 END
diff --git a/subsystems/ntvdm/lang/ja-JP.rc b/subsystems/ntvdm/lang/ja-JP.rc
deleted file mode 100644 (file)
index 7a5bfcf..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n"
-    STRING_PromptMsg "起動するには r<cr> を、シャットダウンするには s<cr> を、今すぐ終了させるには q<cr> を入力してください。"
-END
diff --git a/subsystems/ntvdm/lang/no-NO.rc b/subsystems/ntvdm/lang/no-NO.rc
deleted file mode 100644 (file)
index 421dcd5..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS Vituell DOS Maskin støtte.\n"
-    STRING_PromptMsg "Skriv r<cr> for å kjøre, s<cr> å avslutte eller q<cr> for å slutte nå."
-END
index 689cf0d..e23ee40 100644 (file)
@@ -1,14 +1,15 @@
-/*
- *    Translated by xrogers
- *    xxrogers@users.sourceforge.net
- *    https://sourceforge.net/projects/reactospl
- *    UTF-8 conversion by Caemyr (May, 2011) 
- */
+// Created by wojo664 - Saved in UTF-8 encoding
+
 LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
 
 STRINGTABLE
 BEGIN
-    STRING_WelcomeMsg "Wirtualna maszyna DOS dla ReactOS.\n"
-    STRING_PromptMsg "Wciśnij r<cr> aby uruchomić, s<cr> aby wyłączyć lub q<cr>, aby zakończyć."
+    IDS_HIDE_MOUSE, "&Ukryj Wskaźnik Myszki"
+    IDS_SHOW_MOUSE, "&Pokaż Wskaźnik Myszki"
+    IDS_VDM_MENU  , "ReactOS &VDM"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_VDM_QUIT,   "&Wyjdź z ReactOS VDM"
 END
diff --git a/subsystems/ntvdm/lang/pt-BR.rc b/subsystems/ntvdm/lang/pt-BR.rc
deleted file mode 100644 (file)
index 5f68fc7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS subsistema para suporte DOS de 16 bits.\n"
-    STRING_PromptMsg "Digite r<cr> para executar, s<cr> para desligar ou q<cr> para sair."
-END
diff --git a/subsystems/ntvdm/lang/ro-RO.rc b/subsystems/ntvdm/lang/ro-RO.rc
deleted file mode 100644 (file)
index d8c65c6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 
- * FILE:       subsystems/ntvdm/lang/ro-RO.rc
- *             ReactOS Project (http://www.reactos.org)
- * TRANSLATOR: Fulea Ștefan (PM on ReactOS Forum at fulea.stefan)
- * CHANGE LOG: 2011-10-16  initial translation
- */
-
-LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Asistență pentru mașina virtuală DOS.\n"
-    STRING_PromptMsg "Tastați r<cr> pentru a executa, s<cr> pentru a închide sau q<cr> pentru a ieși imediat."
-END
diff --git a/subsystems/ntvdm/lang/ru-RU.rc b/subsystems/ntvdm/lang/ru-RU.rc
deleted file mode 100644 (file)
index 5a2f3aa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Виртуальная машина поддержки DOS для ReactOS.\n"
-    STRING_PromptMsg "Введите r<cr> для запуска, s<cr> для выключения или q<cr> выхода."
-END
diff --git a/subsystems/ntvdm/lang/sk-SK.rc b/subsystems/ntvdm/lang/sk-SK.rc
deleted file mode 100644 (file)
index cf72455..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* TRANSLATOR: Mário Kaèmár /Mario Kacmar/ aka Kario (kario@szm.sk)
- * DATE OF TR: 12-02-2008
- */
-
-LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Podpora virtuálneho DOSového stroja v systéme ReactOS.\n"
-    STRING_PromptMsg "Napíšte r<cr> pre spustenie, s<cr> pre vypnutie alebo q<cr> pre okamžité skonèenie."
-END
diff --git a/subsystems/ntvdm/lang/th-TH.rc b/subsystems/ntvdm/lang/th-TH.rc
deleted file mode 100644 (file)
index acaa687..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_THAI, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "รองรับการทำงานระบบดอสเสมือนของ ReactOS\n"
-    STRING_PromptMsg "แบบ r<cr> เพื่อทำงาน, s<cr> เพื่อปิดระบบหรือ q<cr> เพื่อออกทันที"
-END
diff --git a/subsystems/ntvdm/lang/uk-UA.rc b/subsystems/ntvdm/lang/uk-UA.rc
deleted file mode 100644 (file)
index ed8fc73..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * PROJECT:    Virtual DOS Machine
- * LICENSE:    GPL - See COPYING in the top level directory
- * FILE:       subsystems/ntvdm/Uk.rc
- * PURPOSE:    Ukraianian Language File for Virtual DOS Machine
- * TRANSLATOR: Artem Reznikov
- */
-
-LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "Підтримка віртуальної машини DOS у ReactOS.\n"
-    STRING_PromptMsg "Введіть r<cr> для запуску, s<cr> для закриття або q<cr>, щоб вийти зараз."
-END
diff --git a/subsystems/ntvdm/lang/zh-CN.rc b/subsystems/ntvdm/lang/zh-CN.rc
deleted file mode 100644 (file)
index 89dbafa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS 虚拟 DOS 机支持。\n"
-    STRING_PromptMsg "输入 r<cr> 以便运行,s<cr> 以便关闭或者 q<cr> 以便立即退出。"
-END
diff --git a/subsystems/ntvdm/lang/zh-TW.rc b/subsystems/ntvdm/lang/zh-TW.rc
deleted file mode 100644 (file)
index 9a7790b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
-
-STRINGTABLE
-BEGIN
-    STRING_WelcomeMsg "ReactOS 虛擬 DOS 機支援。\n"
-    STRING_PromptMsg "鍵入 r<cr> 以便運行, s<cr> 以便關閉或者 q<cr> 以便立即退出。"
-END
index 29cf573..1239def 100644 (file)
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            subsys/ntvdm/ntvdm->c
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            ntvdm.c
  * PURPOSE:         Virtual DOS Machine
- * PROGRAMMER:      Robert Dickenson (robd@mok.lvcm.com)
- * UPDATE HISTORY:
- *                  Created 23/10/2002
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
 
-#include <stdarg.h>
-#define WIN32_NO_STATUS
-#include <windef.h>
-#include <winbase.h>
-#include <wincon.h>
-#include <winuser.h>
-#include <stdio.h>
+#define NDEBUG
+
+#include "ntvdm.h"
+#include "emulator.h"
+
+#include "clock.h"
+#include "hardware/ps2.h"
+#include "hardware/vga.h"
+#include "bios/bios.h"
+#include "dos/dem.h"
 
 #include "resource.h"
 
-#define NDEBUG
-#include <debug.h>
+/* VARIABLES ******************************************************************/
+
+static HANDLE ConsoleInput  = INVALID_HANDLE_VALUE;
+static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
+static DWORD  OrgConsoleInputMode, OrgConsoleOutputMode;
+static BOOLEAN AcceptCommands = TRUE;
+static HANDLE CommandThread = NULL;
+
+static HMENU hConsoleMenu  = NULL;
+static INT   VdmMenuPos    = -1;
+static BOOLEAN ShowPointer = FALSE;
+
+#ifndef STANDALONE
+ULONG SessionId = 0;
+#endif
 
-/* GLOBALS ******************************************************************/
+HANDLE VdmTaskEvent = NULL;
 
+/*
+ * Those menu helpers were taken from the GUI frontend in winsrv.dll
+ */
+typedef struct _VDM_MENUITEM
+{
+    UINT uID;
+    const struct _VDM_MENUITEM *SubMenu;
+    WORD wCmdID;
+} VDM_MENUITEM, *PVDM_MENUITEM;
 
-/* FUNCTIONS *****************************************************************/
+static const VDM_MENUITEM VdmMenuItems[] =
+{
+    { IDS_VDM_QUIT, NULL, ID_VDM_QUIT },
 
-void PrintString(char* fmt,...)
+    { 0, NULL, 0 }      /* End of list */
+};
+
+static const VDM_MENUITEM VdmMainMenuItems[] =
 {
-   char buffer[512];
-   va_list ap;
+    { -1, NULL, 0 },    /* Separator */
+    { IDS_HIDE_MOUSE,   NULL, ID_SHOWHIDE_MOUSE },  /* Hide mouse; can be renamed to Show mouse */
+    { IDS_VDM_MENU  ,   VdmMenuItems,         0 },  /* ReactOS VDM Menu */
 
-   va_start(ap, fmt);
-   vsprintf(buffer, fmt, ap);
-   va_end(ap);
+    { 0, NULL, 0 }      /* End of list */
+};
 
-   OutputDebugStringA(buffer);
+static VOID
+AppendMenuItems(HMENU hMenu,
+                const VDM_MENUITEM *Items)
+{
+    UINT i = 0;
+    WCHAR szMenuString[255];
+    HMENU hSubMenu;
+
+    do
+    {
+        if (Items[i].uID != (UINT)-1)
+        {
+            if (LoadStringW(GetModuleHandle(NULL),
+                            Items[i].uID,
+                            szMenuString,
+                            sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
+            {
+                if (Items[i].SubMenu != NULL)
+                {
+                    hSubMenu = CreatePopupMenu();
+                    if (hSubMenu != NULL)
+                    {
+                        AppendMenuItems(hSubMenu, Items[i].SubMenu);
+
+                        if (!AppendMenuW(hMenu,
+                                         MF_STRING | MF_POPUP,
+                                         (UINT_PTR)hSubMenu,
+                                         szMenuString))
+                        {
+                            DestroyMenu(hSubMenu);
+                        }
+                    }
+                }
+                else
+                {
+                    AppendMenuW(hMenu,
+                                MF_STRING,
+                                Items[i].wCmdID,
+                                szMenuString);
+                }
+            }
+        }
+        else
+        {
+            AppendMenuW(hMenu,
+                        MF_SEPARATOR,
+                        0,
+                        NULL);
+        }
+        i++;
+    } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
 }
 
-/*
-GetVersion
-GetVolumeInformationW
-GetWindowsDirectoryA
-GlobalMemoryStatus
-HeapAlloc
-HeapCreate
-HeapDestroy
-HeapFree
-HeapReAlloc
-
-GetNextVDMCommand
-ExitVDM
-RegisterConsoleVDM
-SetVDMCurrentDirectories
-VDMConsoleOperation
-WriteConsoleInputVDMW
-
-NtSetLdtEntries
-NtTerminateProcess
-
-NtMapViewOfSection
-NtUnmapViewOfSection
-
-NtVdmControl
- */
-typedef struct tag_VDM_CONFIG {
-    int dos_options;
-    int files;
-    int buffers;
-    WCHAR** device_list;
-//dos=high, umb
-//device=%SystemRoot%\system32\himem.sys
-//files=40
-} VDM_CONFIG, *PVDM_CONFIG;
-
-typedef struct tag_VDM_AUTOEXEC {
-    WCHAR** load_list;
-//lh %SystemRoot%\system32\mscdexnt.exe
-//lh %SystemRoot%\system32\redir
-//lh %SystemRoot%\system32\dosx
-} VDM_AUTOEXEC, *PVDM_AUTOEXEC;
-
-typedef struct tag_VDM_CONTROL_BLOCK {
-    HANDLE hHeap;
-    PVOID ImageMem;
-    VDM_CONFIG vdmConfig;
-    VDM_AUTOEXEC vdmAutoexec;
-    PROCESS_INFORMATION ProcessInformation;
-    CHAR CommandLine[MAX_PATH];
-    CHAR CurrentDirectory[MAX_PATH];
-
-} VDM_CONTROL_BLOCK, *PVDM_CONTROL_BLOCK;
-
-
-BOOL
-StartVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+CreateVdmMenu(HANDLE ConOutHandle)
 {
-   BOOL Result;
-   STARTUPINFOA StartupInfo;
-
-   StartupInfo.cb = sizeof(StartupInfo);
-   StartupInfo.lpReserved = NULL;
-   StartupInfo.lpDesktop = NULL;
-   StartupInfo.lpTitle = NULL;
-   StartupInfo.dwFlags = 0;
-   StartupInfo.cbReserved2 = 0;
-   StartupInfo.lpReserved2 = 0;
-
-   Result = CreateProcessA(vdm->CommandLine,
-                          NULL,
-                          NULL,
-                          NULL,
-                          FALSE,
-                          DETACHED_PROCESS,
-                          NULL,
-                          NULL,
-                          &StartupInfo,
-                          &vdm->ProcessInformation);
-    if (!Result) {
-        PrintString("VDM: Failed to execute target process\n");
-        return FALSE;
-    }
-    WaitForSingleObject(vdm->ProcessInformation.hProcess, INFINITE);
-    CloseHandle(vdm->ProcessInformation.hProcess);
-    CloseHandle(vdm->ProcessInformation.hThread);
-    return TRUE;
+    hConsoleMenu = ConsoleMenuControl(ConOutHandle,
+                                      ID_SHOWHIDE_MOUSE,
+                                      ID_VDM_QUIT);
+    if (hConsoleMenu == NULL) return;
+
+    VdmMenuPos = GetMenuItemCount(hConsoleMenu);
+    AppendMenuItems(hConsoleMenu, VdmMainMenuItems);
+    DrawMenuBar(GetConsoleWindow());
 }
 
-BOOL
-ShutdownVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+DestroyVdmMenu(VOID)
 {
-    BOOL result = TRUE;
+    UINT i = 0;
+    const VDM_MENUITEM *Items = VdmMainMenuItems;
+
+    do
+    {
+        DeleteMenu(hConsoleMenu, VdmMenuPos, MF_BYPOSITION);
+        i++;
+    } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
 
-    return result;
+    DrawMenuBar(GetConsoleWindow());
 }
 
-BOOL ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr)
 {
-    BOOL result = TRUE;
-    DWORD dwError;
-    HANDLE hFile;
-
-    hFile = CreateFileW(L"\\system32\\config.nt",
-                        GENERIC_READ,
-                        FILE_SHARE_READ,
-                        NULL,
-                        OPEN_ALWAYS /*OPEN_EXISTING*/,
-                        FILE_ATTRIBUTE_NORMAL,
-                        0);
-    dwError = GetLastError();
-    if (hFile == INVALID_HANDLE_VALUE) {
-        // error with file path or system problem?
-    } else {
-        if (dwError == 0L) {
-            // we just created a new file, perhaps we should set/write some defaults?
-        }
-        if (dwError == ERROR_ALREADY_EXISTS) {
-            // read the line entries and cache in some struct...
-        }
-        CloseHandle(hFile);
+    WCHAR szMenuString[255] = L"";
+
+    if (ShowPtr)
+    {
+        /* Be sure the cursor will be shown */
+        while (ShowConsoleCursor(ConOutHandle, TRUE) < 0) ;
     }
+    else
+    {
+        /* Be sure the cursor will be hidden */
+        while (ShowConsoleCursor(ConOutHandle, FALSE) >= 0) ;
+    }
+
+    if (LoadStringW(GetModuleHandle(NULL),
+                    (!ShowPtr ? IDS_SHOW_MOUSE : IDS_HIDE_MOUSE),
+                    szMenuString,
+                    sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
+    {
+        ModifyMenu(hConsoleMenu, ID_SHOWHIDE_MOUSE,
+                   MF_BYCOMMAND, ID_SHOWHIDE_MOUSE, szMenuString);
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+DisplayMessage(LPCWSTR Format, ...)
+{
+    WCHAR Buffer[256];
+    va_list Parameters;
+
+    va_start(Parameters, Format);
+    _vsnwprintf(Buffer, 256, Format, Parameters);
+    DPRINT1("\n\nNTVDM Subsystem\n%S\n\n", Buffer);
+    MessageBoxW(NULL, Buffer, L"NTVDM Subsystem", MB_OK);
+    va_end(Parameters);
+}
+
+static BOOL
+WINAPI
+ConsoleCtrlHandler(DWORD ControlType)
+{
+    switch (ControlType)
+    {
+        case CTRL_C_EVENT:
+        case CTRL_BREAK_EVENT:
+        {
+            /* Call INT 23h */
+            EmulatorInterrupt(0x23);
+            break;
+        }
+        case CTRL_LAST_CLOSE_EVENT:
+        {
+            if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
+            {
+                /* Exit immediately */
+                if (CommandThread) TerminateThread(CommandThread, 0);
+                EmulatorTerminate();
+            }
+            else
+            {
+                /* Stop accepting new commands */
+                AcceptCommands = FALSE;
+            }
 
-    hFile = CreateFileW(L"\\system32\\autoexec.nt",
-                        GENERIC_READ,
-                        FILE_SHARE_READ,
-                        NULL,
-                        OPEN_ALWAYS,
-                        FILE_ATTRIBUTE_NORMAL,
-                        0);
-    dwError = GetLastError();
-    if (hFile == INVALID_HANDLE_VALUE) {
-        // error with file path or system problem?
-    } else {
-        if (dwError == 0L) {
-            // we just created a new file, perhaps we should set/write some defaults?
+            break;
         }
-        if (dwError == ERROR_ALREADY_EXISTS) {
-            // read the line entries and cache in some struct...
+        default:
+        {
+            /* Stop the VDM if the user logs out or closes the console */
+            EmulatorTerminate();
         }
-        CloseHandle(hFile);
     }
+    return TRUE;
+}
 
-       return result;
+static VOID
+ConsoleInitUI(VOID)
+{
+    CreateVdmMenu(ConsoleOutput);
 }
 
-BOOL
-LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig)
+static VOID
+ConsoleCleanupUI(VOID)
 {
-    BOOL result = TRUE;
+    /* Display again properly the mouse pointer */
+    if (ShowPointer) ShowHideMousePointer(ConsoleOutput, ShowPointer);
 
-       return result;
+    DestroyVdmMenu();
 }
 
-BOOL
-SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec)
+static BOOL
+ConsoleAttach(VOID)
 {
-    BOOL result = TRUE;
+    /* Save the original input and output console modes */
+    if (!GetConsoleMode(ConsoleInput , &OrgConsoleInputMode ) ||
+        !GetConsoleMode(ConsoleOutput, &OrgConsoleOutputMode))
+    {
+        CloseHandle(ConsoleOutput);
+        CloseHandle(ConsoleInput);
+        wprintf(L"FATAL: Cannot save console in/out modes\n");
+        // return FALSE;
+    }
+
+    /* Initialize the UI */
+    ConsoleInitUI();
 
-       return result;
+    return TRUE;
 }
 
-BOOL
-CreateVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+ConsoleDetach(VOID)
 {
-//    BOOL result = TRUE;
-    SYSTEM_INFO inf;
-    MEMORYSTATUS stat;
-
-
-    GlobalMemoryStatus(&stat);
-    if (stat.dwLength != sizeof(MEMORYSTATUS)) {
-        printf("WARNING: GlobalMemoryStatus() returned unknown structure version, size %ld, expected %d.\n", stat.dwLength, sizeof(stat));
-    } else {
-        printf("Memory Load: %ld percent in use.\n", stat.dwMemoryLoad);
-        printf("\t%ld total bytes physical memory.\n", stat.dwTotalPhys);
-        printf("\t%ld available physical memory.\n", stat.dwAvailPhys);
-        printf("\t%ld total bytes paging file.\n", stat.dwTotalPageFile);
-        printf("\t%ld available paging file.\n", stat.dwAvailPageFile);
-        printf("\t%lx total bytes virtual memory.\n", stat.dwTotalVirtual);
-        printf("\t%lx available bytes virtual memory.\n", stat.dwAvailVirtual);
-
-#define OUT_OF_HEADROOM 90
-        if (stat.dwMemoryLoad > OUT_OF_HEADROOM) {
-            DPRINT("VDM: system resources deemed to low to start VDM.\n");
-            //SetLastError();
-            return FALSE;
-        }
+    /* Restore the original input and output console modes */
+    SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
+    SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
 
-    }
+    /* Cleanup the UI */
+    ConsoleCleanupUI();
+}
 
-    GetSystemInfo(&inf);
-    vdm->hHeap = HeapCreate(0, inf.dwAllocationGranularity, 0);
-    if (vdm->hHeap == NULL) {
-        DPRINT("VDM: failed to create heap.\n");
+static BOOL
+ConsoleInit(VOID)
+{
+    /* Set the handler routine */
+    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
+
+    /* Enable the CTRL_LAST_CLOSE_EVENT */
+    SetLastConsoleEventActive();
+
+    /*
+     * NOTE: The CONIN$ and CONOUT$ "virtual" files
+     * always point to non-redirected console handles.
+     */
+
+    /* Get the input handle to the real console, and check for success */
+    ConsoleInput = CreateFileW(L"CONIN$",
+                               GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                               NULL,
+                               OPEN_EXISTING,
+                               0,
+                               NULL);
+    if (ConsoleInput == INVALID_HANDLE_VALUE)
+    {
+        wprintf(L"FATAL: Cannot retrieve a handle to the console input\n");
         return FALSE;
     }
 
-#define DEFAULT_VDM_IMAGE_SIZE 2000000
-    vdm->ImageMem = HeapAlloc(vdm->hHeap, 0, DEFAULT_VDM_IMAGE_SIZE);
-    if (vdm->ImageMem == NULL) {
-        DPRINT("VDM: failed to allocate image memory from heap %x.\n", vdm->hHeap);
-        HeapDestroy(vdm->hHeap);
-        vdm->hHeap = NULL;
+    /* Get the output handle to the real console, and check for success */
+    ConsoleOutput = CreateFileW(L"CONOUT$",
+                                GENERIC_READ | GENERIC_WRITE,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                NULL,
+                                OPEN_EXISTING,
+                                0,
+                                NULL);
+    if (ConsoleOutput == INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(ConsoleInput);
+        wprintf(L"FATAL: Cannot retrieve a handle to the console output\n");
         return FALSE;
     }
-    return TRUE;
+
+    /* Effectively attach to the console */
+    return ConsoleAttach();
 }
 
-BOOL
-DestroyVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+ConsoleCleanup(VOID)
 {
-    BOOL result = TRUE;
+    /* Detach from the console */
+    ConsoleDetach();
+
+    /* Close the console handles */
+    if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput);
+    if (ConsoleInput  != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput);
+}
 
-    if (vdm->ImageMem != NULL) {
-        if (HeapFree(vdm->hHeap, 0, vdm->ImageMem) != FALSE) {
-            DPRINT("VDM: failed to free memory from heap %x.\n", vdm->hHeap);
-            result = FALSE;
+DWORD
+WINAPI
+PumpConsoleInput(LPVOID Parameter)
+{
+    HANDLE ConsoleInput = (HANDLE)Parameter;
+    INPUT_RECORD InputRecord;
+    DWORD Count;
+
+    while (VdmRunning)
+    {
+        /* Make sure the task event is signaled */
+        WaitForSingleObject(VdmTaskEvent, INFINITE);
+
+        /* Wait for an input record */
+        if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count))
+        {
+            DWORD LastError = GetLastError();
+            DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError);
+            return LastError;
+        }
+
+        ASSERT(Count != 0);
+
+        /* Check the event type */
+        switch (InputRecord.EventType)
+        {
+            case KEY_EVENT:
+            case MOUSE_EVENT:
+                /* Send it to the PS/2 controller */
+                PS2Dispatch(&InputRecord);
+                break;
+
+            case MENU_EVENT:
+            {
+                switch (InputRecord.Event.MenuEvent.dwCommandId)
+                {
+                    case ID_SHOWHIDE_MOUSE:
+                        ShowHideMousePointer(ConsoleOutput, ShowPointer);
+                        ShowPointer = !ShowPointer;
+                        break;
+
+                    case ID_VDM_QUIT:
+                        /* Stop the VDM */
+                        EmulatorTerminate();
+                        break;
+
+                    default:
+                        break;
+                }
+
+                break;
+            }
+
+            default:
+                break;
         }
-        vdm->ImageMem = NULL;
     }
-    if (vdm->hHeap != NULL) {
-        if (!HeapDestroy(vdm->hHeap)) {
-            DPRINT("VDM: failed to destroy heap %x.\n", vdm->hHeap);
-            result = FALSE;
+
+    return 0;
+}
+
+#ifndef STANDALONE
+static DWORD
+WINAPI
+CommandThreadProc(LPVOID Parameter)
+{
+    BOOLEAN First = TRUE;
+    DWORD Result;
+    VDM_COMMAND_INFO CommandInfo;
+    CHAR CmdLine[MAX_PATH];
+    CHAR AppName[MAX_PATH];
+    CHAR PifFile[MAX_PATH];
+    CHAR Desktop[MAX_PATH];
+    CHAR Title[MAX_PATH];
+    CHAR Env[MAX_PATH];
+
+    UNREFERENCED_PARAMETER(Parameter);
+
+    do
+    {
+        /* Clear the structure */
+        ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+
+        /* Initialize the structure members */
+        CommandInfo.TaskId = SessionId;
+        CommandInfo.VDMState = VDM_FLAG_DOS;
+        CommandInfo.CmdLine = CmdLine;
+        CommandInfo.CmdLen = sizeof(CmdLine);
+        CommandInfo.AppName = AppName;
+        CommandInfo.AppLen = sizeof(AppName);
+        CommandInfo.PifFile = PifFile;
+        CommandInfo.PifLen = sizeof(PifFile);
+        CommandInfo.Desktop = Desktop;
+        CommandInfo.DesktopLen = sizeof(Desktop);
+        CommandInfo.Title = Title;
+        CommandInfo.TitleLen = sizeof(Title);
+        CommandInfo.Env = Env;
+        CommandInfo.EnvLen = sizeof(Env);
+
+        if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
+
+        /* Wait for the next available VDM */
+        if (!GetNextVDMCommand(&CommandInfo)) break;
+
+        /* Start the process from the command line */
+        DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
+        Result = DosStartProcess(AppName, CmdLine, Env);
+        if (Result != ERROR_SUCCESS)
+        {
+            DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
+            // break;
+            continue;
         }
-        vdm->hHeap = NULL;
+
+        First = FALSE;
     }
-    return result;
+    while (AcceptCommands);
+
+    return 0;
 }
+#endif
 
-int WINAPI
-WinMain(HINSTANCE hInstance,  HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+INT
+wmain(INT argc, WCHAR *argv[])
 {
-    VDM_CONTROL_BLOCK VdmCB;
+#ifdef STANDALONE
+
     DWORD Result;
-    ULONG i;
-    BOOL vdmStarted = FALSE;
+    CHAR ApplicationName[MAX_PATH];
+    CHAR CommandLine[DOS_CMDLINE_LENGTH];
 
-    WCHAR WelcomeMsg[RC_STRING_MAX_SIZE];
-    WCHAR PromptMsg[RC_STRING_MAX_SIZE];
-    CHAR InputBuffer[255];
+    if (argc >= 2)
+    {
+        WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
 
-    LoadStringW( GetModuleHandle(NULL), STRING_WelcomeMsg, WelcomeMsg,sizeof(WelcomeMsg) / sizeof(WelcomeMsg[0]));
-    LoadStringW( GetModuleHandle(NULL), STRING_PromptMsg, PromptMsg ,sizeof(PromptMsg) / sizeof(PromptMsg[0]));
+        if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
+        else strcpy(CommandLine, "");
+    }
+    else
+    {
+        wprintf(L"\nReactOS Virtual DOS Machine\n\n"
+                L"Usage: NTVDM <executable> [<parameters>]\n");
+        return 0;
+    }
 
-    AllocConsole();
-    SetConsoleTitleW(L"ntvdm");
+#else
 
-    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
-                 WelcomeMsg, lstrlenW(WelcomeMsg),  // wcslen(WelcomeMsg),
-                 &Result, NULL);
+    INT i;
+    WCHAR *endptr;
 
-    if (!CreateVDM(&VdmCB)) {
-        DPRINT("VDM: failed to create VDM.\n");
-        //SetLastError();
-        return 2;
+    /* Parse the command line arguments */
+    for (i = 1; i < argc; i++)
+    {
+        if (wcsncmp(argv[i], L"-i", 2) == 0)
+        {
+            /* This is the session ID */
+            SessionId = wcstoul(argv[i] + 2, &endptr, 10);
+
+            /* The VDM hasn't been started from a console, so quit when the task is done */
+            AcceptCommands = FALSE;
+        }
     }
 
-       ReadConfigForVDM(&VdmCB);
+#endif
+
+    DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
+
+    /* Create the task event */
+    VdmTaskEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ASSERT(VdmTaskEvent != NULL);
 
-    if (!LoadConfigDriversForVDM(&(VdmCB.vdmConfig))) {
-        DPRINT("VDM: failed to load configuration drivers.\n");
-        //SetLastError();
-        return 2;
+    /* Initialize the console */
+    if (!ConsoleInit())
+    {
+        wprintf(L"FATAL: A problem occurred when trying to initialize the console\n");
+        goto Cleanup;
     }
-    if (!SetConfigOptionsForVDM(&(VdmCB.vdmAutoexec))) {
-        DPRINT("VDM: failed to set configuration options.\n");
-        //SetLastError();
-        return 3;
+
+    /* Initialize the emulator */
+    if (!EmulatorInitialize(ConsoleInput, ConsoleOutput))
+    {
+        wprintf(L"FATAL: Failed to initialize the emulator\n");
+        goto Cleanup;
     }
 
-    GetSystemDirectoryA(VdmCB.CommandLine, MAX_PATH);
-    strcat(VdmCB.CommandLine, "\\hello.exe");
-    GetWindowsDirectoryA(VdmCB.CurrentDirectory, MAX_PATH);
-
-    for (;;) {
-        WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
-                     PromptMsg, lstrlenW(PromptMsg),  // wcslen(PromptMsg),
-                     &Result, NULL);
-        i = 0;
-        do {
-            ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE),
-                        &InputBuffer[i], 1,
-                        &Result, NULL);
-            if (++i >= (sizeof(InputBuffer) - 1)) {
-                break;
-            }
-        } while (InputBuffer[i - 1] != '\n');
-        InputBuffer[i - 1] = '\0';
-
-        if (InputBuffer[0] == 'r' || InputBuffer[0] == 'R') {
-            if (!vdmStarted) {
-                if (StartVDM(&VdmCB)) {
-                    vdmStarted = TRUE;
-                } else {
-                    DPRINT("VDM: failed to start.\n");
-                }
-            } else {
-                DPRINT("VDM: already started.\n");
-            }
-        }
-        if (InputBuffer[0] == 's' || InputBuffer[0] == 'S') {
-            if (vdmStarted) {
-                if (ShutdownVDM(&VdmCB)) {
-                    vdmStarted = FALSE;
-                } else {
-                    DPRINT("VDM: failed to shutdown.\n");
-                }
-            } else {
-                DPRINT("VDM: not started.\n");
-            }
-        }
-        if (InputBuffer[0] == 'q' || InputBuffer[0] == 'Q') {
-            break;
-        }
+    /* Initialize the system BIOS */
+    if (!BiosInitialize(NULL))
+    {
+        wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
+        goto Cleanup;
     }
 
-    if (!ShutdownVDM(&VdmCB)) {
-        DPRINT("VDM: failed to cleanly shutdown VDM.\n");
-        //SetLastError();
-        return 5;
+    /* Initialize the VDM DOS kernel */
+    if (!DosInitialize(NULL))
+    {
+        wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n");
+        goto Cleanup;
     }
 
-    if (!DestroyVDM(&VdmCB)) {
-        DPRINT("VDM: failed to cleanly destroy VDM.\n");
-        //SetLastError();
-        return 6;
+#ifndef STANDALONE
+
+    /* Create the GetNextVDMCommand thread */
+    CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
+    if (CommandThread == NULL)
+    {
+        wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
+        goto Cleanup;
     }
 
-    ExitProcess(0);
+    /* Wait for the command thread to exit */
+    WaitForSingleObject(CommandThread, INFINITE);
+
+    /* Close the thread handle */
+    CloseHandle(CommandThread);
+
+#else
+
+    /* Start the process from the command line */
+    DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
+    Result = DosStartProcess(ApplicationName,
+                             CommandLine,
+                             GetEnvironmentStrings());
+    if (Result != ERROR_SUCCESS)
+    {
+        DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
+        goto Cleanup;
+    }
+
+#endif
+
+Cleanup:
+    BiosCleanup();
+    EmulatorCleanup();
+    ConsoleCleanup();
+
+#ifndef STANDALONE
+    ExitVDM(FALSE, 0);
+#endif
+
+    /* Quit the VDM */
+    DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n");
+
     return 0;
 }
+
+/* EOF */
diff --git a/subsystems/ntvdm/ntvdm.h b/subsystems/ntvdm/ntvdm.h
new file mode 100644 (file)
index 0000000..4686c05
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            ntvdm.h
+ * PURPOSE:         Header file to define commonly used stuff
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _NTVDM_H_
+#define _NTVDM_H_
+
+/* INCLUDES *******************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <conio.h>
+#include <wchar.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <wincon.h>
+#include <winnls.h>
+#include <winreg.h>
+#include <winuser.h>
+#include <subsys/win/vdm.h>
+
+#include <vddsvc.h>
+
+DWORD WINAPI SetLastConsoleEventActive(VOID);
+
+#include <debug.h>
+
+/*
+ * Activate this line if you want to run NTVDM in standalone mode with:
+ * ntvdm.exe <program>
+ */
+// #define STANDALONE
+
+/* FUNCTIONS ******************************************************************/
+
+#ifndef STANDALONE
+extern ULONG SessionId;
+#endif
+
+extern HANDLE VdmTaskEvent;
+
+VOID DisplayMessage(LPCWSTR Format, ...);
+
+#endif // _NTVDM_H_
+
+/* EOF */
index 6542cc2..bb78ced 100644 (file)
@@ -1,32 +1,39 @@
 #include <windef.h>
+#include <winuser.h>
+// #include <commctrl.h>
 
 #include "resource.h"
 
-#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual DOS Machine"
-#define REACTOS_STR_INTERNAL_NAME "ntvdm"
-#define REACTOS_STR_ORIGINAL_FILENAME "ntvdm.exe"
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#define REACTOS_STR_FILE_DESCRIPTION    "ReactOS Virtual DOS Machine"
+#define REACTOS_STR_INTERNAL_NAME       "ntvdm"
+#define REACTOS_STR_ORIGINAL_FILENAME   "ntvdm.exe"
 #include <reactos/version.rc>
 
+IDI_APPICON ICON "res/ntvdm.ico"
+
 /* UTF-8 */
 #pragma code_page(65001)
 
-#include "lang/bg-BG.rc"
-#include "lang/cs-CZ.rc"
-#include "lang/de-DE.rc"
-#include "lang/en-US.rc"
-#include "lang/es-ES.rc"
-#include "lang/fr-FR.rc"
-#include "lang/hu-HU.rc"
-#include "lang/id-ID.rc"
-#include "lang/it-IT.rc"
-#include "lang/ja-JP.rc"
-#include "lang/no-NO.rc"
-#include "lang/pl-PL.rc"
-#include "lang/pt-BR.rc"
-#include "lang/ro-RO.rc"
-#include "lang/ru-RU.rc"
-#include "lang/sk-SK.rc"
-#include "lang/th-TH.rc"
-#include "lang/uk-UA.rc"
-#include "lang/zh-CN.rc"
-#include "lang/zh-TW.rc"
+#ifdef LANGUAGE_CS_CZ
+    #include "lang/cs-CZ.rc"
+#endif
+#ifdef LANGUAGE_DE_DE
+    #include "lang/de-DE.rc"
+#endif
+#ifdef LANGUAGE_EN_US
+    #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_ES_ES
+    #include "lang/es-ES.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+    #include "lang/fr-FR.rc"
+#endif
+#ifdef LANGUAGE_IT_IT
+    #include "lang/it-IT.rc"
+#endif
+#ifdef LANGUAGE_PL_PL
+    #include "lang/pl-PL.rc"
+#endif
diff --git a/subsystems/ntvdm/ntvdm.spec b/subsystems/ntvdm/ntvdm.spec
new file mode 100644 (file)
index 0000000..244bda9
--- /dev/null
@@ -0,0 +1,220 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; NTVDM Registers exports ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+@ stdcall getAF()
+@ stdcall getAH()
+@ stdcall getAL()
+@ stdcall getAX()
+@ stdcall getBH()
+@ stdcall getBL()
+@ stdcall getBP()
+@ stdcall getBX()
+@ stdcall getCF()
+@ stdcall getCH()
+@ stdcall getCL()
+@ stdcall getCS()
+@ stdcall getCX()
+@ stdcall getDF()
+@ stdcall getDH()
+@ stdcall getDI()
+@ stdcall getDL()
+@ stdcall getDS()
+@ stdcall getDX()
+@ stdcall getEAX()
+@ stdcall getEBP()
+@ stdcall getEBX()
+@ stdcall getECX()
+@ stdcall getEDI()
+@ stdcall getEDX()
+@ stdcall getEFLAGS()
+@ stdcall getEIP()
+@ stdcall getES()
+@ stdcall getESI()
+@ stdcall getESP()
+@ stdcall getFS()
+@ stdcall getGS()
+@ stdcall getIF()
+@ stdcall getIntelRegistersPointer()
+@ stdcall getIP()
+@ stdcall getMSW()
+@ stdcall getOF()
+@ stdcall getPF()
+@ stdcall getSF()
+@ stdcall getSI()
+@ stdcall getSP()
+@ stdcall getSS()
+@ stdcall getZF()
+
+@ stdcall setAF(long)
+@ stdcall setAH(long)
+@ stdcall setAL(long)
+@ stdcall setAX(long)
+@ stdcall setBH(long)
+@ stdcall setBL(long)
+@ stdcall setBP(long)
+@ stdcall setBX(long)
+@ stdcall setCF(long)
+@ stdcall setCH(long)
+@ stdcall setCL(long)
+@ stdcall setCS(long)
+@ stdcall setCX(long)
+@ stdcall setDF(long)
+@ stdcall setDH(long)
+@ stdcall setDI(long)
+@ stdcall setDL(long)
+@ stdcall setDS(long)
+@ stdcall setDX(long)
+@ stdcall setEAX(long)
+@ stdcall setEBP(long)
+@ stdcall setEBX(long)
+@ stdcall setECX(long)
+@ stdcall setEDI(long)
+@ stdcall setEDX(long)
+@ stdcall setEFLAGS(long)
+@ stdcall setEIP(long)
+@ stdcall setES(long)
+@ stdcall setESI(long)
+@ stdcall setESP(long)
+@ stdcall setFS(long)
+@ stdcall setGS(long)
+@ stdcall setIF(long)
+@ stdcall setIP(long)
+@ stdcall setMSW(long)
+@ stdcall setOF(long)
+@ stdcall setPF(long)
+@ stdcall setSF(long)
+@ stdcall setSI(long)
+@ stdcall setSP(long)
+@ stdcall setSS(long)
+@ stdcall setZF(long)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; NTVDM CCPU MIPS exports ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+@ stdcall c_getAF()  getAF
+@ stdcall c_getAH()  getAH
+@ stdcall c_getAL()  getAL
+@ stdcall c_getAX()  getAX
+@ stdcall c_getBH()  getBH
+@ stdcall c_getBL()  getBL
+@ stdcall c_getBP()  getBP
+@ stdcall c_getBX()  getBX
+@ stdcall c_getCF()  getCF
+@ stdcall c_getCH()  getCH
+@ stdcall c_getCL()  getCL
+@ stdcall c_getCS()  getCS
+@ stdcall c_getCX()  getCX
+@ stdcall c_getDF()  getDF
+@ stdcall c_getDH()  getDH
+@ stdcall c_getDI()  getDI
+@ stdcall c_getDL()  getDL
+@ stdcall c_getDS()  getDS
+@ stdcall c_getDX()  getDX
+@ stdcall c_getEAX() getEAX
+@ stdcall c_getEBP() getEBP
+@ stdcall c_getEBX() getEBX
+@ stdcall c_getECX() getECX
+@ stdcall c_getEDI() getEDI
+@ stdcall c_getEDX() getEDX
+@ stdcall c_getEIP() getEIP
+@ stdcall c_getES()  getES
+@ stdcall c_getESI() getESI
+@ stdcall c_getESP() getESP
+@ stdcall c_getFS()  getFS
+@ stdcall c_getGS()  getGS
+@ stdcall c_getIF()  getIF
+@ stdcall c_getIP()  getIP
+@ stdcall c_getMSW() getMSW
+@ stdcall c_getOF()  getOF
+@ stdcall c_getPF()  getPF
+@ stdcall c_getSF()  getSF
+@ stdcall c_getSI()  getSI
+@ stdcall c_getSP()  getSP
+@ stdcall c_getSS()  getSS
+@ stdcall c_getZF()  getZF
+
+@ stdcall c_setAF(long)  setAF
+@ stdcall c_setAH(long)  setAH
+@ stdcall c_setAL(long)  setAL
+@ stdcall c_setAX(long)  setAX
+@ stdcall c_setBH(long)  setBH
+@ stdcall c_setBL(long)  setBL
+@ stdcall c_setBP(long)  setBP
+@ stdcall c_setBX(long)  setBX
+@ stdcall c_setCF(long)  setCF
+@ stdcall c_setCH(long)  setCH
+@ stdcall c_setCL(long)  setCL
+@ stdcall c_setCS(long)  setCS
+@ stdcall c_setCX(long)  setCX
+@ stdcall c_setDF(long)  setDF
+@ stdcall c_setDH(long)  setDH
+@ stdcall c_setDI(long)  setDI
+@ stdcall c_setDL(long)  setDL
+@ stdcall c_setDS(long)  setDS
+@ stdcall c_setDX(long)  setDX
+@ stdcall c_setEAX(long) setEAX
+@ stdcall c_setEBP(long) setEBP
+@ stdcall c_setEBX(long) setEBX
+@ stdcall c_setECX(long) setECX
+@ stdcall c_setEDI(long) setEDI
+@ stdcall c_setEDX(long) setEDX
+@ stdcall c_setEIP(long) setEIP
+@ stdcall c_setES(long)  setES
+@ stdcall c_setESI(long) setESI
+@ stdcall c_setESP(long) setESP
+@ stdcall c_setFS(long)  setFS
+@ stdcall c_setGS(long)  setGS
+@ stdcall c_setIF(long)  setIF
+@ stdcall c_setIP(long)  setIP
+@ stdcall c_setMSW(long) setMSW
+@ stdcall c_setOF(long)  setOF
+@ stdcall c_setPF(long)  setPF
+@ stdcall c_setSF(long)  setSF
+@ stdcall c_setSI(long)  setSI
+@ stdcall c_setSP(long)  setSP
+@ stdcall c_setSS(long)  setSS
+@ stdcall c_setZF(long)  setZF
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; NTVDM DOS-32 Emulation exports ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+@ stdcall demClientErrorEx(long long long)
+@ stdcall demFileDelete(ptr)
+@ stdcall demFileFindFirst(ptr ptr long)
+@ stdcall demFileFindNext(ptr)
+;@ stdcall demGetFileTimeByHandle_WOW
+@ stdcall demGetPhysicalDriveType(long)
+@ stdcall demIsShortPathName(ptr long)
+;@ stdcall demLFNCleanup
+;@ stdcall demLFNGetCurrentDirectory
+@ stdcall demSetCurrentDirectoryGetDrive(ptr ptr)
+;@ stdcall demWOWLFNAllocateSearchHandle
+;@ stdcall demWOWLFNCloseSearchHandle
+;@ stdcall demWOWLFNEntry
+;@ stdcall demWOWLFNGetSearchHandle
+;@ stdcall demWOWLFNInit
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; NTVDM Miscellaneous exports ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+@ stdcall MGetVdmPointer(long long long)
+@ stdcall Sim32pGetVDMPointer(long long)
+
+;@ stdcall VdmFlushCache(long long long long) ; Not exported on x86
+@ stdcall VdmMapFlat(long long long)
+;@ stdcall VdmUnmapFlat(long long ptr long)  ; Not exported on x86
+
+@ stdcall call_ica_hw_interrupt(long long long)
+@ stdcall VDDInstallIOHook(long long ptr ptr)
+@ stdcall VDDDeInstallIOHook(long long ptr)
+
+@ stdcall VDDSimulate16()
+@ stdcall host_simulate()   VDDSimulate16
+@ stdcall VDDTerminateVDM()
diff --git a/subsystems/ntvdm/registers.c b/subsystems/ntvdm/registers.c
new file mode 100644 (file)
index 0000000..d3d5ce1
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            registers.c
+ * PURPOSE:         Exported functions for manipulating registers
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+static inline BOOLEAN EmulatorGetFlag(ULONG Flag)
+{
+    return (EmulatorContext.Flags.Long & Flag) ? TRUE : FALSE;
+}
+
+static inline VOID EmulatorSetFlag(ULONG Flag)
+{
+    EmulatorContext.Flags.Long |= Flag;
+}
+
+static inline VOID EmulatorClearFlag(ULONG Flag)
+{
+    EmulatorContext.Flags.Long &= ~Flag;
+}
+
+VOID EmulatorSetStack(WORD Segment, DWORD Offset)
+{
+    Fast486SetStack(&EmulatorContext, Segment, Offset);
+}
+
+
+
+PVOID
+WINAPI
+getIntelRegistersPointer(VOID)
+{
+    UNIMPLEMENTED;
+    return NULL;
+}
+
+ULONG
+WINAPI
+getEAX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long;
+}
+
+VOID
+WINAPI
+setEAX(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Value;
+}
+
+USHORT
+WINAPI
+getAX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowWord;
+}
+
+VOID
+WINAPI
+setAX(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowWord = Value;
+}
+
+UCHAR
+WINAPI
+getAH(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EAX].HighByte;
+}
+
+VOID
+WINAPI
+setAH(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EAX].HighByte = Value;
+}
+
+UCHAR
+WINAPI
+getAL(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowByte;
+}
+
+VOID
+WINAPI
+setAL(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowByte = Value;
+}
+
+ULONG
+WINAPI
+getEBX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long;
+}
+
+VOID
+WINAPI
+setEBX(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Value;
+}
+
+USHORT
+WINAPI
+getBX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowWord;
+}
+
+VOID
+WINAPI
+setBX(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowWord = Value;
+}
+
+UCHAR
+WINAPI
+getBH(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBX].HighByte;
+}
+
+VOID
+WINAPI
+setBH(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBX].HighByte = Value;
+}
+
+UCHAR
+WINAPI
+getBL(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowByte;
+}
+
+VOID
+WINAPI
+setBL(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowByte = Value;
+}
+
+
+
+ULONG
+WINAPI
+getECX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long;
+}
+
+VOID
+WINAPI
+setECX(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long = Value;
+}
+
+USHORT
+WINAPI
+getCX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowWord;
+}
+
+VOID
+WINAPI
+setCX(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowWord = Value;
+}
+
+UCHAR
+WINAPI
+getCH(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ECX].HighByte;
+}
+
+VOID
+WINAPI
+setCH(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ECX].HighByte = Value;
+}
+
+UCHAR
+WINAPI
+getCL(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowByte;
+}
+
+VOID
+WINAPI
+setCL(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowByte = Value;
+}
+
+
+
+ULONG
+WINAPI
+getEDX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long;
+}
+
+VOID
+WINAPI
+setEDX(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long = Value;
+}
+
+USHORT
+WINAPI
+getDX(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowWord;
+}
+
+VOID
+WINAPI
+setDX(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowWord = Value;
+}
+
+UCHAR
+WINAPI
+getDH(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDX].HighByte;
+}
+
+VOID
+WINAPI
+setDH(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDX].HighByte = Value;
+}
+
+UCHAR
+WINAPI
+getDL(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowByte;
+}
+
+VOID
+WINAPI
+setDL(UCHAR Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowByte = Value;
+}
+
+
+
+ULONG
+WINAPI
+getESP(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ESP].Long;
+}
+
+VOID
+WINAPI
+setESP(ULONG Value)
+{
+    EmulatorSetStack(getSS(), Value);
+}
+
+USHORT
+WINAPI
+getSP(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ESP].LowWord;
+}
+
+VOID
+WINAPI
+setSP(USHORT Value)
+{
+    EmulatorSetStack(getSS(), Value);
+}
+
+
+
+ULONG
+WINAPI
+getEBP(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBP].Long;
+}
+
+VOID
+WINAPI
+setEBP(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBP].Long = Value;
+}
+
+USHORT
+WINAPI
+getBP(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EBP].LowWord;
+}
+
+VOID
+WINAPI
+setBP(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EBP].LowWord = Value;
+}
+
+
+
+ULONG
+WINAPI
+getESI(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long;
+}
+
+VOID
+WINAPI
+setESI(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long = Value;
+}
+
+USHORT
+WINAPI
+getSI(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_ESI].LowWord;
+}
+
+VOID
+WINAPI
+setSI(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_ESI].LowWord = Value;
+}
+
+
+
+ULONG
+WINAPI
+getEDI(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long;
+}
+
+VOID
+WINAPI
+setEDI(ULONG Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long = Value;
+}
+
+USHORT
+WINAPI
+getDI(VOID)
+{
+    return EmulatorContext.GeneralRegs[FAST486_REG_EDI].LowWord;
+}
+
+VOID
+WINAPI
+setDI(USHORT Value)
+{
+    EmulatorContext.GeneralRegs[FAST486_REG_EDI].LowWord = Value;
+}
+
+
+
+ULONG
+WINAPI
+getEIP(VOID)
+{
+    return EmulatorContext.InstPtr.Long;
+}
+
+VOID
+WINAPI
+setEIP(ULONG Value)
+{
+    EmulatorExecute(getCS(), Value);
+}
+
+USHORT
+WINAPI
+getIP(VOID)
+{
+    return EmulatorContext.InstPtr.LowWord;
+}
+
+VOID
+WINAPI
+setIP(USHORT Value)
+{
+    EmulatorExecute(getCS(), Value);
+}
+
+
+
+USHORT
+WINAPI
+getCS(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector;
+}
+
+VOID
+WINAPI
+setCS(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_CS, Value);
+}
+
+USHORT
+WINAPI
+getSS(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_SS].Selector;
+}
+
+VOID
+WINAPI
+setSS(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_SS, Value);
+}
+
+USHORT
+WINAPI
+getDS(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector;
+}
+
+VOID
+WINAPI
+setDS(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_DS, Value);
+}
+
+USHORT
+WINAPI
+getES(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector;
+}
+
+VOID
+WINAPI
+setES(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_ES, Value);
+}
+
+USHORT
+WINAPI
+getFS(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_FS].Selector;
+}
+
+VOID
+WINAPI
+setFS(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_FS, Value);
+}
+
+USHORT
+WINAPI
+getGS(VOID)
+{
+    return EmulatorContext.SegmentRegs[FAST486_REG_GS].Selector;
+}
+
+VOID
+WINAPI
+setGS(USHORT Value)
+{
+    Fast486SetSegment(&EmulatorContext, FAST486_REG_GS, Value);
+}
+
+
+
+ULONG
+WINAPI
+getCF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_CF);
+}
+
+VOID
+WINAPI
+setCF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_CF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_CF);
+}
+
+ULONG
+WINAPI
+getPF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_PF);
+}
+
+VOID
+WINAPI
+setPF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_PF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_PF);
+}
+
+ULONG
+WINAPI
+getAF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_AF);
+}
+
+VOID
+WINAPI
+setAF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_AF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_AF);
+}
+
+ULONG
+WINAPI
+getZF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_ZF);
+}
+
+VOID
+WINAPI
+setZF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_ZF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_ZF);
+}
+
+ULONG
+WINAPI
+getSF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_SF);
+}
+
+VOID
+WINAPI
+setSF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_SF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_SF);
+}
+
+ULONG
+WINAPI
+getIF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_IF);
+}
+
+VOID
+WINAPI
+setIF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_IF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_IF);
+}
+
+ULONG
+WINAPI
+getDF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_DF);
+}
+
+VOID
+WINAPI
+setDF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_DF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_DF);
+}
+
+ULONG
+WINAPI
+getOF(VOID)
+{
+    return EmulatorGetFlag(EMULATOR_FLAG_OF);
+}
+
+VOID
+WINAPI
+setOF(ULONG Flag)
+{
+    if (Flag & 1)
+        EmulatorSetFlag(EMULATOR_FLAG_OF);
+    else
+        EmulatorClearFlag(EMULATOR_FLAG_OF);
+}
+
+
+
+ULONG
+WINAPI
+getEFLAGS(VOID)
+{
+    return EmulatorContext.Flags.Long;
+}
+
+VOID
+WINAPI
+setEFLAGS(ULONG Flags)
+{
+    EmulatorContext.Flags.Long = Flags;
+}
+
+
+
+USHORT
+WINAPI
+getMSW(VOID)
+{
+    return LOWORD(EmulatorContext.ControlRegisters[FAST486_REG_CR0]);
+}
+
+VOID
+WINAPI
+setMSW(USHORT Value)
+{
+    /* Set the lower 16 bits (Machine Status Word) of CR0 */
+    EmulatorContext.ControlRegisters[FAST486_REG_CR0] &= 0xFFFF0000;
+    EmulatorContext.ControlRegisters[FAST486_REG_CR0] |= Value & 0xFFFF;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/registers.h b/subsystems/ntvdm/registers.h
new file mode 100644 (file)
index 0000000..09568f3
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            registers.c
+ * PURPOSE:         Exported functions for manipulating registers
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _REGISTERS_H_
+#define _REGISTERS_H_
+
+/* INCLUDES *******************************************************************/
+
+VOID EmulatorSetStack(WORD Segment, DWORD Offset);
+
+#if 0   // Those function prototypes are already included via ddk/vddsvc.h
+
+PVOID  WINAPI getIntelRegistersPointer(VOID);
+
+ULONG  WINAPI getEAX(VOID);
+VOID   WINAPI setEAX(ULONG);
+USHORT WINAPI getAX(VOID);
+VOID   WINAPI setAX(USHORT);
+UCHAR  WINAPI getAH(VOID);
+VOID   WINAPI setAH(UCHAR);
+UCHAR  WINAPI getAL(VOID);
+VOID   WINAPI setAL(UCHAR);
+
+ULONG  WINAPI getEBX(VOID);
+VOID   WINAPI setEBX(ULONG);
+USHORT WINAPI getBX(VOID);
+VOID   WINAPI setBX(USHORT);
+UCHAR  WINAPI getBH(VOID);
+VOID   WINAPI setBH(UCHAR);
+UCHAR  WINAPI getBL(VOID);
+VOID   WINAPI setBL(UCHAR);
+
+ULONG  WINAPI getECX(VOID);
+VOID   WINAPI setECX(ULONG);
+USHORT WINAPI getCX(VOID);
+VOID   WINAPI setCX(USHORT);
+UCHAR  WINAPI getCH(VOID);
+VOID   WINAPI setCH(UCHAR);
+UCHAR  WINAPI getCL(VOID);
+VOID   WINAPI setCL(UCHAR);
+
+ULONG  WINAPI getEDX(VOID);
+VOID   WINAPI setEDX(ULONG);
+USHORT WINAPI getDX(VOID);
+VOID   WINAPI setDX(USHORT);
+UCHAR  WINAPI getDH(VOID);
+VOID   WINAPI setDH(UCHAR);
+UCHAR  WINAPI getDL(VOID);
+VOID   WINAPI setDL(UCHAR);
+
+
+
+ULONG  WINAPI getESP(VOID);
+VOID   WINAPI setESP(ULONG);
+USHORT WINAPI getSP(VOID);
+VOID   WINAPI setSP(USHORT);
+
+ULONG  WINAPI getEBP(VOID);
+VOID   WINAPI setEBP(ULONG);
+USHORT WINAPI getBP(VOID);
+VOID   WINAPI setBP(USHORT);
+
+ULONG  WINAPI getESI(VOID);
+VOID   WINAPI setESI(ULONG);
+USHORT WINAPI getSI(VOID);
+VOID   WINAPI setSI(USHORT);
+
+ULONG  WINAPI getEDI(VOID);
+VOID   WINAPI setEDI(ULONG);
+USHORT WINAPI getDI(VOID);
+VOID   WINAPI setDI(USHORT);
+
+ULONG  WINAPI getEIP(VOID);
+VOID   WINAPI setEIP(ULONG);
+USHORT WINAPI getIP(VOID);
+VOID   WINAPI setIP(USHORT);
+
+USHORT WINAPI getCS(VOID);
+VOID   WINAPI setCS(USHORT);
+USHORT WINAPI getSS(VOID);
+VOID   WINAPI setSS(USHORT);
+USHORT WINAPI getDS(VOID);
+VOID   WINAPI setDS(USHORT);
+USHORT WINAPI getES(VOID);
+VOID   WINAPI setES(USHORT);
+USHORT WINAPI getFS(VOID);
+VOID   WINAPI setFS(USHORT);
+USHORT WINAPI getGS(VOID);
+VOID   WINAPI setGS(USHORT);
+
+ULONG  WINAPI getCF(VOID);
+VOID   WINAPI setCF(ULONG);
+ULONG  WINAPI getPF(VOID);
+VOID   WINAPI setPF(ULONG);
+ULONG  WINAPI getAF(VOID);
+VOID   WINAPI setAF(ULONG);
+ULONG  WINAPI getZF(VOID);
+VOID   WINAPI setZF(ULONG);
+ULONG  WINAPI getSF(VOID);
+VOID   WINAPI setSF(ULONG);
+ULONG  WINAPI getIF(VOID);
+VOID   WINAPI setIF(ULONG);
+ULONG  WINAPI getDF(VOID);
+VOID   WINAPI setDF(ULONG);
+ULONG  WINAPI getOF(VOID);
+VOID   WINAPI setOF(ULONG);
+
+ULONG  WINAPI getEFLAGS(VOID);
+VOID   WINAPI setEFLAGS(ULONG);
+
+USHORT WINAPI getMSW(VOID);
+VOID   WINAPI setMSW(USHORT);
+
+#endif
+
+#endif // _REGISTERS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/res/ntvdm.ico b/subsystems/ntvdm/res/ntvdm.ico
new file mode 100644 (file)
index 0000000..161c1b0
Binary files /dev/null and b/subsystems/ntvdm/res/ntvdm.ico differ
index e7572ad..f7a6f3c 100644 (file)
@@ -1,5 +1,14 @@
 #pragma once
 
-#define RC_STRING_MAX_SIZE 2048
-#define STRING_WelcomeMsg  100
-#define STRING_PromptMsg   101
+#define ID_SHOWHIDE_MOUSE   1000
+#define ID_VDM_QUIT         1001
+
+#define IDS_HIDE_MOUSE  100
+#define IDS_SHOW_MOUSE  101
+#define IDS_VDM_MENU    102
+
+#define IDS_VDM_QUIT    200
+
+#define IDI_APPICON 1
+
+/* EOF */
diff --git a/subsystems/ntvdm/utils.c b/subsystems/ntvdm/utils.c
new file mode 100644 (file)
index 0000000..0619376
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            utils.c
+ * PURPOSE:         Utility Functions
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID
+FileClose(IN HANDLE FileHandle)
+{
+    CloseHandle(FileHandle);
+}
+
+HANDLE
+FileOpen(IN  PCSTR  FileName,
+         OUT PULONG FileSize OPTIONAL)
+{
+    HANDLE hFile;
+    ULONG  ulFileSize;
+
+    /* Open the file */
+    SetLastError(0); // For debugging purposes
+    hFile = CreateFileA(FileName,
+                        GENERIC_READ,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        FILE_ATTRIBUTE_NORMAL,
+                        NULL);
+    DPRINT1("File '%s' opening %s ; GetLastError() = %u\n",
+            FileName, hFile != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError());
+
+    /* If we failed, bail out */
+    if (hFile == INVALID_HANDLE_VALUE) return NULL;
+
+    /* OK, we have a handle to the file */
+
+    /*
+     * Retrieve the size of the file. In NTVDM we will handle files
+     * of maximum 1Mb so we can largely use GetFileSize only.
+     */
+    ulFileSize = GetFileSize(hFile, NULL);
+    if (ulFileSize == INVALID_FILE_SIZE && GetLastError() != ERROR_SUCCESS)
+    {
+        /* We failed, bail out */
+        DPRINT1("Error when retrieving file size, or size too large (%d)\n", ulFileSize);
+        FileClose(hFile);
+        return NULL;
+    }
+
+    /* Success, return file handle and size if needed */
+    if (FileSize) *FileSize = ulFileSize;
+    return hFile;
+}
+
+BOOLEAN
+FileLoadByHandle(IN  HANDLE FileHandle,
+                 IN  PVOID  Location,
+                 IN  ULONG  FileSize,
+                 OUT PULONG BytesRead)
+{
+    BOOLEAN Success;
+
+    /* Attempt to load the file into memory */
+    SetLastError(0); // For debugging purposes
+    Success = !!ReadFile(FileHandle,
+                         Location, // REAL_TO_PHYS(LocationRealPtr),
+                         FileSize,
+                         BytesRead,
+                         NULL);
+    DPRINT1("File loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
+
+    return Success;
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/utils.h b/subsystems/ntvdm/utils.h
new file mode 100644 (file)
index 0000000..98ce093
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            utils.h
+ * PURPOSE:         Utility Functions
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+FileClose(IN HANDLE FileHandle);
+
+HANDLE
+FileOpen(IN  PCSTR  FileName,
+         OUT PULONG FileSize OPTIONAL);
+
+BOOLEAN
+FileLoadByHandle(IN  HANDLE FileHandle,
+                 IN  PVOID  Location,
+                 IN  ULONG  FileSize,
+                 OUT PULONG BytesRead);
+
+#endif // _UTILS_H_
+
+/* EOF */
diff --git a/subsystems/ntvdm/vddsup.c b/subsystems/ntvdm/vddsup.c
new file mode 100644 (file)
index 0000000..92a0ff1
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vddsup.c
+ * PURPOSE:         Virtual Device Drivers (VDD) Support
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "vddsup.h"
+
+#include "bop.h"
+
+#include <isvbop.h>
+
+typedef VOID (WINAPI *VDD_PROC)(VOID);
+
+typedef struct _VDD_MODULE
+{
+    HMODULE  hDll;
+    VDD_PROC DispatchRoutine;
+} VDD_MODULE, *PVDD_MODULE;
+
+/* PRIVATE VARIABLES **********************************************************/
+
+// TODO: Maybe use a linked list.
+// But the number of elements must be <= MAXUSHORT (MAXWORD)
+#define MAX_VDD_MODULES 0xFF + 1
+VDD_MODULE VDDList[MAX_VDD_MODULES] = {{NULL}};
+
+// Valid handles of VDD DLLs start at 1 and finish at MAX_VDD_MODULES
+#define ENTRY_TO_HANDLE(Entry)  ((Entry)  + 1)
+#define HANDLE_TO_ENTRY(Handle) ((Handle) - 1)
+#define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES)
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+USHORT GetNextFreeVDDEntry(VOID)
+{
+    USHORT Entry = MAX_VDD_MODULES;
+    for (Entry = 0; Entry < sizeof(VDDList)/sizeof(VDDList[0]); ++Entry)
+    {
+        if (VDDList[Entry].hDll == NULL) break;
+    }
+    return Entry;
+}
+
+VOID WINAPI ThirdPartyVDDBop(LPWORD Stack)
+{
+    /* Get the Function Number and skip it */
+    BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+    setIP(getIP() + 1);
+
+    switch (FuncNum)
+    {
+        /* RegisterModule */
+        case 0:
+        {
+            BOOL Success = TRUE;
+            WORD RetVal  = 0;
+            WORD Entry   = 0;
+            LPCSTR DllName = NULL,
+                   InitRoutineName     = NULL,
+                   DispatchRoutineName = NULL;
+            HMODULE hDll = NULL;
+            VDD_PROC InitRoutine     = NULL,
+                     DispatchRoutine = NULL;
+
+            DPRINT("RegisterModule() called\n");
+
+            /* Clear the Carry Flag (no error happened so far) */
+            setCF(0);
+
+            /* Retrieve the next free entry in the table (used later on) */
+            Entry = GetNextFreeVDDEntry();
+            if (Entry >= MAX_VDD_MODULES)
+            {
+                DPRINT1("Failed to create a new VDD module entry\n");
+                Success = FALSE;
+                RetVal = 4;
+                goto Quit;
+            }
+
+            /* Retrieve the VDD name in DS:SI */
+            DllName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI());
+
+            /* Retrieve the initialization routine API name in ES:DI (optional --> ES=DI=0) */
+            if (TO_LINEAR(getES(), getDI()) != 0)
+                InitRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getES(), getDI());
+
+            /* Retrieve the dispatch routine API name in DS:BX */
+            DispatchRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getBX());
+
+            DPRINT1("DllName = '%s' - InitRoutineName = '%s' - DispatchRoutineName = '%s'\n",
+                    (DllName ? DllName : "n/a"),
+                    (InitRoutineName ? InitRoutineName : "n/a"),
+                    (DispatchRoutineName ? DispatchRoutineName : "n/a"));
+
+            /* Load the VDD DLL */
+            hDll = LoadLibraryA(DllName);
+            if (hDll == NULL)
+            {
+                DWORD LastError = GetLastError();
+                Success = FALSE;
+
+                if (LastError == ERROR_NOT_ENOUGH_MEMORY)
+                {
+                    DPRINT1("Not enough memory to load DLL '%s'\n", DllName);
+                    RetVal = 4;
+                    goto Quit;
+                }
+                else
+                {
+                    DPRINT1("Failed to load DLL '%s'; last error = %d\n", DllName, LastError);
+                    RetVal = 1;
+                    goto Quit;
+                }
+            }
+
+            /* Load the initialization routine if needed */
+            if (InitRoutineName)
+            {
+                InitRoutine = (VDD_PROC)GetProcAddress(hDll, InitRoutineName);
+                if (InitRoutine == NULL)
+                {
+                    DPRINT1("Failed to load the initialization routine '%s'\n", InitRoutineName);
+                    Success = FALSE;
+                    RetVal = 3;
+                    goto Quit;
+                }
+            }
+
+            /* Load the dispatch routine */
+            DispatchRoutine = (VDD_PROC)GetProcAddress(hDll, DispatchRoutineName);
+            if (DispatchRoutine == NULL)
+            {
+                DPRINT1("Failed to load the dispatch routine '%s'\n", DispatchRoutineName);
+                Success = FALSE;
+                RetVal = 2;
+                goto Quit;
+            }
+
+            /* If we arrived there, that means everything is OK */
+
+            /* Register the VDD DLL */
+            VDDList[Entry].hDll = hDll;
+            VDDList[Entry].DispatchRoutine = DispatchRoutine;
+
+            /* Call the initialization routine if needed */
+            if (InitRoutine) InitRoutine();
+
+            /* We succeeded. RetVal will contain a valid VDD DLL handle */
+            Success = TRUE;
+            RetVal  = ENTRY_TO_HANDLE(Entry); // Convert the entry to a valid handle
+
+Quit:
+            if (!Success)
+            {
+                /* Unload the VDD DLL */
+                if (hDll) FreeLibrary(hDll);
+
+                /* Set the Carry Flag to indicate that an error happened */
+                setCF(1);
+            }
+            // else
+            // {
+                // /* Clear the Carry Flag (success) */
+                // setCF(0);
+            // }
+            setAX(RetVal);
+            break;
+        }
+
+        /* UnRegisterModule */
+        case 1:
+        {
+            WORD Handle = getAX();
+            WORD Entry  = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry
+
+            DPRINT("UnRegisterModule() called\n");
+
+            /* Sanity checks */
+            if (!IS_VALID_HANDLE(Handle) || VDDList[Entry].hDll == NULL)
+            {
+                DPRINT1("Invalid VDD DLL Handle: %d\n", Entry);
+                /* Stop the VDM */
+                EmulatorTerminate();
+                return;
+            }
+
+            /* Unregister the VDD DLL */
+            FreeLibrary(VDDList[Entry].hDll);
+            VDDList[Entry].hDll = NULL;
+            VDDList[Entry].DispatchRoutine = NULL;
+            break;
+        }
+
+        /* DispatchCall */
+        case 2:
+        {
+            WORD Handle = getAX();
+            WORD Entry  = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry
+
+            DPRINT("DispatchCall() called\n");
+
+            /* Sanity checks */
+            if (!IS_VALID_HANDLE(Handle)    ||
+                VDDList[Entry].hDll == NULL ||
+                VDDList[Entry].DispatchRoutine == NULL)
+            {
+                DPRINT1("Invalid VDD DLL Handle: %d\n", Entry);
+                /* Stop the VDM */
+                EmulatorTerminate();
+                return;
+            }
+
+            /* Call the dispatch routine */
+            VDDList[Entry].DispatchRoutine();
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("Unknown 3rd-party VDD BOP Function: 0x%02X\n", FuncNum);
+            setCF(1);
+            break;
+        }
+    }
+}
+
+BOOL LoadInstallableVDD(VOID)
+{
+#define ERROR_MEMORYVDD L"Insufficient memory to load installable Virtual Device Drivers."
+#define ERROR_REGVDD    L"Virtual Device Driver format in the registry is invalid."
+#define ERROR_LOADVDD   L"An installable Virtual Device Driver failed Dll initialization."
+
+    BOOL  Success = TRUE;
+    LONG  Error   = 0;
+    DWORD Type    = 0;
+    DWORD BufSize = 0;
+
+    HKEY    hVDDKey;
+    LPCWSTR VDDKeyName   = L"SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers";
+    LPWSTR  VDDValueName = L"VDD";
+    LPWSTR  VDDList      = NULL;
+
+    HANDLE hVDD;
+
+    /* Try to open the VDD registry key */
+    Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                          VDDKeyName,
+                          0,
+                          KEY_QUERY_VALUE,
+                          &hVDDKey);
+    if (Error == ERROR_FILE_NOT_FOUND)
+    {
+        /* If the key just doesn't exist, don't do anything else */
+        return TRUE;
+    }
+    else if (Error != ERROR_SUCCESS)
+    {
+        /* The key exists but there was an access error: display an error and quit */
+        DisplayMessage(ERROR_REGVDD);
+        return FALSE;
+    }
+
+    /*
+     * Retrieve the size of the VDD registry value
+     * and check that it's of REG_MULTI_SZ type.
+     */
+    Error = RegQueryValueExW(hVDDKey,
+                             VDDValueName,
+                             NULL,
+                             &Type,
+                             NULL,
+                             &BufSize);
+    if (Error == ERROR_FILE_NOT_FOUND)
+    {
+        /* If the value just doesn't exist, don't do anything else */
+        Success = TRUE;
+        goto Quit;
+    }
+    else if (Error != ERROR_SUCCESS || Type != REG_MULTI_SZ)
+    {
+        /*
+         * The value exists but there was an access error or
+         * is of the wrong type: display an error and quit.
+         */
+        DisplayMessage(ERROR_REGVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Allocate the buffer */
+    BufSize = (BufSize < 2*sizeof(WCHAR) ? 2*sizeof(WCHAR) : BufSize);
+    VDDList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufSize);
+    if (VDDList == NULL)
+    {
+        DisplayMessage(ERROR_MEMORYVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Retrieve the list of VDDs to load */
+    if (RegQueryValueExW(hVDDKey,
+                         VDDValueName,
+                         NULL,
+                         NULL,
+                         (LPBYTE)VDDList,
+                         &BufSize) != ERROR_SUCCESS)
+    {
+        DisplayMessage(ERROR_REGVDD);
+        Success = FALSE;
+        goto Quit;
+    }
+
+    /* Load the VDDs */
+    VDDValueName = VDDList;
+    while (*VDDList)
+    {
+        DPRINT1("Loading VDD '%S'...", VDDList);
+        hVDD = LoadLibraryW(VDDList);
+        if (hVDD == NULL)
+        {
+            DbgPrint("Failed\n");
+            DisplayMessage(ERROR_LOADVDD);
+        }
+        else
+        {
+            DbgPrint("Succeeded\n");
+        }
+        /* Go to next string */
+        VDDList += wcslen(VDDList) + 1;
+    }
+    VDDList = VDDValueName;
+
+Quit:
+    if (VDDList) HeapFree(GetProcessHeap(), 0, VDDList);
+    RegCloseKey(hVDDKey);
+    return Success;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID VDDSupInitialize(VOID)
+{
+    /* Register the 3rd-party VDD BOP Handler */
+    RegisterBop(BOP_3RDPARTY, ThirdPartyVDDBop);
+
+    /* Load the installable VDDs from the registry */
+    LoadInstallableVDD();
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/vddsup.h b/subsystems/ntvdm/vddsup.h
new file mode 100644 (file)
index 0000000..4de9178
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            vddsup.h
+ * PURPOSE:         Virtual Device Drivers (VDD) Support
+ * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _VDDSUP_H_
+#define _VDDSUP_H_
+
+/* DEFINES ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+VOID VDDSupInitialize(VOID);
+
+#endif // _VDDSUP_H_
+
+/* EOF */
index 66e4efc..881156d 100644 (file)
@@ -22,6 +22,7 @@
 #include <ndk/psfuncs.h>
 #include <ndk/exfuncs.h>
 #include <ndk/umfuncs.h>
+#include <ndk/cmfuncs.h>
 
 /* PSEH for SEH Support */
 #include <pseh/pseh2.h>
index 49e9485..ef98ed3 100644 (file)
@@ -9,6 +9,7 @@
 /* INCLUDES *******************************************************************/
 
 #include "basesrv.h"
+#include "vdm.h"
 
 #include <winreg.h>
 
@@ -569,6 +570,14 @@ BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll)
     LoadedServerDll->SharedSection = BaseStaticServerData;
 }
 
+VOID
+NTAPI
+BaseSrvDisconnect(PCSR_PROCESS Process)
+{
+    /* Cleanup the VDM console records */
+    BaseSrvCleanupVdmRecords(HandleToUlong(Process->ClientId.UniqueProcess));
+}
+
 CSR_SERVER_DLL_INIT(ServerDllInitialization)
 {
     /* Setup the DLL Object */
@@ -581,7 +590,7 @@ CSR_SERVER_DLL_INIT(ServerDllInitialization)
 #endif
     LoadedServerDll->SizeOfProcessData = 0;
     LoadedServerDll->ConnectCallback = NULL;
-    LoadedServerDll->DisconnectCallback = NULL;
+    LoadedServerDll->DisconnectCallback = BaseSrvDisconnect;
     LoadedServerDll->ShutdownProcessCallback = NULL;
 
     BaseSrvDllInstance = LoadedServerDll->ServerHandle;
@@ -591,6 +600,9 @@ CSR_SERVER_DLL_INIT(ServerDllInitialization)
     /* Initialize DOS devices management */
     BaseInitDefineDosDevice();
 
+    /* Initialize VDM support */
+    BaseInitializeVDM();
+
     /* All done */
     return STATUS_SUCCESS;
 }
index e61405c..53113f7 100644 (file)
@@ -9,6 +9,7 @@
 /* INCLUDES *******************************************************************/
 
 #include "basesrv.h"
+#include "vdm.h"
 
 #define NDEBUG
 #include <debug.h>
@@ -167,7 +168,30 @@ CSR_API(BaseSrvCreateProcess)
 
     /* FIXME: Should notify user32 */
 
-    /* FIXME: VDM vodoo */
+    /* Check if this is a VDM process */
+    if (CreateProcessRequest->VdmBinaryType)
+    {
+        PVDM_CONSOLE_RECORD ConsoleRecord;
+
+        if (CreateProcessRequest->VdmTask != 0)
+        {
+            /* Get the console record using the task ID */
+            Status = GetConsoleRecordBySessionId(CreateProcessRequest->VdmTask,
+                                                 &ConsoleRecord);
+        }
+        else
+        {
+            /* Get the console record using the console handle */
+            Status = BaseSrvGetConsoleRecord(CreateProcessRequest->hVDM,
+                                             &ConsoleRecord);
+        }
+
+        /* Check if it failed */
+        if (!NT_SUCCESS(Status)) return Status;
+
+        /* Store the process ID of the VDM in the console record */
+        ConsoleRecord->ProcessId = HandleToUlong(CreateProcessRequest->ClientId.UniqueProcess);
+    }
 
     /* Return the result of this operation */
     return Status;
index 2ac4565..782918c 100644 (file)
  * FILE:            subsystems/win/basesrv/vdm.c
  * PURPOSE:         Virtual DOS Machines (VDM) Support
  * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *                  Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
  */
 
 /* INCLUDES *******************************************************************/
 
 #include "basesrv.h"
+#include "vdm.h"
 
 #define NDEBUG
 #include <debug.h>
 
+/* GLOBALS ********************************************************************/
+
+BOOLEAN FirstVDM = TRUE;
+LIST_ENTRY VDMConsoleListHead;
+RTL_CRITICAL_SECTION DosCriticalSection;
+RTL_CRITICAL_SECTION WowCriticalSection;
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record)
+{
+    PLIST_ENTRY i;
+    PVDM_CONSOLE_RECORD CurrentRecord = NULL;
+
+    /* NULL is not a valid console handle */
+    if (ConsoleHandle == NULL) return STATUS_INVALID_PARAMETER;
+
+    /* Search for a record that has the same console handle */
+    for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
+    {
+        CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
+        if (CurrentRecord->ConsoleHandle == ConsoleHandle) break;
+    }
+
+    /* Check if nothing was found */
+    if (i == &VDMConsoleListHead) CurrentRecord = NULL;
+
+    *Record = CurrentRecord;
+    return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND;
+}
+
+NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record)
+{
+    PLIST_ENTRY i;
+    PVDM_CONSOLE_RECORD CurrentRecord = NULL;
+
+    /* Search for a record that has the same console handle */
+    for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
+    {
+        CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
+        if (CurrentRecord->SessionId == TaskId) break;
+    }
+
+    /* Check if nothing was found */
+    if (i == &VDMConsoleListHead) CurrentRecord = NULL;
+
+    *Record = CurrentRecord;
+    return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND;
+}
+
+ULONG NTAPI GetNextDosSesId(VOID)
+{
+    ULONG SessionId;
+    PLIST_ENTRY i;
+    PVDM_CONSOLE_RECORD CurrentRecord = NULL;
+    BOOLEAN Found;
+
+    /* Search for an available session ID */
+    for (SessionId = 1; SessionId != 0; SessionId++)
+    {
+        Found = FALSE;
+
+        /* Check if the ID is already in use */
+        for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
+        {
+            CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
+            if (CurrentRecord->SessionId == SessionId) Found = TRUE;
+        }
+
+        /* If not, we found one */
+        if (!Found) break;
+    }
+
+    ASSERT(SessionId != 0);
+
+    /* Return the session ID */
+    return SessionId;
+}
+
+BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID)
+{
+    NTSTATUS Status;
+    BOOLEAN VdmAllowed = TRUE;
+    HANDLE RootKey, KeyHandle;
+    UNICODE_STRING KeyName, ValueName, MachineKeyName;
+    OBJECT_ATTRIBUTES Attributes;
+    UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
+    PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
+    ULONG ActualSize;
+
+    /* Initialize the unicode strings */
+    RtlInitUnicodeString(&MachineKeyName, L"\\Registry\\Machine");
+    RtlInitUnicodeString(&KeyName, VDM_POLICY_KEY_NAME);
+    RtlInitUnicodeString(&ValueName, VDM_DISALLOWED_VALUE_NAME);
+
+    InitializeObjectAttributes(&Attributes,
+                               &MachineKeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    /* Open the local machine key */
+    Status = NtOpenKey(&RootKey, KEY_READ, &Attributes);
+    if (!NT_SUCCESS(Status)) return FALSE;
+
+    InitializeObjectAttributes(&Attributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKey,
+                               NULL);
+
+    /* Open the policy key in the local machine hive, if it exists */
+    if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes)))
+    {
+        /* Read the value, if it's set */
+        if (NT_SUCCESS(NtQueryValueKey(KeyHandle,
+                                       &ValueName,
+                                       KeyValuePartialInformation,
+                                       ValueInfo,
+                                       sizeof(ValueBuffer),
+                                       &ActualSize)))
+        {
+            if (*((PULONG)ValueInfo->Data))
+            {
+                /* The VDM has been disabled in the registry */
+                VdmAllowed = FALSE;
+            }
+        }
+
+        NtClose(KeyHandle);
+    }
+
+    /* Close the local machine key */
+    NtClose(RootKey);
+
+    /* If it's disabled system-wide, there's no need to check the user key */
+    if (!VdmAllowed) return FALSE;
+
+    /* Open the current user key of the client */
+    if (!CsrImpersonateClient(NULL)) return VdmAllowed;
+    Status = RtlOpenCurrentUser(KEY_READ, &RootKey);
+    CsrRevertToSelf();
+
+    /* If that fails, return the system-wide setting */
+    if (!NT_SUCCESS(Status)) return VdmAllowed;
+
+    InitializeObjectAttributes(&Attributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKey,
+                               NULL);
+
+    /* Open the policy key in the current user hive, if it exists */
+    if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes)))
+    {
+        /* Read the value, if it's set */
+        if (NT_SUCCESS(NtQueryValueKey(KeyHandle,
+                                       &ValueName,
+                                       KeyValuePartialInformation,
+                                       ValueInfo,
+                                       sizeof(ValueBuffer),
+                                       &ActualSize)))
+        {
+            if (*((PULONG)ValueInfo->Data))
+            {
+                /* The VDM has been disabled in the registry */
+                VdmAllowed = FALSE;
+            }
+        }
+
+        NtClose(KeyHandle);
+    }
+
+    return VdmAllowed;
+}
+
+NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent)
+{
+    NTSTATUS Status;
+
+    /* Create the event */
+    Status = NtCreateEvent(ServerEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Duplicate the event into the client process */
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               *ServerEvent,
+                               CsrGetClientThread()->Process->ProcessHandle,
+                               ClientEvent,
+                               0,
+                               0,
+                               DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
+
+    if (!NT_SUCCESS(Status)) NtClose(*ServerEvent);
+    return Status;
+}
+
+VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo)
+{
+    /* Free the allocated structure members */
+    if (CommandInfo->CmdLine != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CmdLine);
+    if (CommandInfo->AppName != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->AppName);
+    if (CommandInfo->PifFile != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->PifFile);
+    if (CommandInfo->CurDirectory != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CurDirectory);
+    if (CommandInfo->Env != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Env);
+    if (CommandInfo->Desktop != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Desktop);
+    if (CommandInfo->Title != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Title);
+    if (CommandInfo->Reserved != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Reserved);
+
+    /* Free the structure itself */
+    RtlFreeHeap(BaseSrvHeap, 0, CommandInfo);
+}
+
+VOID NTAPI BaseSrvCleanupVdmRecords(ULONG ProcessId)
+{
+    PLIST_ENTRY i;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(&DosCriticalSection);
+
+    /* Search for a record that has the same process handle */
+    for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
+    {
+        ConsoleRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
+
+        if (ConsoleRecord->ProcessId == ProcessId)
+        {
+            /* Cleanup the DOS records */
+            while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead)
+            {
+                DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
+                                              VDM_DOS_RECORD,
+                                              Entry);
+
+                /* Set the event and close it */
+                NtSetEvent(DosRecord->ServerEvent, NULL);
+                NtClose(DosRecord->ServerEvent);
+
+                /* Remove the DOS entry */
+                if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+                RemoveEntryList(&DosRecord->Entry);
+                RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
+            }
+
+            if (ConsoleRecord->CurrentDirs != NULL)
+            {
+                /* Free the current directories */
+                RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs);
+                ConsoleRecord->CurrentDirs = NULL;
+                ConsoleRecord->CurDirsLength = 0;
+            }
+
+            /* Close the process handle */
+            if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle);
+
+            /* Close the event handle */
+            if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent);
+
+            /* Remove the console record */
+            i = i->Blink;
+            RemoveEntryList(&ConsoleRecord->Entry);
+            RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
+        }
+    }
+
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(&DosCriticalSection);
+}
+
+BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord)
+{
+    BOOLEAN Success = FALSE;
+    PVDM_COMMAND_INFO CommandInfo = NULL;
+
+    /* Allocate the command information structure */
+    CommandInfo = (PVDM_COMMAND_INFO)RtlAllocateHeap(BaseSrvHeap,
+                                                     HEAP_ZERO_MEMORY,
+                                                     sizeof(VDM_COMMAND_INFO));
+    if (CommandInfo == NULL) return FALSE;
+
+    /* Fill the structure */
+    CommandInfo->TaskId = CheckVdmRequest->iTask;
+    CommandInfo->ExitCode = DosRecord->ExitCode;
+    CommandInfo->CodePage = CheckVdmRequest->CodePage;
+    CommandInfo->StdIn = CheckVdmRequest->StdIn;
+    CommandInfo->StdOut = CheckVdmRequest->StdOut;
+    CommandInfo->StdErr = CheckVdmRequest->StdErr;
+
+    /* Allocate memory for the command line */
+    CommandInfo->CmdLine = RtlAllocateHeap(BaseSrvHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           CheckVdmRequest->CmdLen);
+    if (CommandInfo->CmdLine == NULL) goto Cleanup;
+
+    /* Copy the command line */
+    RtlMoveMemory(CommandInfo->CmdLine, CheckVdmRequest->CmdLine, CheckVdmRequest->CmdLen);
+
+    /* Allocate memory for the application name */
+    CommandInfo->AppName = RtlAllocateHeap(BaseSrvHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           CheckVdmRequest->AppLen);
+    if (CommandInfo->AppName == NULL) goto Cleanup;
+
+    /* Copy the application name */
+    RtlMoveMemory(CommandInfo->AppName, CheckVdmRequest->AppName, CheckVdmRequest->AppLen);
+
+    /* Allocate memory for the PIF file name */
+    if (CheckVdmRequest->PifLen != 0)
+    {
+        CommandInfo->PifFile = RtlAllocateHeap(BaseSrvHeap,
+                                               HEAP_ZERO_MEMORY,
+                                               CheckVdmRequest->PifLen);
+        if (CommandInfo->PifFile == NULL) goto Cleanup;
+
+        /* Copy the PIF file name */
+        RtlMoveMemory(CommandInfo->PifFile, CheckVdmRequest->PifFile, CheckVdmRequest->PifLen);
+    }
+    else CommandInfo->PifFile = NULL;
+
+    /* Allocate memory for the current directory */
+    if (CheckVdmRequest->CurDirectoryLen != 0)
+    {
+        CommandInfo->CurDirectory = RtlAllocateHeap(BaseSrvHeap,
+                                                    HEAP_ZERO_MEMORY,
+                                                    CheckVdmRequest->CurDirectoryLen);
+        if (CommandInfo->CurDirectory == NULL) goto Cleanup;
+
+        /* Copy the current directory */
+        RtlMoveMemory(CommandInfo->CurDirectory,
+                      CheckVdmRequest->CurDirectory,
+                      CheckVdmRequest->CurDirectoryLen);
+    }
+    else CommandInfo->CurDirectory = NULL;
+
+    /* Allocate memory for the environment block */
+    CommandInfo->Env = RtlAllocateHeap(BaseSrvHeap,
+                                       HEAP_ZERO_MEMORY,
+                                       CheckVdmRequest->EnvLen);
+    if (CommandInfo->Env == NULL) goto Cleanup;
+
+    /* Copy the environment block */
+    RtlMoveMemory(CommandInfo->Env, CheckVdmRequest->Env, CheckVdmRequest->EnvLen);
+
+    CommandInfo->EnvLen = CheckVdmRequest->EnvLen;
+    RtlMoveMemory(&CommandInfo->StartupInfo,
+                  CheckVdmRequest->StartupInfo,
+                  sizeof(STARTUPINFOA));
+    /* Allocate memory for the desktop */
+    if (CheckVdmRequest->DesktopLen != 0)
+    {
+        CommandInfo->Desktop = RtlAllocateHeap(BaseSrvHeap,
+                                               HEAP_ZERO_MEMORY,
+                                               CheckVdmRequest->DesktopLen);
+        if (CommandInfo->Desktop == NULL) goto Cleanup;
+
+        /* Copy the desktop name */
+        RtlMoveMemory(CommandInfo->Desktop, CheckVdmRequest->Desktop, CheckVdmRequest->DesktopLen);
+    }
+    else CommandInfo->Desktop = NULL;
+
+    CommandInfo->DesktopLen = CheckVdmRequest->DesktopLen;
+
+    /* Allocate memory for the title */
+    if (CheckVdmRequest->TitleLen != 0)
+    {
+        CommandInfo->Title = RtlAllocateHeap(BaseSrvHeap,
+                                             HEAP_ZERO_MEMORY,
+                                             CheckVdmRequest->TitleLen);
+        if (CommandInfo->Title == NULL) goto Cleanup;
+
+        /* Copy the title */
+        RtlMoveMemory(CommandInfo->Title, CheckVdmRequest->Title, CheckVdmRequest->TitleLen);
+    }
+    else CommandInfo->Title = NULL;
+
+    CommandInfo->TitleLen = CheckVdmRequest->TitleLen;
+
+    /* Allocate memory for the reserved field */
+    if (CheckVdmRequest->ReservedLen != 0)
+    {
+        CommandInfo->Reserved = RtlAllocateHeap(BaseSrvHeap,
+                                                HEAP_ZERO_MEMORY,
+                                                CheckVdmRequest->ReservedLen);
+        if (CommandInfo->Reserved == NULL) goto Cleanup;
+
+        /* Copy the reserved field */
+        RtlMoveMemory(CommandInfo->Reserved,
+                      CheckVdmRequest->Reserved,
+                      CheckVdmRequest->ReservedLen);
+    }
+    else CommandInfo->Reserved = NULL;
+
+    CommandInfo->ReservedLen = CheckVdmRequest->ReservedLen;
+
+    CommandInfo->CmdLen = CheckVdmRequest->CmdLen;
+    CommandInfo->AppLen = CheckVdmRequest->AppLen;
+    CommandInfo->PifLen = CheckVdmRequest->PifLen;
+    CommandInfo->CurDirectoryLen = CheckVdmRequest->CurDirectoryLen;
+    CommandInfo->VDMState = DosRecord->State;
+    // TODO: Set CommandInfo->CurrentDrive
+    // TODO: Set CommandInfo->ComingFromBat
+
+    /* Set the DOS record's command structure */
+    DosRecord->CommandInfo = CommandInfo;
+
+    /* The operation was successful */
+    Success = TRUE;
+
+Cleanup:
+    /* If it wasn't successful, free the memory */
+    if (!Success) BaseSrvFreeVDMInfo(CommandInfo);
+
+    return Success;
+}
+
+NTSTATUS NTAPI BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo,
+                                      PBASE_GET_NEXT_VDM_COMMAND Message)
+{
+    /* Copy the data */
+    Message->iTask = CommandInfo->TaskId;
+    Message->StdIn = CommandInfo->StdIn;
+    Message->StdOut = CommandInfo->StdOut;
+    Message->StdErr = CommandInfo->StdErr;
+    Message->CodePage = CommandInfo->CodePage;
+    Message->dwCreationFlags = CommandInfo->CreationFlags;
+    Message->ExitCode = CommandInfo->ExitCode;
+    Message->CurrentDrive = CommandInfo->CurrentDrive;
+    Message->VDMState = CommandInfo->VDMState;
+    Message->fComingFromBat = CommandInfo->ComingFromBat;
+
+    if (CommandInfo->CmdLen && Message->CmdLen)
+    {
+        if (Message->CmdLen < CommandInfo->CmdLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the command line */
+        RtlMoveMemory(Message->CmdLine, CommandInfo->CmdLine, CommandInfo->CmdLen);
+        Message->CmdLen = CommandInfo->CmdLen;
+    }
+
+    if (CommandInfo->AppLen && Message->AppLen)
+    {
+        if (Message->AppLen < CommandInfo->CmdLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the application name */
+        RtlMoveMemory(Message->AppName, CommandInfo->AppName, CommandInfo->AppLen);
+        Message->AppLen = CommandInfo->AppLen;
+    }
+
+    if (CommandInfo->PifLen && Message->PifLen)
+    {
+        if (Message->PifLen < CommandInfo->PifLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the PIF file name */
+        RtlMoveMemory(Message->PifFile, CommandInfo->PifFile, CommandInfo->PifLen);
+        Message->PifLen = CommandInfo->PifLen;
+    }
+
+    if (CommandInfo->CurDirectoryLen && Message->CurDirectoryLen)
+    {
+        if (Message->CurDirectoryLen < CommandInfo->CurDirectoryLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the current directory */
+        RtlMoveMemory(Message->CurDirectory, CommandInfo->CurDirectory, CommandInfo->CurDirectoryLen);
+        Message->CurDirectoryLen = CommandInfo->CurDirectoryLen;
+    }
+
+    if (CommandInfo->EnvLen && Message->EnvLen)
+    {
+        if (Message->EnvLen < CommandInfo->EnvLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the environment */
+        RtlMoveMemory(Message->Env, CommandInfo->Env, CommandInfo->EnvLen);
+        Message->EnvLen = CommandInfo->EnvLen;
+    }
+
+    /* Copy the startup info */
+    RtlMoveMemory(Message->StartupInfo,
+                  &CommandInfo->StartupInfo,
+                  sizeof(STARTUPINFOA));
+
+    if (CommandInfo->DesktopLen && Message->DesktopLen)
+    {
+        if (Message->DesktopLen < CommandInfo->DesktopLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the desktop name */
+        RtlMoveMemory(Message->Desktop, CommandInfo->Desktop, CommandInfo->DesktopLen);
+        Message->DesktopLen = CommandInfo->DesktopLen;
+    }
+
+    if (CommandInfo->TitleLen && Message->TitleLen)
+    {
+        if (Message->TitleLen < CommandInfo->TitleLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the title */
+        RtlMoveMemory(Message->Title, CommandInfo->Title, CommandInfo->TitleLen);
+        Message->TitleLen = CommandInfo->TitleLen;
+    }
+
+    if (CommandInfo->ReservedLen && Message->ReservedLen)
+    {
+        if (Message->ReservedLen < CommandInfo->ReservedLen) return STATUS_BUFFER_TOO_SMALL;
+
+        /* Copy the reserved parameter */
+        RtlMoveMemory(Message->Reserved, CommandInfo->Reserved, CommandInfo->ReservedLen);
+        Message->ReservedLen = CommandInfo->ReservedLen;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+VOID NTAPI BaseInitializeVDM(VOID)
+{
+    /* Initialize the list head */
+    InitializeListHead(&VDMConsoleListHead);
+
+    /* Initialize the critical section */
+    RtlInitializeCriticalSection(&DosCriticalSection);
+    RtlInitializeCriticalSection(&WowCriticalSection);
+}
+
 /* PUBLIC SERVER APIS *********************************************************/
 
 CSR_API(BaseSrvCheckVDM)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_CHECK_VDM CheckVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CheckVDMRequest;
+    PRTL_CRITICAL_SECTION CriticalSection = NULL;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord = NULL;
+    BOOLEAN NewConsoleRecord = FALSE;
+
+    /* Don't do anything if the VDM has been disabled in the registry */
+    if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED;
+
+    /* Validate the message buffers */
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&CheckVdmRequest->CmdLine,
+                                  CheckVdmRequest->CmdLen,
+                                  sizeof(*CheckVdmRequest->CmdLine))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->AppName,
+                                     CheckVdmRequest->AppLen,
+                                     sizeof(*CheckVdmRequest->AppName))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->PifFile,
+                                     CheckVdmRequest->PifLen,
+                                     sizeof(*CheckVdmRequest->PifFile))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->CurDirectory,
+                                     CheckVdmRequest->CurDirectoryLen,
+                                     sizeof(*CheckVdmRequest->CurDirectory))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->Desktop,
+                                     CheckVdmRequest->DesktopLen,
+                                     sizeof(*CheckVdmRequest->Desktop))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->Title,
+                                     CheckVdmRequest->TitleLen,
+                                     sizeof(*CheckVdmRequest->Title))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&CheckVdmRequest->Reserved,
+                                     CheckVdmRequest->ReservedLen,
+                                     sizeof(*CheckVdmRequest->Reserved)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    CriticalSection = (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
+                      ? &DosCriticalSection
+                      : &WowCriticalSection;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(CriticalSection);
+
+    /* Check if this is a DOS or WOW VDM */
+    if (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
+    {
+        /* Get the console record */
+        Status = BaseSrvGetConsoleRecord(CheckVdmRequest->ConsoleHandle,
+                                         &ConsoleRecord);
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* Allocate a new console record */
+            ConsoleRecord = (PVDM_CONSOLE_RECORD)RtlAllocateHeap(BaseSrvHeap,
+                                                                 HEAP_ZERO_MEMORY,
+                                                                 sizeof(VDM_CONSOLE_RECORD));
+            if (ConsoleRecord == NULL)
+            {
+                Status = STATUS_NO_MEMORY;
+                goto Cleanup;
+            }
+
+            /* Remember that the console record was allocated here */
+            NewConsoleRecord = TRUE;
+
+            /* Initialize the console record */
+            ConsoleRecord->ConsoleHandle = CheckVdmRequest->ConsoleHandle;
+            ConsoleRecord->ProcessHandle = NULL;
+            ConsoleRecord->ServerEvent = ConsoleRecord->ClientEvent = NULL;
+            ConsoleRecord->ReenterCount = 0;
+            ConsoleRecord->CurrentDirs = NULL;
+            ConsoleRecord->CurDirsLength = 0;
+            ConsoleRecord->SessionId = GetNextDosSesId();
+            InitializeListHead(&ConsoleRecord->DosListHead);
+        }
+
+        /* Allocate a new DOS record */
+        DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap,
+                                                     HEAP_ZERO_MEMORY,
+                                                     sizeof(VDM_DOS_RECORD));
+        if (DosRecord == NULL)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto Cleanup;
+        }
+
+        /* Initialize the DOS record */
+        DosRecord->State = VDM_NOT_LOADED;
+        DosRecord->ExitCode = 0;
+
+        Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent);
+        if (!NT_SUCCESS(Status)) goto Cleanup;
+
+        /* Return the client event handle */
+        CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent;
+
+        /* Translate the input structure into a VDM command structure and set it in the DOS record */
+        if (!BaseSrvCopyCommand(CheckVdmRequest, DosRecord))
+        {
+            /* The only possibility is that an allocation failure occurred */
+            Status = STATUS_NO_MEMORY;
+            goto Cleanup;
+        }
+
+        /* Add the DOS record */
+        InsertHeadList(&ConsoleRecord->DosListHead, &DosRecord->Entry);
+
+        if (ConsoleRecord->ServerEvent)
+        {
+            /* Signal the session event */
+            NtSetEvent(ConsoleRecord->ServerEvent, NULL);
+        }
+
+        if (NewConsoleRecord)
+        {
+            /* Add the console record */
+            InsertTailList(&VDMConsoleListHead, &ConsoleRecord->Entry);
+        }
+
+        if (ConsoleRecord->ConsoleHandle == NULL)
+        {
+            /* The parent doesn't have a console, so return the session ID */
+            CheckVdmRequest->iTask = ConsoleRecord->SessionId;
+        }
+        else CheckVdmRequest->iTask = 0;
+
+        CheckVdmRequest->VDMState = NewConsoleRecord ? VDM_NOT_LOADED : VDM_READY;
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        // TODO: NOT IMPLEMENTED
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+    }
+
+Cleanup:
+    /* Check if it failed */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Free the DOS record */
+        if (DosRecord != NULL)
+        {
+            if (DosRecord->ServerEvent) NtClose(DosRecord->ServerEvent);
+            if (DosRecord->ClientEvent)
+            {
+                /* Close the remote handle */
+                NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle,
+                                  DosRecord->ClientEvent,
+                                  NULL,
+                                  NULL,
+                                  0,
+                                  0,
+                                  DUPLICATE_CLOSE_SOURCE);
+            }
+
+            RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
+            DosRecord = NULL;
+        }
+
+        /* Free the console record if it was allocated here */
+        if (NewConsoleRecord)
+        {
+            RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
+            ConsoleRecord = NULL;
+        }
+    }
+
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(CriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvUpdateVDMEntry)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.UpdateVDMEntryRequest;
+    PRTL_CRITICAL_SECTION CriticalSection = NULL;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord = NULL;
+
+    CriticalSection = (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
+                      ? &DosCriticalSection
+                      : &WowCriticalSection;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(CriticalSection);
+
+    /* Check if this is a DOS or WOW VDM */
+    if (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
+    {
+        if (UpdateVdmEntryRequest->iTask != 0)
+        {
+            /* Get the console record using the task ID */
+            Status = GetConsoleRecordBySessionId(UpdateVdmEntryRequest->iTask,
+                                                 &ConsoleRecord);
+        }
+        else
+        {
+            /* Get the console record using the console handle */
+            Status = BaseSrvGetConsoleRecord(UpdateVdmEntryRequest->ConsoleHandle,
+                                             &ConsoleRecord);
+        }
+
+        if (!NT_SUCCESS(Status)) goto Cleanup;
+
+        /* Get the primary DOS record */
+        DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
+                                                       VDM_DOS_RECORD,
+                                                       Entry);
+
+        switch (UpdateVdmEntryRequest->EntryIndex)
+        {
+            case VdmEntryUndo:
+            {
+                /* Close the server event handle, the client will close the client handle */
+                NtClose(DosRecord->ServerEvent);
+                DosRecord->ServerEvent = DosRecord->ClientEvent = NULL;
+
+                if (UpdateVdmEntryRequest->VDMCreationState & (VDM_UNDO_PARTIAL | VDM_UNDO_FULL))
+                {
+                    /* Remove the DOS record */
+                    if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+                    RemoveEntryList(&DosRecord->Entry);
+                    RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
+
+                    /*
+                     * Since this is an undo, if that was the only DOS record the VDM
+                     * won't even start, so the console record should be removed too.
+                     */
+                    if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead)
+                    {
+                        if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle);
+                        if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent);
+                        RemoveEntryList(&ConsoleRecord->Entry);
+                        RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
+                    }
+                }
+
+                /* It was successful */
+                Status = STATUS_SUCCESS;
+
+                break;
+            }
+
+            case VdmEntryUpdateProcess:
+            {
+                /* Duplicate the VDM process handle */
+                Status = NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle,
+                                           UpdateVdmEntryRequest->VDMProcessHandle,
+                                           NtCurrentProcess(),
+                                           &ConsoleRecord->ProcessHandle,
+                                           0,
+                                           0,
+                                           DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
+                if (!NT_SUCCESS(Status)) goto Cleanup;
+
+                /* Create a pair of handles to one event object */
+                Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent,
+                                                      &DosRecord->ClientEvent);
+                if (!NT_SUCCESS(Status)) goto Cleanup;
+
+                /* Return the client event handle */
+                UpdateVdmEntryRequest->WaitObjectForParent = DosRecord->ClientEvent;
+
+                break;
+            }
+
+            case VdmEntryUpdateControlCHandler:
+            {
+                // TODO: NOT IMPLEMENTED
+                DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!");
+                Status = STATUS_NOT_IMPLEMENTED;
+
+                break;
+            }
+
+            default:
+            {
+                /* Invalid */
+                Status = STATUS_INVALID_PARAMETER;
+            }
+        }
+    }
+    else
+    {
+        // TODO: NOT IMPLEMENTED
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+    }
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(CriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvGetNextVDMCommand)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest =
+    &((PBASE_API_MESSAGE)ApiMessage)->Data.GetNextVDMCommandRequest;
+    PRTL_CRITICAL_SECTION CriticalSection;
+    PLIST_ENTRY i = NULL;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord = NULL;
+
+    /* Validate the message buffers */
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&GetNextVdmCommandRequest->CmdLine,
+                                  GetNextVdmCommandRequest->CmdLen,
+                                  sizeof(*GetNextVdmCommandRequest->CmdLine))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->AppName,
+                                     GetNextVdmCommandRequest->AppLen,
+                                     sizeof(*GetNextVdmCommandRequest->AppName))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->PifFile,
+                                     GetNextVdmCommandRequest->PifLen,
+                                     sizeof(*GetNextVdmCommandRequest->PifFile))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->CurDirectory,
+                                     GetNextVdmCommandRequest->CurDirectoryLen,
+                                     sizeof(*GetNextVdmCommandRequest->CurDirectory))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->Env,
+                                     GetNextVdmCommandRequest->EnvLen,
+                                     sizeof(*GetNextVdmCommandRequest->Env))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->Desktop,
+                                     GetNextVdmCommandRequest->DesktopLen,
+                                     sizeof(*GetNextVdmCommandRequest->Desktop))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->Title,
+                                     GetNextVdmCommandRequest->TitleLen,
+                                     sizeof(*GetNextVdmCommandRequest->Title))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->Reserved,
+                                     GetNextVdmCommandRequest->ReservedLen,
+                                     sizeof(*GetNextVdmCommandRequest->Reserved))
+        || !CsrValidateMessageBuffer(ApiMessage,
+                                     (PVOID*)&GetNextVdmCommandRequest->StartupInfo,
+                                     1,
+                                     sizeof(STARTUPINFOA)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    CriticalSection = (GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)
+                      ? &WowCriticalSection
+                      : &DosCriticalSection;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(CriticalSection);
+
+    if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW))
+    {
+        if (GetNextVdmCommandRequest->iTask != 0)
+        {
+            /* Get the console record using the task ID */
+            Status = GetConsoleRecordBySessionId(GetNextVdmCommandRequest->iTask,
+                                                 &ConsoleRecord);
+        }
+        else
+        {
+            /* Get the console record using the console handle */
+            Status = BaseSrvGetConsoleRecord(GetNextVdmCommandRequest->ConsoleHandle,
+                                             &ConsoleRecord);
+        }
+
+        /* Make sure we found the console record */
+        if (!NT_SUCCESS(Status)) goto Cleanup;
+
+        /* Return the session ID */
+        GetNextVdmCommandRequest->iTask = ConsoleRecord->SessionId;
+        GetNextVdmCommandRequest->WaitObjectForVDM = NULL;
+
+        if (GetNextVdmCommandRequest->VDMState & VDM_GET_FIRST_COMMAND)
+        {
+            /* Check if the DOS record list is empty */
+            if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Get the first DOS record */
+            DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, VDM_DOS_RECORD, Entry);
+
+            /* Make sure its command information is still there */
+            if (DosRecord->CommandInfo == NULL)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Fill the command information */
+            Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest);
+            goto Cleanup;
+        }
+
+        /* Check if we should set the state of a running DOS record to ready */
+        if (!(GetNextVdmCommandRequest->VDMState
+            & (VDM_FLAG_FIRST_TASK | VDM_FLAG_RETRY | VDM_FLAG_NESTED_TASK)))
+        {
+            /* Search for a DOS record that is currently running */
+            for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
+            {
+                DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
+                if (DosRecord->State == VDM_NOT_READY) break;
+            }
+
+            /* Check if we found any */
+            if (i == &ConsoleRecord->DosListHead)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Set the exit code */
+            DosRecord->ExitCode = GetNextVdmCommandRequest->ExitCode;
+
+            /* Update the VDM state */
+            DosRecord->State = VDM_READY; 
+
+            /* Notify all waiting threads that the task is finished */
+            NtSetEvent(DosRecord->ServerEvent, NULL);
+            NtClose(DosRecord->ServerEvent);
+            DosRecord->ServerEvent = NULL;
+        }
+
+        /* Search for a DOS record that isn't loaded yet */
+        for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
+        {
+            DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
+            if (DosRecord->State == VDM_NOT_LOADED) break;
+        }
+
+        if (i != &ConsoleRecord->DosListHead)
+        {
+            /* DOS tasks which haven't been loaded yet should have a command info structure */
+            ASSERT(DosRecord->CommandInfo != NULL);
+
+            /* Check if the caller only wants environment data */
+            if (GetNextVdmCommandRequest->VDMState & VDM_GET_ENVIRONMENT)
+            {
+                if (GetNextVdmCommandRequest->EnvLen < DosRecord->CommandInfo->EnvLen)
+                {
+                    /* Not enough space was reserved */
+                    GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen;
+                    Status = STATUS_BUFFER_OVERFLOW;
+                    goto Cleanup;
+                }
+
+                /* Copy the environment data */
+                RtlMoveMemory(GetNextVdmCommandRequest->Env,
+                              DosRecord->CommandInfo->Env,
+                              DosRecord->CommandInfo->EnvLen);
+
+                /* Return the actual size to the caller */
+                GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen;
+            }
+            else
+            {
+                /* Fill the command information */
+                Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest);
+
+                /* Free the command information, it's no longer needed */
+                BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+                DosRecord->CommandInfo = NULL;
+
+                /* Update the VDM state */
+                GetNextVdmCommandRequest->VDMState = DosRecord->State = VDM_NOT_READY;
+            }
+
+            Status = STATUS_SUCCESS;
+            goto Cleanup;
+        }
+    }
+    else
+    {
+        // TODO: WOW SUPPORT NOT IMPLEMENTED
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto Cleanup;
+    }
+
+    /* There is no command yet */
+    if ((GetNextVdmCommandRequest->VDMState & (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY))
+        != (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY))
+    {
+        if (ConsoleRecord->ServerEvent)
+        {
+            /* Reset the event */
+            NtResetEvent(ConsoleRecord->ServerEvent, NULL);
+        }
+        else
+        {
+            /* Create a pair of wait handles */
+            Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent,
+                                                  &ConsoleRecord->ClientEvent);
+            if (!NT_SUCCESS(Status)) goto Cleanup;
+        }
+
+        /* Return the client event handle */
+        GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent;
+    }
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(CriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvExitVDM)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_EXIT_VDM ExitVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ExitVDMRequest;
+    PRTL_CRITICAL_SECTION CriticalSection = NULL;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord;
+
+    CriticalSection = (ExitVdmRequest->iWowTask == 0)
+                      ? &DosCriticalSection
+                      : &WowCriticalSection;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(CriticalSection);
+
+    if (ExitVdmRequest->iWowTask == 0)
+    {
+        /* Get the console record */
+        Status = BaseSrvGetConsoleRecord(ExitVdmRequest->ConsoleHandle, &ConsoleRecord);
+        if (!NT_SUCCESS(Status)) goto Cleanup;
+
+        /* Cleanup the DOS records */
+        while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead)
+        {
+            DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
+                                          VDM_DOS_RECORD,
+                                          Entry);
+
+            /* Set the event and close it */
+            NtSetEvent(DosRecord->ServerEvent, NULL);
+            NtClose(DosRecord->ServerEvent);
+
+            /* Remove the DOS entry */
+            if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+            RemoveEntryList(&DosRecord->Entry);
+            RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
+        }
+
+        if (ConsoleRecord->CurrentDirs != NULL)
+        {
+            /* Free the current directories */
+            RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs);
+            ConsoleRecord->CurrentDirs = NULL;
+            ConsoleRecord->CurDirsLength = 0;
+        }
+
+        /* Close the event handle */
+        if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent);
+
+        /* Remove the console record */
+        RemoveEntryList(&ConsoleRecord->Entry);
+        RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
+    }
+    else
+    {
+        // TODO: NOT IMPLEMENTED
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+    }
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(CriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvIsFirstVDM)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    PBASE_IS_FIRST_VDM IsFirstVDMRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.IsFirstVDMRequest;
+
+    /* Return the result */
+    IsFirstVDMRequest->FirstVDM = FirstVDM;
+
+    /* Clear the first VDM flag */
+    FirstVDM = FALSE;
+
+    return STATUS_SUCCESS;
 }
 
 CSR_API(BaseSrvGetVDMExitCode)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetVDMExitCodeRequest;
+    PLIST_ENTRY i = NULL;
+    PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
+    PVDM_DOS_RECORD DosRecord = NULL;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(&DosCriticalSection);
+
+    /* Get the console record */
+    Status = BaseSrvGetConsoleRecord(GetVDMExitCodeRequest->ConsoleHandle, &ConsoleRecord);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    /* Search for a DOS record that has the same parent process handle */
+    for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
+    {
+        DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
+        if (DosRecord->ClientEvent == GetVDMExitCodeRequest->hParent) break;
+    }
+
+    /* Check if no DOS record was found */
+    if (i == &ConsoleRecord->DosListHead)
+    {
+        Status = STATUS_NOT_FOUND;
+        goto Cleanup;
+    }
+
+    /* Check if this task is still running */
+    if (DosRecord->State == VDM_READY)
+    {
+        GetVDMExitCodeRequest->ExitCode = STATUS_PENDING;
+        goto Cleanup;
+    }
+
+    /* Return the exit code */
+    GetVDMExitCodeRequest->ExitCode = DosRecord->ExitCode;
+
+    /* Since this is a zombie task record, remove it */
+    if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+    RemoveEntryList(&DosRecord->Entry);
+    RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(&DosCriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvSetReenterCount)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PBASE_SET_REENTER_COUNT SetReenterCountRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.SetReenterCountRequest;
+    PVDM_CONSOLE_RECORD ConsoleRecord;
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(&DosCriticalSection);
+
+    /* Get the console record */
+    Status = BaseSrvGetConsoleRecord(SetReenterCountRequest->ConsoleHandle, &ConsoleRecord);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    if (SetReenterCountRequest->fIncDec == VDM_INC_REENTER_COUNT) ConsoleRecord->ReenterCount++;
+    else if (SetReenterCountRequest->fIncDec == VDM_DEC_REENTER_COUNT)
+    {
+        ConsoleRecord->ReenterCount--;
+        if (ConsoleRecord->ServerEvent != NULL) NtSetEvent(ConsoleRecord->ServerEvent, NULL);
+    }
+    else Status = STATUS_INVALID_PARAMETER;
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(&DosCriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvSetVDMCurDirs)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest;
+    PVDM_CONSOLE_RECORD ConsoleRecord;
+    PCHAR Buffer = NULL;
+
+    /* Validate the input buffer */
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs,
+                                  VDMCurrentDirsRequest->cchCurDirs,
+                                  sizeof(*VDMCurrentDirsRequest->lpszzCurDirs)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(&DosCriticalSection);
+
+    /* Find the console record */
+    Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    if (ConsoleRecord->CurrentDirs == NULL)
+    {
+        /* Allocate memory for the current directory information */
+        Buffer = RtlAllocateHeap(BaseSrvHeap,
+                                 HEAP_ZERO_MEMORY,
+                                 VDMCurrentDirsRequest->cchCurDirs);
+    }
+    else
+    {
+        /* Resize the amount of allocated memory */
+        Buffer = RtlReAllocateHeap(BaseSrvHeap,
+                                   HEAP_ZERO_MEMORY,
+                                   ConsoleRecord->CurrentDirs,
+                                   VDMCurrentDirsRequest->cchCurDirs);
+    }
+
+    if (Buffer == NULL)
+    {
+        /* Allocation failed */
+        Status = STATUS_NO_MEMORY;
+        goto Cleanup;
+    }
+
+    /* Update the console record */
+    ConsoleRecord->CurrentDirs = Buffer;
+    ConsoleRecord->CurDirsLength = VDMCurrentDirsRequest->cchCurDirs;
+
+    /* Copy the data */
+    RtlMoveMemory(ConsoleRecord->CurrentDirs,
+                  VDMCurrentDirsRequest->lpszzCurDirs,
+                  VDMCurrentDirsRequest->cchCurDirs);
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(&DosCriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvGetVDMCurDirs)
 {
-    DPRINT1("%s not yet implemented\n", __FUNCTION__);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest;
+    PVDM_CONSOLE_RECORD ConsoleRecord;
+
+    /* Validate the output buffer */
+    if (!CsrValidateMessageBuffer(ApiMessage,
+                                  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs,
+                                  VDMCurrentDirsRequest->cchCurDirs,
+                                  sizeof(*VDMCurrentDirsRequest->lpszzCurDirs)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Enter the critical section */
+    RtlEnterCriticalSection(&DosCriticalSection);
+
+    /* Find the console record */
+    Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    /* Return the actual size of the current directory information */
+    VDMCurrentDirsRequest->cchCurDirs = ConsoleRecord->CurDirsLength;
+
+    /* Check if the buffer is large enough */
+    if (VDMCurrentDirsRequest->cchCurDirs < ConsoleRecord->CurDirsLength)
+    {
+        Status = STATUS_BUFFER_TOO_SMALL;
+        goto Cleanup;
+    }
+
+    /* Copy the data */
+    RtlMoveMemory(VDMCurrentDirsRequest->lpszzCurDirs,
+                  ConsoleRecord->CurrentDirs,
+                  ConsoleRecord->CurDirsLength);
+
+Cleanup:
+    /* Leave the critical section */
+    RtlLeaveCriticalSection(&DosCriticalSection);
+
+    return Status;
 }
 
 CSR_API(BaseSrvBatNotification)
diff --git a/subsystems/win/basesrv/vdm.h b/subsystems/win/basesrv/vdm.h
new file mode 100644 (file)
index 0000000..3da59d9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Base API Server DLL
+ * FILE:            subsystems/win/basesrv/vdm.h
+ * PURPOSE:         VDM Definitions
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef __VDM_H__
+#define __VDM_H__
+
+#include <win/vdm.h>
+
+/* DEFINITIONS ****************************************************************/
+
+#define VDM_POLICY_KEY_NAME L"Software\\Policies\\Microsoft\\Windows\\AppCompat"
+#define VDM_DISALLOWED_VALUE_NAME L"VDMDisallowed"
+
+typedef struct _VDM_CONSOLE_RECORD
+{
+    LIST_ENTRY Entry;
+    HANDLE ConsoleHandle;
+    HANDLE ProcessHandle;
+    HANDLE ServerEvent;
+    HANDLE ClientEvent;
+    ULONG ProcessId;
+    ULONG ReenterCount;
+    PCHAR CurrentDirs;
+    ULONG CurDirsLength;
+    ULONG SessionId;
+    LIST_ENTRY DosListHead;
+} VDM_CONSOLE_RECORD, *PVDM_CONSOLE_RECORD;
+
+typedef struct _VDM_DOS_RECORD
+{
+    LIST_ENTRY Entry;
+    USHORT State;
+    ULONG ExitCode;
+    HANDLE ServerEvent;
+    HANDLE ClientEvent;
+    PVDM_COMMAND_INFO CommandInfo;
+} VDM_DOS_RECORD, *PVDM_DOS_RECORD;
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record);
+NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record);
+ULONG NTAPI GetNextDosSesId(VOID);
+BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID);
+NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent);
+VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo);
+VOID NTAPI BaseSrvCleanupVdmRecords(ULONG ProcessId);
+BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord);
+NTSTATUS NTAPI BaseSrvFillCommandInfo(
+    PVDM_COMMAND_INFO CommandInfo,
+    PBASE_GET_NEXT_VDM_COMMAND Message
+);
+VOID NTAPI BaseInitializeVDM(VOID);
+
+#endif // __VDM_H__
index d682c37..451f269 100644 (file)
@@ -605,15 +605,18 @@ CsrCreateProcess(IN HANDLE hProcess,
     }
 
     /* Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
-    if ((Flags & CsrProcessCreateNewGroup) == 0)
+    if (Flags & CsrProcessCreateNewGroup)
     {
-        /* Create new data */
+        /*
+         * We create the process group leader of a new process group, therefore
+         * its process group ID and sequence number are its own ones.
+         */
         CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess);
         CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber;
     }
     else
     {
-        /* Copy it from the current process */
+        /* Inherit the process group ID and sequence number from the current process */
         CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId;
         CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence;
     }
index 96df922..bfca706 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "videoprt.h"
+#include <stdio.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -33,30 +34,24 @@ IntVideoPortGetMonitorId(
     IN OUT PWCHAR Buffer)
 {
     USHORT Manufacturer, Model;
-    UNICODE_STRING UnicodeModelStr;
 
     /* This must be valid to call this function */
     ASSERT(ChildExtension->EdidValid);
 
     /* 3 letters 5-bit ANSI manufacturer code (big endian) */
-    Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]);
-
     /* Letters encoded as A=1 to Z=26 */
-    Buffer[0] = (WCHAR)((Manufacturer & 0x7C00) + 'A' - 1);
-    Buffer[1] = (WCHAR)((Manufacturer & 0x03E0) + 'A' - 1);
-    Buffer[2] = (WCHAR)((Manufacturer & 0x001F) + 'A' - 1);
+    Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]);
 
     /* Model number (16-bit little endian) */
     Model = *(PUSHORT)(&ChildExtension->ChildDescriptor[10]);
 
-    /* Use Rtl helper for conversion */
-    UnicodeModelStr.Buffer = &Buffer[3];
-    UnicodeModelStr.Length = 0;
-    UnicodeModelStr.MaximumLength = 4 * sizeof(WCHAR);
-    RtlIntegerToUnicodeString(Model, 16, &UnicodeModelStr);
-
-    /* Terminate it */
-    Buffer[7] = UNICODE_NULL;
+    /* Convert the Monitor ID to a readable form */
+    swprintf(Buffer,
+             L"%C%C%C%04hx",
+             (WCHAR)((Manufacturer >> 10 & 0x001F) + 'A' - 1),
+             (WCHAR)((Manufacturer >> 5 & 0x001F) + 'A' - 1),
+             (WCHAR)((Manufacturer & 0x001F) + 'A' - 1),
+             Model);
 
     /* And we're done */
     return TRUE;
index ab6e8ac..77b00a4 100644 (file)
@@ -134,7 +134,7 @@ EngMapEvent(
     /* Create a handle, and have Ob fill out the pKEvent field */
     Status = ObReferenceObjectByHandle(EngEvent,
                                        EVENT_ALL_ACCESS,
-                                       ExEventObjectType,
+                                       *ExEventObjectType,
                                        UserMode,
                                        &EngEvent->pKEvent,
                                        NULL);
index 7d887b1..26f9aec 100644 (file)
@@ -114,7 +114,7 @@ HackSecureVirtualMemory(
     else if (ProbeMode == PAGE_READWRITE) Operation = IoModifyAccess;
     else return NULL;
 
-    pmdl = IoAllocateMdl(Address, Size, FALSE, TRUE, NULL);
+    pmdl = IoAllocateMdl(Address, (ULONG)Size, FALSE, TRUE, NULL);
     if (pmdl == NULL)
     {
         return NULL;
index e1ed160..fb39f5a 100644 (file)
@@ -329,7 +329,6 @@ typedef struct tagITEM
     INT cyBmp;     /* Height " */
     //// ReactOS
     UNICODE_STRING lpstr;
-    struct tagITEM *Next;
 } ITEM, *PITEM;
 
 typedef struct tagMENULIST
@@ -369,7 +368,7 @@ typedef struct tagMENU
     DWORD dwArrowsOn:2;       /* Arrows: 0 off, 1 on, 2 to the top, 3 to the bottom. */
     //// ReactOS
     LIST_ENTRY ListEntry;
-    HWND hWnd;           /* Window containing the menu */
+    HWND hWnd;           /* Window containing the menu, use POPUPMENU */
     BOOL TimeToHide;
 } MENU, *PMENU;
 
index f43ee5e..7777c50 100644 (file)
@@ -99,7 +99,7 @@ co_IntTranslateAccelerator(
     /* Check if accelerator is associated with menu command */
     hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu;
     hSubMenu = NULL;
-    MenuObject = IntGetMenuObject(hMenu);
+    MenuObject = UserGetMenuObject(hMenu);
     nPos = pAccel->cmd;
     if (MenuObject)
     {
@@ -113,7 +113,7 @@ co_IntTranslateAccelerator(
         /* Check system menu now */
         hMenu = Window->SystemMenu;
         hSubMenu = hMenu; /* system menu is a popup menu */
-        MenuObject = IntGetMenuObject(hMenu);
+        MenuObject = UserGetMenuObject(hMenu);
         nPos = pAccel->cmd;
         if (MenuObject)
         {
index 4485c5d..905fa04 100644 (file)
@@ -320,7 +320,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
        goto error;
     }
     Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
-                                       ExEventObjectType, KernelMode,
+                                       *ExEventObjectType, KernelMode,
                                        (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
     if (!NT_SUCCESS(Status))
     {
index f4c4e4c..f46ea91 100644 (file)
@@ -11,6 +11,8 @@ DBG_DEFAULT_CHANNEL(UserMenu);
 
 /* INTERNAL ******************************************************************/
 
+BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING);
+
 /* maximum allowed depth of any branch in the menu tree.
  * This value is slightly larger than in windows (25) to
  * stay on the safe side. */
@@ -23,16 +25,29 @@ DBG_DEFAULT_CHANNEL(UserMenu);
                  MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
                  MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
 
+#define TYPE_MASK  (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
+
+#define STATE_MASK (~TYPE_MASK)
+
+#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
+
+#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
+
 /* Maximum number of menu items a menu can contain */
 #define MAX_MENU_ITEMS (0x4000)
 #define MAX_GOINTOSUBMENU (0x10)
 
 #define UpdateMenuItemState(state, change) \
 {\
-  if((change) & MFS_DISABLED) { \
-    (state) |= MFS_DISABLED; \
+  if((change) & MF_GRAYED) { \
+    (state) |= MF_GRAYED; \
+  } else { \
+    (state) &= ~MF_GRAYED; \
+  } /* Separate the two for test_menu_resource_layout.*/ \
+  if((change) & MF_DISABLED) { \
+    (state) |= MF_DISABLED; \
   } else { \
-    (state) &= ~MFS_DISABLED; \
+    (state) &= ~MF_DISABLED; \
   } \
   if((change) & MFS_CHECKED) { \
     (state) |= MFS_CHECKED; \
@@ -56,42 +71,12 @@ DBG_DEFAULT_CHANNEL(UserMenu);
   } \
 }
 
-#define FreeMenuText(Menu,MenuItem) \
-{ \
-  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
-           (MenuItem)->lpstr.Length) { \
-    DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
-  } \
-}
-
-
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu)
-{
-   PMENU Menu;
-
-   if (!hMenu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU);
-   if (!Menu)
-   {
-      EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-      return NULL;
-   }
-
-   return Menu;
-}
-
-
 #if 0
 void FASTCALL
-DumpMenuItemList(PITEM MenuItem)
+DumpMenuItemList(PMENU Menu, PITEM MenuItem)
 {
-   UINT cnt = 0;
-   while(MenuItem)
+   UINT cnt = 0, i = Menu->cItems;
+   while(i)
    {
       if(MenuItem->lpstr.Length)
          DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr);
@@ -132,13 +117,22 @@ DumpMenuItemList(PITEM MenuItem)
       if(MFS_GRAYED & MenuItem->fState)
          DbgPrint("MFS_GRAYED ");
       DbgPrint("\n   wId=%d\n", MenuItem->wID);
-      MenuItem = MenuItem->Next;
+      MenuItem++;
+      i--;
    }
    DbgPrint("Entries: %d\n", cnt);
    return;
 }
 #endif
 
+#define FreeMenuText(Menu,MenuItem) \
+{ \
+  if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
+           (MenuItem)->lpstr.Length) { \
+    DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
+  } \
+}
+
 PMENU FASTCALL
 IntGetMenuObject(HMENU hMenu)
 {
@@ -149,64 +143,68 @@ IntGetMenuObject(HMENU hMenu)
    return Menu;
 }
 
-BOOL FASTCALL
-IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse)
+PMENU FASTCALL VerifyMenu(PMENU pMenu)
 {
-   FreeMenuText(Menu,MenuItem);
-   if(bRecurse && MenuItem->spSubMenu)
-   {
-      IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE);
-   }
-
-   /* Free memory */
-   DesktopHeapFree(Menu->head.rpdesk, MenuItem);
-
-   return TRUE;
-}
+   HMENU hMenu;
+   PITEM pItem;
+   UINT i;
+   if (!pMenu) return NULL;
 
-BOOL FASTCALL
-IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse)
-{
-   PITEM PrevMenuItem, MenuItem = NULL;
-   if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1)
+   ERR("VerifyMenu 1!\n");
+   _SEH2_TRY
    {
-      if(MenuItem)
+      hMenu = UserHMGetHandle(pMenu);
+      pItem = pMenu->rgItems;
+      if (pItem)
       {
-         if(PrevMenuItem)
-            PrevMenuItem->Next = MenuItem->Next;
-         else
-         {
-            Menu->rgItems = MenuItem->Next;
-         }
-         Menu->cItems--;
-         return IntFreeMenuItem(Menu, MenuItem, bRecurse);
+         i = pItem[0].wID;
+         pItem[0].wID = i;
       }
    }
-   return FALSE;
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      ERR("Run away LOOP!\n");
+      _SEH2_YIELD(return NULL);
+   }
+   _SEH2_END
+   ERR("VerifyMenu 2!\n");
+   if ( UserObjectInDestroy(hMenu))
+      return NULL;
+   ERR("VerifyMenu 3!\n");
+   return pMenu;
 }
 
-UINT FASTCALL
-IntDeleteMenuItems(PMENU Menu, BOOL bRecurse)
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
 {
-   UINT res = 0;
-   PITEM NextItem;
-   PITEM CurItem = Menu->rgItems;
-   while(CurItem && Menu->cItems)
-   {
-      Menu->cItems--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine!
-                      //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel.
-                      ////   SC_CLOSE First       and      SC_CLOSED Last
-                      //// Use menu item blocks not chain.
-                      /// So do it like windows~!
-      NextItem = CurItem->Next;
-      IntFreeMenuItem(Menu, CurItem, bRecurse);
-      CurItem->Next = 0; // mark the item as end of the list!!!
-      CurItem = NextItem;
-      res++;
-   }
-   Menu->cItems = 0;
-   Menu->rgItems = NULL;
-   return res;
+    /* DestroyMenu should not destroy system menu popup owner */
+    if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd)
+    {
+       //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd);
+       ERR("FIXME Pop up menu window thing'ie\n");
+       
+       //co_UserDestroyWindow( pWnd );
+       //pMenu->hWnd = 0;
+    }
+
+    if (pMenu->rgItems) /* recursively destroy submenus */
+    {
+       int i;
+       ITEM *item = pMenu->rgItems;
+       for (i = pMenu->cItems; i > 0; i--, item++)
+       {
+           pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems.
+           FreeMenuText(pMenu,item);
+           if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu))
+           {
+              IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess);
+              item->spSubMenu = NULL;
+           }
+       }
+       DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
+       pMenu->rgItems = NULL; 
+       pMenu->cItems = 0; //// What ever~!
+    }
+    return TRUE;
 }
 
 BOOL FASTCALL
@@ -216,24 +214,15 @@ IntDestroyMenuObject(PMENU Menu,
    if(Menu)
    {
       PWND Window;
-      //PWINSTATION_OBJECT WindowStation;
-      //NTSTATUS Status;
-
+      
       /* Remove all menu items */
-      IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */
+      IntDestroyMenu( Menu, bRecurse, RemoveFromProcess);
 
       if(RemoveFromProcess)
       {
          RemoveEntryList(&Menu->ListEntry);
       }
 
-      /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
-                                         0,
-                                         ExWindowStationObjectType,
-                                         KernelMode,
-                                         (PVOID*)&WindowStation,
-                                         NULL);
-      if(NT_SUCCESS(Status))*/
       if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
       {
          BOOL ret;
@@ -252,55 +241,32 @@ IntDestroyMenuObject(PMENU Menu,
             ret = UserObjectInDestroy(Menu->head.h);
             if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE;
          }  // See test_subpopup_locked_by_menu tests....
-         //ObDereferenceObject(WindowStation);
          return ret;
       }
    }
    return FALSE;
 }
 
-BOOL IntDestroyMenu( PMENU pMenu, BOOL RemoveFromProcess)
-{
-    /* DestroyMenu should not destroy system menu popup owner */
-    if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP )//&& pMenu->hWnd)
-    {
-        //DestroyWindow( pMenu->hWnd );
-        //pMenu->hWnd = 0;
-    }
-
-    if (pMenu->rgItems) /* recursively destroy submenus */
-    {
-        int i;
-        ITEM *item = pMenu->rgItems;
-        for (i = pMenu->cItems; i > 0; i--, item++)
-        {
-            if (item->spSubMenu) IntDestroyMenu(item->spSubMenu, RemoveFromProcess);
-            //FreeMenuText(pMenu,item);
-        }
-        DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
-    }
-    //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess);
-    return TRUE;
-}
-
 /**********************************************************************
  *             MENU_depth
  *
  * detect if there are loops in the menu tree (or the depth is too large)
  */
-int MENU_depth( PMENU pmenu, int depth)
+int FASTCALL MENU_depth( PMENU pmenu, int depth)
 {
     UINT i;
     ITEM *item;
     int subdepth;
 
+    if (!pmenu) return depth;
+
     depth++;
     if( depth > MAXMENUDEPTH) return depth;
     item = pmenu->rgItems;
     subdepth = depth;
-    for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
+    for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
     {
-        if( item->spSubMenu)
+        if( item->spSubMenu)//VerifyMenu(item->spSubMenu))
         {
             int bdepth = MENU_depth( item->spSubMenu, depth);
             if( bdepth > subdepth) subdepth = bdepth;
@@ -317,38 +283,29 @@ int MENU_depth( PMENU pmenu, int depth)
  * Find a menu item. Return a pointer on the item, and modifies *hmenu
  * in case the item was in a sub-menu.
  */
-ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
 {
     MENU *menu = *pmenu;
     ITEM *fallback = NULL;
     UINT fallback_pos = 0;
     UINT i;
-    PITEM pItem;
+
+    if (!menu) return NULL;
 
     if (wFlags & MF_BYPOSITION)
     {
+        if (!menu->cItems) return NULL;
        if (*nPos >= menu->cItems) return NULL;
-       pItem = menu->rgItems;
-       //pItem = &menu->rgItems[*nPos];
-       i = 0;
-        while(pItem) // Do this for now.
-        {
-           if (i < (INT)menu->cItems)
-           {
-              if ( *nPos == i ) return pItem;
-           }
-           pItem = pItem->Next;
-           i++;
-        }      
+       return &menu->rgItems[*nPos];
     }
     else
     {
         PITEM item = menu->rgItems;
-       for (i = 0; item ,i < menu->cItems; i++,  item = item->Next)//, item++)
+       for (i = 0; item, i < menu->cItems; i++, item++)
        {
            if (item->spSubMenu)
            {
-               PMENU psubmenu = item->spSubMenu;
+               PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu);
                PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags );
                if (subitem)
                {
@@ -376,20 +333,20 @@ ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
     return fallback;
 }
 
-BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
+BOOL FASTCALL
+IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
 {
     PITEM item, NewItems;
 
     TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags);
     if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE;
 
-      /* Remove item */
-
-    //FreeMenuText(pMenu,item);
+    /* Remove item */
 
+    FreeMenuText(pMenu,item);
     if (bRecurse && item->spSubMenu)
     {
-       IntDestroyMenu(item->spSubMenu, TRUE);
+       IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE);
     }
     ////// Use cAlloced with inc's of 8's....
     if (--pMenu->cItems == 0)
@@ -413,6 +370,100 @@ BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
     return TRUE;
 }
 
+/**********************************************************************
+ *         MENU_InsertItem
+ *
+ * Insert (allocate) a new item into a menu.
+ */
+ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags, PMENU *submenu, UINT *npos )
+{
+    ITEM *newItems;
+
+    /* Find where to insert new item */
+
+    if (flags & MF_BYPOSITION) {
+        if (pos > menu->cItems)
+            pos = menu->cItems;
+    } else {
+        if (!MENU_FindItem( &menu, &pos, flags ))
+        {
+            if (submenu) *submenu = menu;
+            if (npos) *npos = pos;
+            pos = menu->cItems;
+        }
+    }
+
+    /* Make sure that MDI system buttons stay on the right side.
+     * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
+     * regardless of their id.
+     */
+    while ( pos > 0 &&
+           (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
+           (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
+        pos--;
+
+    TRACE("inserting at %u flags %x\n", pos, flags);
+
+    /* Create new items array */
+
+    newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
+    if (!newItems)
+    {
+        WARN("allocation failed\n" );
+        return NULL;
+    }
+    if (menu->cItems > 0)
+    {
+       /* Copy the old array into the new one */
+       if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
+       if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
+       DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
+    }
+    menu->rgItems = newItems;
+    menu->cItems++;
+    RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
+    menu->cyMenu = 0; /* force size recalculate */
+    return &newItems[pos];
+}
+
+BOOL FASTCALL
+IntInsertMenuItem(
+    _In_ PMENU MenuObject,
+    UINT uItem,
+    BOOL fByPosition,
+    PROSMENUITEMINFO ItemInfo,
+    PUNICODE_STRING lpstr)
+{
+   PITEM MenuItem;
+   PMENU SubMenu = NULL;
+
+   NT_ASSERT(MenuObject != NULL);
+
+   if (MAX_MENU_ITEMS <= MenuObject->cItems)
+   {
+      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+   }
+
+   SubMenu = MenuObject;
+
+   if(!(MenuItem = MENU_InsertItem( SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, &SubMenu, &uItem ))) return FALSE;
+   
+   if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, lpstr))
+   {
+      IntRemoveMenuItem(SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, FALSE);
+      return FALSE;
+   }
+
+   /* Force size recalculation! */
+   SubMenu->cyMenu = 0;
+   MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
+
+   TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0));
+
+   return TRUE;
+}
+
 PMENU FASTCALL
 IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
 {
@@ -460,21 +511,21 @@ BOOL FASTCALL
 IntCloneMenuItems(PMENU Destination, PMENU Source)
 {
    PITEM MenuItem, NewMenuItem = NULL;
-   PITEM Old = NULL;
+   UINT i;
 
    if(!Source->cItems)
       return FALSE;
 
+   NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, (Source->cItems+1) * sizeof(ITEM));
+   if(!NewMenuItem) return FALSE;
+
+   RtlZeroMemory(NewMenuItem, (Source->cItems+1) * sizeof(ITEM));
+
+   Destination->rgItems = NewMenuItem;
+
    MenuItem = Source->rgItems;
-   while(MenuItem)
+   for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++)
    {
-      Old = NewMenuItem;
-      if(NewMenuItem)
-         NewMenuItem->Next = MenuItem;
-      NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, sizeof(ITEM));
-      if(!NewMenuItem)
-         break;
-      RtlZeroMemory(NewMenuItem, sizeof(NewMenuItem));
       NewMenuItem->fType = MenuItem->fType;
       NewMenuItem->fState = MenuItem->fState;
       NewMenuItem->wID = MenuItem->wID;
@@ -506,16 +557,7 @@ IntCloneMenuItems(PMENU Destination, PMENU Source)
          NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer;
       }
       NewMenuItem->hbmp = MenuItem->hbmp;
-
-      NewMenuItem->Next = NULL;
-      if(Old)
-         Old->Next = NewMenuItem;
-      else
-         Destination->rgItems = NewMenuItem;
-      Destination->cItems++;
-      MenuItem = MenuItem->Next;
    }
-
    return TRUE;
 }
 
@@ -547,7 +589,7 @@ IntCloneMenu(PMENU Source)
    Menu->spwndNotify = NULL;
    Menu->cyMenu = 0;
    Menu->cxMenu = 0;
-   Menu->cItems = 0;
+   Menu->cItems = Source->cItems;
    Menu->iTop = 0;
    Menu->iMaxTop = 0;
    Menu->cxTextAlign = 0;
@@ -631,21 +673,13 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
    {
       int i;
       PITEM item = Menu->rgItems;
-      for ( i = Menu->cItems; i; i--, item = item->Next)
-      {
-         if ( item->spSubMenu )
-         {
-            IntSetMenuInfo( item->spSubMenu, lpmi);
-         }
-      }
-     /* PITEM item = Menu->rgItems;
       for ( i = Menu->cItems; i; i--, item++)
       {
          if ( item->spSubMenu )
          {
             IntSetMenuInfo( item->spSubMenu, lpmi);
          }
-      }*/      
+      }      
    }
    if (sizeof(MENUINFO) < lpmi->cbSize)
    {
@@ -664,117 +698,6 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi)
    return TRUE;
 }
 
-//
-// Old and yeah~..... Why start with a -1 for position search?
-//
-int FASTCALL
-IntGetMenuItemByFlag(PMENU Menu,
-                     UINT uSearchBy,
-                     UINT fFlag,
-                     PMENU *SubMenu,
-                     PITEM *MenuItem,
-                     PITEM *PrevMenuItem)
-{
-   PITEM PrevItem = NULL;
-   PITEM CurItem = Menu->rgItems;
-   int p;
-   int ret;
-
-   if(MF_BYPOSITION & fFlag)
-   {
-      p = uSearchBy;
-      while(CurItem && (p > 0))
-      {
-         PrevItem = CurItem;
-         CurItem = CurItem->Next;
-         p--;
-      }
-      if(CurItem)
-      {
-         if(MenuItem)
-            *MenuItem = CurItem;
-         if(PrevMenuItem)
-            *PrevMenuItem = PrevItem;
-      }
-      else
-      {
-         if(MenuItem)
-            *MenuItem = NULL;
-         if(PrevMenuItem)
-            *PrevMenuItem = NULL; /* ? */
-         return -1;
-      }
-
-      return uSearchBy - p;
-   }
-   else
-   {
-      p = 0;
-      while(CurItem)
-      {
-         if(CurItem->wID == uSearchBy)
-         {
-            if(MenuItem)
-               *MenuItem = CurItem;
-            if(PrevMenuItem)
-               *PrevMenuItem = PrevItem;
-            if(SubMenu)
-                *SubMenu = Menu;
-
-            return p;
-         }
-         else
-         {
-            if(CurItem->spSubMenu)
-            {
-               ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem);
-               if(ret != -1)
-               {
-                 return ret;
-               }
-            }
-         }
-         PrevItem = CurItem;
-         CurItem = CurItem->Next;
-         p++;
-      }
-   }
-   return -1;
-}
-
-
-int FASTCALL
-IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos)
-{
-   PITEM CurItem;
-   PITEM LastItem = NULL;
-   UINT npos = 0;
-
-   CurItem = Menu->rgItems;
-   while(CurItem && (pos != 0))
-   {
-      LastItem = CurItem;
-      CurItem = CurItem->Next;
-      pos--;
-      npos++;
-   }
-
-   if(LastItem)
-   {
-      /* Insert the item after LastItem */
-      LastItem->Next = MenuItem;
-   }
-   else
-   {
-      /* Insert at the beginning */
-      Menu->rgItems = MenuItem;
-   }
-   MenuItem->Next = CurItem;
-   Menu->cItems++;
-
-   return npos;
-}
-
 BOOL FASTCALL
 IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */
                    PITEM MenuItem, PROSMENUITEMINFO lpmii)
@@ -850,18 +773,17 @@ BOOL FASTCALL
 IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr)
 {
    PMENU SubMenuObject;
-   UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR);
 
    if(!MenuItem || !MenuObject || !lpmii)
    {
       return FALSE;
    }
-   if (lpmii->fType & ~fTypeMask)
+   if ( lpmii->fMask & MIIM_FTYPE )
    {
-     ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask);
-     lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE);
+      MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
+      MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
    }
-   if (lpmii->fMask &  MIIM_TYPE)
+   if (lpmii->fMask & MIIM_TYPE)
    {
       #if 0 //// Done in User32.
       if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP))
@@ -882,6 +804,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
       {
          FreeMenuText(MenuObject,MenuItem);
          RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+         MenuItem->Xlpstr = NULL;
       }
       if(lpmii->fType & MFT_BITMAP)
       {
@@ -891,25 +814,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
          { /* Win 9x/Me stuff */
            MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
          }
+         lpmii->dwTypeData = 0;
       }
-      MenuItem->fType |= lpmii->fType;
-   }
-   if (lpmii->fMask & MIIM_FTYPE )
-   {
-      #if 0 //// ?
-      if(( lpmii->fType & MFT_BITMAP))
-      {
-         ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
-         SetLastNtError( ERROR_INVALID_PARAMETER);
-         return FALSE;
-      }
-      #endif
-      MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
-      MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
    }
    if(lpmii->fMask & MIIM_BITMAP)
    {
-         MenuItem->hbmp = lpmii->hbmpItem;
+      MenuItem->hbmp = lpmii->hbmpItem;
    }
    if(lpmii->fMask & MIIM_CHECKMARKS)
    {
@@ -942,9 +852,14 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
          SubMenuObject = UserGetMenuObject(lpmii->hSubMenu);
          if (SubMenuObject != NULL)
          {
+            if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH)
+            {
+               ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
+               return FALSE;
+            }
             SubMenuObject->fFlags |= MNF_POPUP;
             // Now fix the test_subpopup_locked_by_menu tests....
-            if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+            if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
             MenuItem->spSubMenu = SubMenuObject;
             UserReferenceObject(SubMenuObject);
          }
@@ -956,7 +871,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
       }
       else
       {  // If submenu just dereference it.
-         if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+         if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
          MenuItem->spSubMenu = NULL;
       }
    }
@@ -964,9 +879,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
    if ((lpmii->fMask & MIIM_STRING) ||
       ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
    {
+      /* free the string when used */
       FreeMenuText(MenuObject,MenuItem);
+      RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+      MenuItem->Xlpstr = NULL;
 
-      if(lpmii->dwTypeData && lpmii->cch)
+      if(lpmii->dwTypeData && lpmii->cch && lpstr && lpstr->Buffer)
       {
          UNICODE_STRING Source;
 
@@ -984,27 +902,15 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
             MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR);
             MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer;
          }
-         else
-         {
-            RtlInitUnicodeString(&MenuItem->lpstr, NULL);
-            MenuItem->Xlpstr = NULL;
-         }
-      }
-      else
-      {
-         if (0 == (MenuObject->fFlags & MNF_SYSDESKMN))
-         {
-            MenuItem->fType |= MF_SEPARATOR;
-         }
-         RtlInitUnicodeString(&MenuItem->lpstr, NULL);
       }
    }
 
-   //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp)
-   //   MenuItem->fType |= MFT_SEPARATOR; break system menu.....
-
-   /* Force size recalculation! */
-   MenuObject->cyMenu = 0;
+   if( !(MenuObject->fFlags & MNF_SYSDESKMN) &&
+       !MenuItem->Xlpstr &&
+       !lpmii->dwTypeData &&
+       !(MenuItem->fType & MFT_OWNERDRAW) &&
+       !MenuItem->hbmp)
+      MenuItem->fType |= MFT_SEPARATOR;
 
    if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
    {
@@ -1022,130 +928,6 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
 }
 
 
-/**********************************************************************
- *         MENU_InsertItem
- *
- * Insert (allocate) a new item into a menu.
- */
-ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags )
-{
-    ITEM *newItems;
-
-    /* Find where to insert new item */
-
-    if (flags & MF_BYPOSITION) {
-        if (pos > menu->cItems)
-            pos = menu->cItems;
-    } else {
-        if (!MENU_FindItem( &menu, &pos, flags ))
-            pos = menu->cItems;
-    }
-
-    /* Make sure that MDI system buttons stay on the right side.
-     * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
-     * regardless of their id.
-     */
-    while ( pos > 0 &&
-           (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
-           (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
-        pos--;
-
-    TRACE("inserting at %u flags %x\n", pos, flags);
-
-    /* Create new items array */
-
-    newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
-    if (!newItems)
-    {
-        WARN("allocation failed\n" );
-        return NULL;
-    }
-    if (menu->cItems > 0)
-    {
-       /* Copy the old array into the new one */
-       if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
-       if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
-       DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
-    }
-    menu->rgItems = newItems;
-    menu->cItems++;
-    RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
-    menu->cyMenu = 0; /* force size recalculate */
-    return &newItems[pos];
-}
-
-BOOL FASTCALL
-IntInsertMenuItem(
-    _In_ PMENU MenuObject,
-    UINT uItem,
-    BOOL fByPosition,
-    PROSMENUITEMINFO ItemInfo)
-{
-   int pos;
-   PITEM MenuItem;
-   PMENU SubMenu = NULL;
-
-   NT_ASSERT(MenuObject != NULL);
-   //ERR("InsertMenuItem\n");
-   if (MAX_MENU_ITEMS <= MenuObject->cItems)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   if (fByPosition)
-   {
-      SubMenu = MenuObject;
-      /* calculate position */
-      pos = (int)uItem;
-      if(uItem > MenuObject->cItems)
-      {
-         pos = MenuObject->cItems;
-      }
-   }
-   else
-   {
-      pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL);
-   }
-   if (SubMenu == NULL)
-   {
-       /* Default to last position of menu */
-      SubMenu = MenuObject;
-      pos = MenuObject->cItems;
-   }
-
-
-   if (pos < -1)
-   {
-      pos = -1;
-   }
-
-   MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM));
-   if (NULL == MenuItem)
-   {
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-
-   RtlZeroMemory(MenuItem, sizeof(MenuItem));
-
-   if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL))
-   {
-      DesktopHeapFree(MenuObject->head.rpdesk, MenuItem);
-      return FALSE;
-   }
-
-   /* Force size recalculation! */
-   MenuObject->cyMenu = 0;
-   MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
-
-   pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos);
-
-   TRACE("IntInsertMenuItemToList = %i\n", pos);
-
-   return (pos >= 0);
-}
-
 UINT FASTCALL
 IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
 {
@@ -1173,109 +955,7 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
    }
    return res;
 }
-#if 0 // Moved to User32.
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
-   DWORD res = 0;
-   ROSMENUITEMINFO mii;
-   PVOID Buf;
-   PITEM CurItem = MenuObject->rgItems;
-   PWCHAR StrOut;
-   NTSTATUS Status;
-   WCHAR NulByte;
 
-   if (0 != nMax)
-   {
-      if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
-      {
-         return 0;
-      }
-      StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems
-                        * sizeof(ROSMENUITEMINFO));
-      nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
-      Buf = Buffer;
-      mii.cbSize = sizeof(ROSMENUITEMINFO);
-      mii.fMask = 0;
-      NulByte = L'\0';
-
-      while (NULL != CurItem)
-      {
-         mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
-         mii.dwItemData = CurItem->dwItemData;
-         if (0 != CurItem->lpstr.Length)
-         {
-            mii.dwTypeData = StrOut;
-         }
-         else
-         {
-            mii.dwTypeData = NULL;
-         }
-         mii.fState = CurItem->fState;
-         mii.fType = CurItem->fType;
-         mii.wID = CurItem->wID;
-         mii.hbmpChecked = CurItem->hbmpChecked;
-         mii.hbmpItem = CurItem->hbmp;
-         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
-         mii.hSubMenu = CurItem->spSubMenu ? CurItem->spSubMenu->head.h : NULL;
-         mii.Rect.left   = CurItem->xItem; 
-         mii.Rect.top    = CurItem->yItem; 
-         mii.Rect.right  = CurItem->cxItem; // Do this for now......
-         mii.Rect.bottom = CurItem->cyItem;
-         mii.dxTab = CurItem->dxTab;
-         mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
-         //mii.maxBmpSize.cx = CurItem->cxBmp;
-         //mii.maxBmpSize.cy = CurItem->cyBmp;
-
-         Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
-         if (! NT_SUCCESS(Status))
-         {
-            SetLastNtError(Status);
-            return 0;
-         }
-         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
-         if (0 != CurItem->lpstr.Length
-               && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
-         {
-            /* Copy string */
-            Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer,
-                                    CurItem->lpstr.Length);
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
-            Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
-            if (! NT_SUCCESS(Status))
-            {
-               SetLastNtError(Status);
-               return 0;
-            }
-            StrOut++;
-            nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
-         }
-         else if (0 != CurItem->lpstr.Length)
-         {
-            break;
-         }
-
-         CurItem = CurItem->Next;
-         res++;
-      }
-   }
-   else
-   {
-      while (NULL != CurItem)
-      {
-         res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
-         CurItem = CurItem->Next;
-      }
-   }
-   return res;
-}
-#endif
 DWORD FASTCALL
 IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck)
 {
@@ -1301,32 +981,31 @@ IntHiliteMenuItem(PWND WindowObject,
 
    if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE;
 
-   if (MenuItem)
+   if (uHilite & MF_HILITE)
    {
-      if (uHilite & MF_HILITE)
-      {
-         MenuItem->fState |= MF_HILITE;
-      }
-      else
-      {
-         MenuItem->fState &= ~MF_HILITE;
-      }
+      MenuItem->fState |= MF_HILITE;
+   }
+   else
+   {
+      MenuItem->fState &= ~MF_HILITE;
    }
    /* FIXME: Update the window's menu */
 
-   return TRUE;
+   return TRUE; // Always returns true!!!!
 }
 
 BOOL FASTCALL
 UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
 {
-   BOOL ret = FALSE;
+   UINT i;
    PITEM MenuItem = MenuObject->rgItems;
 
-   while(MenuItem)
+   if (!MenuItem) return FALSE;   
+
+   /* reset all default-item flags */
+   for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
    {
-      MenuItem->fState &= ~MFS_DEFAULT;
-      MenuItem = MenuItem->Next;
+       MenuItem->fState &= ~MFS_DEFAULT;
    }
 
    /* no default item */
@@ -1334,90 +1013,59 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
    {
       return TRUE;
    }
-
-   if(fByPos)
+   MenuItem = MenuObject->rgItems;
+   if ( fByPos )
    {
-      UINT pos = 0;
-      while(MenuItem)
-      {
-         if(pos == uItem)
-         {
-            MenuItem->fState |= MFS_DEFAULT;
-            ret = TRUE;
-         }
-         else
-         {
-            MenuItem->fState &= ~MFS_DEFAULT;
-         }
-         pos++;
-         MenuItem = MenuItem->Next;
-      }
+      if ( uItem >= MenuObject->cItems ) return FALSE;
+         MenuItem[uItem].fState |= MFS_DEFAULT;
+      return TRUE;
    }
    else
    {
-      while(MenuItem)
+      for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
       {
-         if(!ret && (MenuItem->wID == uItem))
-         {
-            MenuItem->fState |= MFS_DEFAULT;
-            ret = TRUE;
-         }
-         else
-         {
-            MenuItem->fState &= ~MFS_DEFAULT;
-         }
-         MenuItem = MenuItem->Next;
+          if (MenuItem->wID == uItem)
+          {
+             MenuItem->fState |= MFS_DEFAULT;
+             return TRUE;
+          }
       }
+
    }
-   return ret;
+   return FALSE;
 }
 
 
 UINT FASTCALL
-IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags,
-                      DWORD *gismc)
+IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc)
 {
-   UINT x = 0;
-   UINT res = -1;
-   UINT sres;
+   UINT i = 0;
    PITEM MenuItem = MenuObject->rgItems;
 
-   while(MenuItem)
-   {
-      if(MenuItem->fState & MFS_DEFAULT)
-      {
-
-         if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
-            break;
+   /* empty menu */
+   if (!MenuItem) return -1;
 
-         if(fByPos)
-            res = x;
-         else
-            res = MenuItem->wID;
-
-         if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) &&
-               MenuItem->spSubMenu)
-         {
-
-            if(MenuItem->spSubMenu == MenuObject)
-               break;
-
-            (*gismc)++;
-            sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc);
-            (*gismc)--;
+   while ( !( MenuItem->fState & MFS_DEFAULT ) )
+   {
+      i++; MenuItem++;
+      if  (i >= MenuObject->cItems ) return -1;
+   }
 
-            if(sres > (UINT)-1)
-               res = sres;
-         }
+   /* default: don't return disabled items */
+   if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1;
 
-         break;
-      }
+   /* search rekursiv when needed */
+   if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu)
+   {
+      UINT ret;
+      (*gismc)++;
+      ret = IntGetMenuDefaultItem( MenuItem->spSubMenu, fByPos, gmdiFlags, gismc );
+      (*gismc)--;
+      if ( -1 != ret ) return ret;
 
-      MenuItem = MenuItem->Next;
-      x++;
+      /* when item not found in submenu, return the popup item */
    }
-
-   return res;
+   return ( fByPos ) ? i : MenuItem->wID;
 }
 
 VOID FASTCALL
@@ -1484,7 +1132,7 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
    {
       LastHead = Win32Process->MenuListHead.Flink;
       MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry);
-      ERR("Menus are stuck on the process list!\n");
+      TRACE("Menus are stuck on the process list!\n");
       IntDestroyMenuObject(MenuObject, FALSE, TRUE);
    }
 
@@ -1631,7 +1279,8 @@ UserInsertMenuItem(
    PMENU Menu,
    UINT uItem,
    BOOL fByPosition,
-   LPCMENUITEMINFOW UnsafeItemInfo)
+   LPCMENUITEMINFOW UnsafeItemInfo,
+   PUNICODE_STRING lpstr)
 {
    NTSTATUS Status;
    ROSMENUITEMINFO ItemInfo;
@@ -1646,7 +1295,7 @@ UserInsertMenuItem(
          EngSetLastError(ERROR_INVALID_PARAMETER);
          return FALSE;
       }
-      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
    }
 
    /* Try to copy without last field (not present in older versions) */
@@ -1659,7 +1308,7 @@ UserInsertMenuItem(
          return FALSE;
       }
       ItemInfo.hbmpItem = (HBITMAP)0;
-      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+      return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
    }
 
    SetLastNtError(Status);
@@ -1717,7 +1366,7 @@ UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget )
         return NO_SELECTED_ITEM;
 
     item = menu->rgItems;
-    for (i = 0; i < menu->cItems; i++, item = item->Next)//item++)
+    for (i = 0; i < menu->cItems; i++, item++)
     {
         if (!item->spSubMenu)
            continue;
@@ -1792,7 +1441,8 @@ UserMenuItemInfo(
    UINT Item,
    BOOL ByPosition,
    PROSMENUITEMINFO UnsafeItemInfo,
-   BOOL SetOrGet)
+   BOOL SetOrGet,
+   PUNICODE_STRING lpstr)
 {
    PITEM MenuItem;
    ROSMENUITEMINFO ItemInfo;
@@ -1836,7 +1486,7 @@ UserMenuItemInfo(
 
    if (SetOrGet)
    {
-      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL);
+      Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr);
    }
    else
    {
@@ -1931,7 +1581,6 @@ IntGetMenuItemRect(
 {
    LONG XMove, YMove;
    PITEM MenuItem;
-   //int p = 0;
 
    if (!pWnd)
    {
@@ -2109,7 +1758,6 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
       return FALSE;
    }
 
-   //if(Menu->Process != PsGetCurrentProcess())
    if (Menu->head.rpdesk != pti->rpdesk)
    {
       EngSetLastError(ERROR_ACCESS_DENIED);
@@ -2262,12 +1910,12 @@ NtUserGetMenuBarInfo(
       Ret = IntGetMenuItemRect(pWnd, Menu, 0, &kmbi.rcBar);
       kmbi.rcBar.right = kmbi.rcBar.left + Menu->cxMenu;
       kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->cyMenu;
-      ERR("idItem 0 %d\n",Ret);
+      TRACE("idItem 0 %d\n",Ret);
    }
    else
    {
       Ret = IntGetMenuItemRect(pWnd, Menu, idItem-1, &kmbi.rcBar);
-      ERR("idItem X %d\n", Ret);
+      TRACE("idItem X %d\n", Ret);
    }
 
    kmbi.hMenu = hMenu;
@@ -2277,15 +1925,15 @@ NtUserGetMenuBarInfo(
    //kmbi.fBarFocused = top_popup_hmenu == hMenu;
    if (idItem)
    {
-       PITEM MenuItem;
-       UINT nPos = idItem-1;
+       //PITEM MenuItem;
+       //UINT nPos = idItem-1;
        kmbi.fFocused = Menu->iItem == idItem-1;
-       //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
-       MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
-       if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
+       if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
+       //MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
+       //if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
        {
-          //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
-          kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
+          kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
+          //kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
        }
    }
 /*   else
@@ -2327,6 +1975,7 @@ NtUserGetMenuIndex(
 {
    PMENU Menu, SubMenu;
    PITEM MenuItem;
+   UINT i;
    DECLARE_RETURN(UINT);
 
    TRACE("Enter NtUserGetMenuIndex\n");
@@ -2337,13 +1986,11 @@ NtUserGetMenuIndex(
       RETURN(0xFFFFFFFF);
 
    MenuItem = Menu->rgItems;
-   while(MenuItem)
+   for (i = 0; i < Menu->cItems; i++, MenuItem++)
    {
-      if (MenuItem->spSubMenu == SubMenu)
-         RETURN(MenuItem->wID);
-      MenuItem = MenuItem->Next;
+       if (MenuItem->spSubMenu == SubMenu)
+          RETURN(MenuItem->wID);
    }
-
    RETURN(0xFFFFFFFF);
 
 CLEANUP:
@@ -2507,7 +2154,7 @@ NtUserMenuItemFromPoint(
    Y -= Window->rcWindow.top;
 
    mi = Menu->rgItems;
-   for (i = 0; NULL != mi; i++)//, mi++)
+   for (i = 0; i < Menu->cItems; i++, mi++)
    {
       RECTL Rect;
       Rect.left   = mi->xItem; 
@@ -2519,7 +2166,6 @@ NtUserMenuItemFromPoint(
       {
          break;
       }
-      mi = mi->Next;
    }
 
    RETURN( (mi ? i : NO_SELECTED_ITEM));
@@ -2696,7 +2342,7 @@ NtUserThunkedMenuItemInfo(
       RETURN(FALSE);
    }
 
-   lstrCaption.Buffer = NULL;
+   RtlInitUnicodeString(&lstrCaption, 0);
 
    /* Check if we got a Caption */
    if (lpszCaption && lpszCaption->Buffer)
@@ -2711,12 +2357,11 @@ NtUserThunkedMenuItemInfo(
          SetLastNtError(Status);
          RETURN(FALSE);
       }
-      ///// Now use it!
    }
 
-   if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii));
+   if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii, &lstrCaption));
 
-   RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE));
+   RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption));
 
 CLEANUP:
    TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_);
index 9ff6b0c..e583054 100644 (file)
@@ -38,8 +38,7 @@ BOOL FASTCALL
 IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process);
 
 BOOL FASTCALL
-IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition,
-                  PROSMENUITEMINFO ItemInfo);
+IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo, PUNICODE_STRING lpstr);
 
 PMENU FASTCALL
 IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu);
@@ -47,4 +46,4 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu);
 UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget );
 UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags);
 BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse);
-PITEM MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
index a9e2256..c458230 100644 (file)
@@ -1548,7 +1548,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     {
         RETURN(FALSE);
     }
-    
+
     ptiSendTo = IntSendTo(Window, Win32Thread, Msg);
 
     if (Msg & 0x80000000 &&
@@ -2755,7 +2755,7 @@ NtUserMessageCall( HWND hWnd,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWP,
                                               Hook->Proc,
-                                              Hook->ihmod, 
+                                              Hook->ihmod,
                                               Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
@@ -2774,7 +2774,7 @@ NtUserMessageCall( HWND hWnd,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWPR,
                                               Hook->Proc,
-                                              Hook->ihmod, 
+                                              Hook->ihmod,
                                               Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
@@ -2833,7 +2833,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     Status = ObReferenceObjectByHandle(hProcess,
                                        PROCESS_QUERY_INFORMATION,
-                                       PsProcessType,
+                                       *PsProcessType,
                                        UserMode,
                                        (PVOID*)&Process,
                                        NULL);
index 52f0abe..4b64a13 100644 (file)
@@ -223,7 +223,7 @@ NtUserGetThreadState(
          break;
       case THREADSTATE_INSENDMESSAGE:
          {
-           PUSER_SENT_MESSAGE Message = 
+           PUSER_SENT_MESSAGE Message =
                 ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent;
            ERR("THREADSTATE_INSENDMESSAGE\n");
 
@@ -243,7 +243,7 @@ NtUserGetThreadState(
              if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
            }
 
-           break;         
+           break;
          }
       case THREADSTATE_GETMESSAGETIME:
          ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
@@ -289,7 +289,7 @@ NtUserSetThreadState(
    DWORD Ret = 0;
    // Test the only flags user can change.
    if (Set & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
-   if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;   
+   if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
    UserEnterExclusive();
    pti = PsGetCurrentThreadWin32Thread();
    if (pti->MessageQueue)
@@ -448,7 +448,7 @@ NtUserGetGuiResources(
 
    Status = ObReferenceObjectByHandle(hProcess,
                                       PROCESS_QUERY_INFORMATION,
-                                      PsProcessType,
+                                      *PsProcessType,
                                       ExGetPreviousMode(),
                                       (PVOID*)&Process,
                                       NULL);
@@ -656,7 +656,7 @@ void UserDbgAssertThreadInfo(BOOL showCaller)
     ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta());
     if (pti->pcti && pci->pDeskInfo)
         ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta));
-    if (pti->KeyboardLayout) 
+    if (pti->KeyboardLayout)
         ASSERT(pci->hKL == pti->KeyboardLayout->hkl);
     if(pti->rpdesk != NULL)
         ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo);
index e4ee395..73c92bf 100644 (file)
@@ -19,11 +19,11 @@ RtlInitLargeAnsiString(
     IN PCSZ SourceString,
     IN INT Unknown)
 {
-    ULONG DestSize;
+    USHORT DestSize;
 
     if (SourceString)
     {
-        DestSize = strlen(SourceString);
+        DestSize = (USHORT)strlen(SourceString);
         DestinationString->Length = DestSize;
         DestinationString->MaximumLength = DestSize + sizeof(CHAR);
     }
@@ -44,11 +44,11 @@ RtlInitLargeUnicodeString(
     IN PCWSTR SourceString,
     IN INT Unknown)
 {
-    ULONG DestSize;
+    USHORT DestSize;
 
     if (SourceString)
     {
-        DestSize = wcslen(SourceString) * sizeof(WCHAR);
+        DestSize = (USHORT)wcslen(SourceString) * sizeof(WCHAR);
         DestinationString->Length = DestSize;
         DestinationString->MaximumLength = DestSize + sizeof(WCHAR);
     }
index 9693508..2e45bc6 100644 (file)
@@ -1,6 +1,9 @@
 #pragma once
 
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu);
+FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
+{
+   return ValidateHandle(hMenu, TYPE_MENU);
+}
 
 #define ASSERT_REFS_CO(_obj_) \
 { \
index 6e95a3e..6259742 100644 (file)
@@ -953,6 +953,11 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
          SysMenu->fFlags |= MNF_SYSDESKMN;
          SysMenu->hWnd = Window->head.h;
          hNewMenu = co_IntLoadSysMenuTemplate();
+         //if ( Window->ExStyle & WS_EX_MDICHILD )
+         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENUMDI");
+         // else
+         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENU");
+         // Do the rest in here.
          if(!hNewMenu)
          {
             IntReleaseMenuObject(SysMenu);
@@ -985,7 +990,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
             ItemInfo.dwTypeData = NULL;
             ItemInfo.cch = 0;
             ItemInfo.hSubMenu = NewMenu->head.h;
-            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);
+            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL);
 
             Window->SystemMenu = SysMenu->head.h;
 
index 5ad490a..f11f57c 100644 (file)
@@ -1710,6 +1710,7 @@ co_WinPosSetWindowPos(
    RECTL valid_rects[2];
    PROSRGNDATA VisRgn;
    HRGN VisBefore = NULL;
+   HRGN VisBeforeJustClient = NULL;
    HRGN VisAfter = NULL;
    HRGN DirtyRgn = NULL;
    HRGN ExposedRgn = NULL;
@@ -1806,6 +1807,28 @@ co_WinPosSetWindowPos(
             RGNOBJAPI_Unlock(VisRgn);
             NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
          }
+
+         /* Calculate the non client area for resizes, as this is used in the copy region */ 
+         if (!(WinPos.flags & SWP_NOSIZE))
+         {
+             VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE,
+                 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
+             VisRgn = NULL;
+
+             if ( VisBeforeJustClient != NULL &&
+                 (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBeforeJustClient, NULL)) &&
+                 REGION_Complexity(VisRgn) == NULLREGION )
+             {
+                 RGNOBJAPI_Unlock(VisRgn);
+                 GreDeleteObject(VisBeforeJustClient);
+                 VisBeforeJustClient = NULL;
+             }
+             else if(VisRgn)
+             {
+                 RGNOBJAPI_Unlock(VisRgn);
+                 NtGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
+             }
+         }
       }
    }
 
@@ -1909,8 +1932,6 @@ co_WinPosSetWindowPos(
           ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
           !(Window->ExStyle & WS_EX_TRANSPARENT) )
       {
-         CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
-         RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
 
          /*
           * If this is (also) a window resize, the whole nonclient area
@@ -1920,19 +1941,14 @@ co_WinPosSetWindowPos(
           * we don't have to crop (can't take anything away from an empty
           * region...)
           */
-         if (!(WinPos.flags & SWP_NOSIZE) &&
-               RgnType != ERROR &&
-               RgnType != NULLREGION )
+
+         CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
+         if (WinPos.flags & SWP_NOSIZE)
+            RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
+         else if (VisBeforeJustClient != NULL)
          {
-            PROSRGNDATA pCopyRgn;
-            RECTL ORect = OldClientRect;
-            RECTL NRect = NewClientRect;
-            RECTL_vOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
-            RECTL_vOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
-            RECTL_bIntersectRect(&CopyRect, &ORect, &NRect);
-            pCopyRgn = RGNOBJAPI_Lock(CopyRgn, NULL);
-            REGION_CropAndOffsetRegion(pCopyRgn, pCopyRgn, &CopyRect, NULL);
-            RGNOBJAPI_Unlock(pCopyRgn);
+            RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
+            GreDeleteObject(VisBeforeJustClient);
          }
 
          /* No use in copying bits which are in the update region. */
index 40db647..cc25f91 100644 (file)
@@ -344,21 +344,26 @@ HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccl, int cEntries)
  */
 int WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
 {
- MSG mCopy = *lpMsg;
- CHAR cChar;
- WCHAR wChar;
- NTSTATUS Status;
-
- if(!U32IsValidAccelMessage(lpMsg->message)) return 0;
-
- Status = RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar));
- if(!NT_SUCCESS(Status))
- {
-  SetLastError(RtlNtStatusToDosError(Status));
-  return 0;
- }
-
- return TranslateAcceleratorW(hWnd, hAccTable, &mCopy);
+    switch (lpMsg->message)
+    {
+    case WM_KEYDOWN:
+    case WM_SYSKEYDOWN:
+        return TranslateAcceleratorW( hWnd, hAccTable, lpMsg );
+
+    case WM_CHAR:
+    case WM_SYSCHAR:
+        {
+            MSG msgW = *lpMsg;
+            char ch = LOWORD(lpMsg->wParam);
+            WCHAR wch;
+            MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
+            msgW.wParam = MAKEWPARAM(wch, HIWORD(lpMsg->wParam));
+            return TranslateAcceleratorW( hWnd, hAccTable, &msgW );
+        }
+
+    default:
+        return 0;
+    }
 }
 
 /* EOF */
index ba844d0..ae86741 100644 (file)
@@ -897,8 +897,11 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
     nItems = GetMenuItemCount(menu) - 1;
     iId = GetMenuItemID(menu,nItems) ;
     if (iId == SC_RESTORE || iId == SC_CLOSE)
+    {
+        ERR("system buttons already exist\n");
        return 0;
-
+    }
+//// End
     /* create a copy of sysmenu popup and insert it into frame menu bar */
     if (!(hSysPopup = GetSystemMenu(hChild, FALSE)))
     {
@@ -907,21 +910,14 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
     }
 
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
-                SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ;
+                SC_CLOSE, is_close_enabled(hChild, hSysPopup) ?
+                (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D );
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
                 SC_RESTORE, (LPCWSTR)HBMMENU_MBAR_RESTORE );
     AppendMenuW(menu, MF_HELP | MF_BITMAP,
-                SC_CLOSE, is_close_enabled(hChild, hSysPopup) ?
-                (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D );
+                SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ;
 
     /* The system menu is replaced by the child icon */
-/*    hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM);
-    if (!hIcon)
-        hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON);
-    if (!hIcon)
-        hIcon = LoadIconW(NULL, IDI_APPLICATION);
-*/
-//// End
     hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_SMALL, 0);
     if (!hIcon)
         hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_BIG, 0);
@@ -990,7 +986,10 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild, HBITMAP hBmpClose )
     nItems = GetMenuItemCount(menu) - 1;
     iId = GetMenuItemID(menu,nItems) ;
     if( !(iId == SC_RESTORE || iId == SC_CLOSE) )
+    {
+        ERR("no system buttons then nothing to do\n");
        return 0;
+    }
 
     /*
      * Remove the system menu, If that menu is the icon of the window
@@ -1534,9 +1533,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
     case WM_CHILDACTIVATE:
     case WM_SYSCOMMAND:
     case WM_SHOWWINDOW:
-#ifndef __REACTOS__
     case WM_SETVISIBLE:
-#endif
     case WM_SIZE:
     case WM_NEXTMENU:
     case WM_SYSCHAR:
@@ -1613,9 +1610,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
         break;
 
     case WM_SHOWWINDOW:
-#ifndef __REACTOS__
     case WM_SETVISIBLE:
-#endif  //// Commented out r57663
+        //// Commented out r57663
         /*if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
         else*/ MDI_PostUpdate(client, ci, SB_BOTH+1);
         break;
index 7470a3c..08e3332 100644 (file)
@@ -15,6 +15,8 @@
 
 LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
 BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj);
+LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
+void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
 
 WINE_DEFAULT_DEBUG_CHANNEL(menu);
 
@@ -132,7 +134,23 @@ static SIZE MenuCharSize;
  */
 FORCEINLINE PMENU MENU_GetMenu(HMENU hMenu)
 {
-    return ValidateHandle(hMenu, TYPE_MENU); 
+    return ValidateHandleNoErr(hMenu, TYPE_MENU); 
+}
+
+/***********************************************************************
+ *           get_win_sys_menu
+ *
+ * Get the system menu of a window
+ */
+static HMENU get_win_sys_menu( HWND hwnd )
+{
+    HMENU ret = 0;
+    WND *win = ValidateHwnd( hwnd );
+    if (win)
+    {
+        ret = win->SystemMenu;
+    }
+    return ret;
 }
 
 /***********************************************************************
@@ -154,22 +172,13 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
     {
        if (*nPos >= menu->cItems) return NULL;
        pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-       //pItem = &menu->rgItems[*nPos];
-       i = 0;
-        while(pItem) // Do this for now.
-        {
-           if (i < (INT)menu->cItems)
-           {
-              if ( *nPos == i ) return pItem;
-           }
-           pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
-           i++;
-        }      
+       if (pItem) pItem = &pItem[*nPos];
+       return pItem;
     }
     else
     {
         PITEM item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-       for (i = 0; item ,i < menu->cItems; i++,  item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//, item++)
+       for (i = 0; item, i < menu->cItems; i++, item++)
        {
            if (item->spSubMenu)
            {
@@ -206,41 +215,33 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags )
 UINT FASTCALL
 IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc)
 {
-   UINT x = 0;
-   UINT res = -1;
-   UINT sres;
+   UINT i = 0;
    PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL;
 
-   while(Item)
-   {
-      if (Item->fState & MFS_DEFAULT)
-      {
-         if (!(gmdiFlags & GMDI_USEDISABLED) &&
-             (Item->fState & MFS_DISABLED) )
-            break;
+   /* empty menu */
+   if (!Item) return -1;
 
-         res = fByPos ? x : Item->wID;
+   while ( !( Item->fState & MFS_DEFAULT ) )
+   {
+      i++; Item++;
+      if  (i >= Menu->cItems ) return -1;
+   }
 
-         if ((*gismc < MAX_GOINTOSUBMENU) &&
-             (gmdiFlags & GMDI_GOINTOPOPUPS) &&
-              Item->spSubMenu)
-         {
-            if (DesktopPtrToUser(Item->spSubMenu) == Menu)
-               break;
+   /* default: don't return disabled items */
+   if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1;
 
-            (*gismc)++;
-            sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc);
-            (*gismc)--;
+   /* search rekursiv when needed */
+   if ( (Item->fType & MF_POPUP) &&  (gmdiFlags & GMDI_GOINTOPOPUPS) && Item->spSubMenu)
+   {
+      UINT ret;
+      (*gismc)++;
+      ret = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc );
+      (*gismc)--;
+      if ( -1 != ret ) return ret;
 
-            if(sres > (UINT)-1)
-               res = sres;
-         }
-         break;
-      }
-      Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL;
-      x++;
+      /* when item not found in submenu, return the popup item */
    }
-   return res;
+   return ( fByPos ) ? i : Item->wID;
 }
 
 static BOOL GetMenuItemInfo_common ( HMENU hmenu,
@@ -256,7 +257,6 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu,
     if (!pItem)
     {
         SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
-        //SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
@@ -339,7 +339,7 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu,
        lpmii->hbmpItem = pItem->hbmp;
 
     if (lpmii->fMask & MIIM_STATE)
-       lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK;
+       lpmii->fState = pItem->fState & MENUITEMINFO_STATE_MASK;
 
     if (lpmii->fMask & MIIM_ID)
        lpmii->wID = pItem->wID;
@@ -377,7 +377,7 @@ static BOOL FASTCALL
 MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
 {
   PMENU pMenu;
-  if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE;
+  if (!(pMenu = ValidateHandleNoErr(Menu, TYPE_MENU))) return FALSE;
 
   MenuInfo->hbrBack = pMenu->hbrBack;
   MenuInfo->dwContextHelpID = pMenu->dwContextHelpId;
@@ -518,6 +518,10 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo)
   {
     ItemInfo->cch = strlenW(ItemInfo->dwTypeData);
   }
+  if (ItemInfo->hSubMenu)
+  {
+     if (!IsMenu(ItemInfo->hSubMenu)) ItemInfo->hSubMenu = NULL;
+  }
   Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL);
   return Ret;
 }
@@ -537,139 +541,6 @@ MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
   }
 }
 
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
-   DWORD res = 0;
-   ROSMENUITEMINFO mii;
-   PVOID Buf;
-   PITEM CurItem = MenuObject->rgItems ? DesktopPtrToUser(MenuObject->rgItems) : NULL;
-   PWCHAR StrOut;
-   WCHAR NulByte;
-
-   if (0 != nMax)
-   {
-      if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
-      {
-         return 0;
-      }
-      StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO));
-      nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
-      Buf = Buffer;
-      mii.cbSize = sizeof(ROSMENUITEMINFO);
-      mii.fMask = 0;
-      NulByte = L'\0';
-
-      while (NULL != CurItem)
-      {
-         mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
-         mii.dwItemData = CurItem->dwItemData;
-         if (0 != CurItem->lpstr.Length)
-         {
-            mii.dwTypeData = StrOut;
-         }
-         else
-         {
-            mii.dwTypeData = NULL;
-         }
-         mii.fState = CurItem->fState;
-         mii.fType = CurItem->fType;
-         mii.wID = CurItem->wID;
-         mii.hbmpChecked = CurItem->hbmpChecked;
-         mii.hbmpItem = CurItem->hbmp;
-         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
-         if (CurItem->spSubMenu)
-         {
-            PMENU pSubMenu = DesktopPtrToUser(CurItem->spSubMenu);
-            HMENU hSubMenu = UserHMGetHandle(pSubMenu);
-            mii.hSubMenu = hSubMenu;
-         }
-         else
-            mii.hSubMenu = NULL;
-         mii.Rect.left   = CurItem->xItem; 
-         mii.Rect.top    = CurItem->yItem; 
-         mii.Rect.right  = CurItem->cxItem; // Do this for now......
-         mii.Rect.bottom = CurItem->cyItem;
-         mii.dxTab = CurItem->dxTab;
-         mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
-         //mii.maxBmpSize.cx = CurItem->cxBmp;
-         //mii.maxBmpSize.cy = CurItem->cyBmp;
-
-         RtlCopyMemory(Buf, &mii, sizeof(ROSMENUITEMINFO));
-         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
-         if (0 != CurItem->lpstr.Length && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
-         {
-            LPWSTR lpstr = CurItem->lpstr.Buffer ? DesktopPtrToUser(CurItem->lpstr.Buffer) : NULL;
-            if (lpstr)
-            {
-               /* Copy string */
-               RtlCopyMemory(StrOut, lpstr, CurItem->lpstr.Length);
-            
-               StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
-               RtlCopyMemory(StrOut, &NulByte, sizeof(WCHAR));
-               StrOut++;
-               nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
-            }
-         }
-         else if (0 != CurItem->lpstr.Length)
-         {
-            break;
-         }
-
-         CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
-         res++;
-      }
-   }
-   else
-   {
-      while (NULL != CurItem)
-      {
-         res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
-         CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
-      }
-   }
-   return res;
-}
-
-/***********************************************************************
- *           MenuGetAllRosMenuItemInfo
- *
- * Get full information about all menu items
- */
-static INT FASTCALL
-MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo)
-{
-  DWORD BufSize;
-  PMENU pMenu;
-
-  if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return -1;
-
-  BufSize = IntBuildMenuItemList(pMenu, (PVOID)1, 0);
-  if (BufSize == (DWORD) -1 || BufSize == 0)
-  {
-      return -1;
-  }
-  *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize);
-  if (NULL == *ItemInfo)
-  {
-      return -1;
-  }
-
-  return IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize);
-}
-
-/***********************************************************************
- *           MenuCleanupAllRosMenuItemInfo
- *
- * Cleanup after use of MenuGetAllRosMenuItemInfo
- */
-static VOID FASTCALL
-MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
-{
-  HeapFree(GetProcessHeap(), 0, ItemInfo);
-}
-
 /***********************************************************************
  *           MenuInitSysMenuPopup
  *
@@ -718,22 +589,27 @@ void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LON
  *     PROSMENUINFO MenuInfo)
  *
  *****************************************************************************/
-static UINT MenuGetStartOfNextColumn(
-    PROSMENUINFO MenuInfo)
+
+static UINT  MENU_GetStartOfNextColumn(
+    HMENU  hMenu )
 {
-    PROSMENUITEMINFO MenuItems;
+    MENU *menu = MENU_GetMenu(hMenu);
+    PITEM pItem;
     UINT i;
 
-    i = MenuInfo->iItem;
-    if ( i == NO_SELECTED_ITEM )
-        return i;
+    if(!menu)
+       return NO_SELECTED_ITEM;
 
-    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-        return NO_SELECTED_ITEM;
+    i = menu->iItem + 1;
+    if( i == NO_SELECTED_ITEM )
+       return i;
 
-    for (i++ ; i < MenuInfo->cItems; i++)
-        if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
-            return i;
+    pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (!pItem) return NO_SELECTED_ITEM;
+    for( ; i < menu->cItems; ++i ) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           return i;
+    }
 
     return NO_SELECTED_ITEM;
 }
@@ -744,38 +620,36 @@ static UINT MenuGetStartOfNextColumn(
  *     PROSMENUINFO MenuInfo)
  *
  *****************************************************************************/
-
-static UINT FASTCALL MenuGetStartOfPrevColumn(
-    PROSMENUINFO MenuInfo)
+static UINT  MENU_GetStartOfPrevColumn(
+    HMENU  hMenu )
 {
-    PROSMENUITEMINFO MenuItems;
-    UINT i;
+    MENU *menu = MENU_GetMenu(hMenu);
+    UINT  i;
+    PITEM pItem;
 
-    if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM)
-        return NO_SELECTED_ITEM;
+    if( !menu )
+       return NO_SELECTED_ITEM;
 
-    if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
-        return NO_SELECTED_ITEM;
+    if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM )
+       return NO_SELECTED_ITEM;
+
+    pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (!pItem) return NO_SELECTED_ITEM;
 
     /* Find the start of the column */
-    for (i = MenuInfo->iItem;
-         0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
-         --i)
-    {
-        ; /* empty */
-    }
 
-    if (i == 0)
-    {
-        MenuCleanupAllRosMenuItemInfo(MenuItems);
-        return NO_SELECTED_ITEM;
-    }
+    for(i = menu->iItem; i != 0 &&
+        !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+       --i); /* empty */
 
-    for (--i; 0 != i; --i)
-        if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
-            break;
+    if(i == 0)
+       return NO_SELECTED_ITEM;
+
+    for(--i; i != 0; --i) {
+       if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+           break;
+    }
 
-    MenuCleanupAllRosMenuItemInfo(MenuItems);
     TRACE("ret %d.\n", i );
 
     return i;
@@ -870,7 +744,7 @@ static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget )
         return NO_SELECTED_ITEM;
 
     item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
-    for (i = 0; i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//item++)
+    for (i = 0; i < menu->cItems; i++, item++)
     {
         if (!item->spSubMenu)
            continue;
@@ -987,58 +861,48 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil
  * Find the menu item selected by a key press.
  * Return item id, -1 if none, -2 if we should close the menu.
  */
-static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
+static UINT FASTCALL MENU_FindItemByKey(HWND WndOwner, HMENU hmenu,
                   WCHAR Key, BOOL ForceMenuChar)
 {
-  ROSMENUINFO SysMenuInfo;
-  PROSMENUITEMINFO Items, ItemInfo;
   LRESULT MenuChar;
-  UINT i;
   WORD Flags = 0;
 
-  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
+  TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, hmenu );
 
-  if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
-  {
-      if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
-      {
-          MenuInfo = &SysMenuInfo;
-      }
-      else
-      {
-          MenuInfo = NULL;
-      }
-  }
+  if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(WndOwner), 0);
+    if (hmenu)
+    {
+       MENU *menu = MENU_GetMenu( hmenu );
+       ITEM *item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
 
-  if (NULL != MenuInfo)
-  {
-      if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
-      {
-          return -1;
-      }
-      if ( !ForceMenuChar )
-      {
-          ItemInfo = Items;
-          for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++)
-          {
-              if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
-              {
-                  WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
-                  do
-                  {
-                      p = strchrW (p + 2, '&');
-                  }
-                  while (p != NULL && p [1] == '&');
-                  if (p && (toupperW(p[1]) == toupperW(Key))) return i;
-              }
-          }
-      }
+       if( !ForceMenuChar )
+       {
+            UINT i;
+            BOOL cjk = GetSystemMetrics( SM_DBCSENABLED );
+
+            for (i = 0; i < menu->cItems; i++, item++)
+            {
+               LPWSTR text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL;
+               if( text)
+               {
+                   const WCHAR *p = text - 2;
+                   do
+                   {
+                       const WCHAR *q = p + 2;
+                       p = strchrW (q, '&');
+                       if (!p && cjk) p = strchrW (q, '\036'); /* Japanese Win16 */
+                   }
+                   while (p != NULL && p [1] == '&');
+                   if (p && (toupperW(p[1]) == toupperW(Key))) return i;
+               }
+            }
+       }
 
-      Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0;
-      Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
+      Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0;
+      Flags |= menu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
 
       MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
-                              MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self);
+                              MAKEWPARAM(Key, Flags), (LPARAM) hmenu);
       if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
       if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
     }
@@ -1530,7 +1394,7 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect,
 
     if ((lprect == NULL) || (MenuInfo == NULL)) return;
     if (MenuInfo->cItems == 0) return;
-    TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+    TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
     MenuInfo->cxMenu = lprect->right - lprect->left;
     MenuInfo->cyMenu = 0;
     maxY = lprect->top + 1;
@@ -1689,7 +1553,6 @@ MENU_DrawScrollArrows(PROSMENUINFO lppop, HDC hdc)
     DeleteDC(hdcMem);
 }
 
-
 /***********************************************************************
  *           MenuDrawMenuItem
  *
@@ -1702,7 +1565,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
     PWCHAR Text;
     BOOL flat_menu = FALSE;
     int bkgnd;
-    PWND Wnd = ValidateHwnd(hWnd);
+    PWND Wnd = ValidateHwndNoErr(hWnd);
 
     if (!Wnd)
       return;
@@ -1744,6 +1607,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
         SetBkColor( hdc, GetSysColor( bkgnd ) );
     }
 
+    TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect));
     rect = lpitem->Rect;
     MENU_AdjustMenuItemRect(MenuInfo, &rect);
 
@@ -1949,7 +1813,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
                        DT_LEFT | DT_VCENTER | DT_SINGLELINE;
 
         if((MenuInfo->dwStyle & MNS_CHECKORBMP))
-             rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK));
+             rect.left += max(0, (int)(MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)));
         else
              rect.left += MenuInfo->cxTextAlign;
 
@@ -2053,6 +1917,7 @@ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu )
                DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
 
             /* draw menu items */
+            //TRACE("hmenu %p Style %08x\n", hmenu, menu->dwStyle);
             if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems)
             {
                 UINT u;
@@ -2115,6 +1980,44 @@ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd,
         return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
 }
 
+/***********************************************************************
+ *           MENU_InitPopup
+ *   
+ * Popup menu initialization before WM_ENTERMENULOOP.
+ */
+static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
+{
+    MENU *menu;
+    DWORD ex_style = 0;
+    ROSMENUINFO MenuInfo;
+
+    TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
+
+    if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
+
+    /* store the owner for DrawItem */
+    if (!IsWindow( hwndOwner ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
+    MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+    //menu->hwndOwner = hwndOwner;
+    MenuInfo.spwndNotify = ValidateHwndNoErr( hwndOwner );
+
+    if (flags & TPM_LAYOUTRTL)
+        ex_style = WS_EX_LAYOUTRTL;
+
+    /* NOTE: In Windows, top menu popup is not owned. */
+    //menu->hWnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+    MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+                                WS_POPUP, 0, 0, 0, 0,
+                                hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+                                (LPVOID)hmenu );
+    MenuSetRosMenuInfo(&MenuInfo);
+    if( !menu->hWnd ) return FALSE;
+    return TRUE;
+}
 
 /***********************************************************************
  *           MenuShowPopup
@@ -2130,7 +2033,6 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     POINT pt;
     HMONITOR monitor;
     MONITORINFO info;
-    DWORD ex_style = 0; 
 
     TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
           hwndOwner, hmenu, id, x, y, xanchor, yanchor);
@@ -2149,15 +2051,9 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
         MenuInfo.iItem = NO_SELECTED_ITEM;
     }
 
-    /* store the owner for DrawItem */
-    if (!IsWindow(hwndOwner))
-    {
-       SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-       return FALSE;
-    }
-    MenuInfo.spwndNotify = ValidateHwndNoErr(hwndOwner);
+    //menu->dwArrowsOn = 0;
+    MenuInfo.dwArrowsOn = 0;
     MenuSetRosMenuInfo(&MenuInfo);
-
     MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
 
     /* adjust popup menu pos so that it fits within the desktop */
@@ -2173,10 +2069,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     GetMonitorInfoW( monitor, &info );
 
     if (flags & TPM_LAYOUTRTL) 
-    {                               
-        ex_style = WS_EX_LAYOUTRTL; 
         flags ^= TPM_RIGHTALIGN;
-    } 
+
     if( flags & TPM_RIGHTALIGN ) x -= width;
     if( flags & TPM_CENTERALIGN ) x -= width / 2;
 
@@ -2203,24 +2097,18 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
     }
     if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
 
-    /* NOTE: In Windows, top menu popup is not owned. */
-    MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
-                                  WS_POPUP, x, y, width, height,
-                                  hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
-                                 (LPVOID) MenuInfo.Self);
-    if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
     if (!top_popup) {
         top_popup = MenuInfo.Wnd;
         top_popup_hmenu = hmenu;
     }
-
-    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
-
     /* Display the window */
 
-    SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
-                  SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+    SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, x, y, width, height,
+                  SWP_SHOWWINDOW | SWP_NOACTIVATE);
     UpdateWindow( MenuInfo.Wnd );
+
+    IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
+
     return TRUE;
 }
 
@@ -2426,7 +2314,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
   PWND pWnd;
   PPOPUPMENU pPopupMenu;
 
-  pWnd = ValidateHwnd(Wnd);
+  pWnd = ValidateHwndNoErr(Wnd);
   if (pWnd)
   {
      if (!pWnd->fnid)
@@ -2609,6 +2497,12 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
         }
       break;
 
+#ifdef __REACTOS__
+    case WM_NCDESTROY:
+      NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+      break;
+#endif
+
     case WM_SHOWWINDOW:
       if (0 != wParam)
         {
@@ -2721,7 +2615,6 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu)
     return res;
 }
 
-
 /**********************************************************************
  *         MENUEX_ParseResource
  *
@@ -2784,88 +2677,6 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
     return res;
 }
 
-NTSTATUS WINAPI
-User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
-{
-  HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
-  LRESULT Result = (LRESULT)hmenu;
-  MENUINFO menuinfo = {0};
-  MENUITEMINFOW info = {0};
-
-  // removing space for checkboxes from menu
-  menuinfo.cbSize = sizeof(menuinfo);
-  menuinfo.fMask = MIM_STYLE;
-  GetMenuInfo(hmenu, &menuinfo);
-  menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
-  SetMenuInfo(hmenu, &menuinfo);
-
-  // adding bitmaps to menu items
-  info.cbSize = sizeof(info);
-  info.fMask |= MIIM_BITMAP;
-  info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
-  SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_RESTORE;
-  SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
-  SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
-  info.hbmpItem = HBMMENU_POPUP_CLOSE;
-  SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
-
-  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
-}
-
-
-BOOL
-MenuInit(VOID)
-{
-  NONCLIENTMETRICSW ncm;
-
-  /* get the menu font */
-  if(!hMenuFont || !hMenuFontBold)
-  {
-    ncm.cbSize = sizeof(ncm);
-    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
-    {
-      ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
-      return FALSE;
-    }
-
-    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFont == NULL)
-    {
-      ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
-      return FALSE;
-    }
-
-    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
-    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
-    if(hMenuFontBold == NULL)
-    {
-      ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
-      DeleteObject(hMenuFont);
-      hMenuFont = NULL;
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-VOID
-MenuCleanup(VOID)
-{
-  if (hMenuFont)
-  {
-    DeleteObject(hMenuFont);
-    hMenuFont = NULL;
-  }
-
-  if (hMenuFontBold)
-  {
-    DeleteObject(hMenuFontBold);
-    hMenuFontBold = NULL;
-  }
-}
 
 /***********************************************************************
  *           DrawMenuBarTemp   (USER32.@)
@@ -2943,36 +2754,8 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font)
 
   return MenuInfo.cyMenu;
 }
-#if 0
-static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
-{
-    POPUPMENU *menu;
-    DWORD ex_style = 0;
-
-    TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
 
-    if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
-
-    /* store the owner for DrawItem */
-    if (!IsWindow( hwndOwner ))
-    {
-        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return FALSE;
-    }
-    menu->hwndOwner = hwndOwner;
-
-    if (flags & TPM_LAYOUTRTL)
-        ex_style = WS_EX_LAYOUTRTL;
 
-    /* NOTE: In Windows, top menu popup is not owned. */
-    menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL,
-                                WS_POPUP, 0, 0, 0, 0,
-                                hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
-                                (LPVOID)hmenu );
-    if( !menu->hWnd ) return FALSE;
-    return TRUE;
-}
-#endif
 /***********************************************************************
  *           MenuShowSubPopup
  *
@@ -2982,7 +2765,6 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
 static HMENU FASTCALL
 MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags)
 {
-  extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
   RECT Rect;
   ROSMENUITEMINFO ItemInfo;
   ROSMENUINFO SubMenuInfo;
@@ -3100,7 +2882,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
   /* use default alignment for submenus */
   Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
 
-  //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
+  MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
 
   MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags,
                 Rect.left, Rect.top, Rect.right, Rect.bottom );
@@ -3124,11 +2906,10 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
  */
 void MENU_EndMenu( HWND hwnd )
 {
-    ROSMENUINFO MenuInfo;
-    BOOL Ret = FALSE;
-    if (top_popup_hmenu)
-       Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu);
-    if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu();
+    MENU *menu;
+    menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL;
+    if (menu && ( hwnd == menu->hWnd ||  hwnd == (menu->spwndNotify ? menu->spwndNotify->head.h : NULL)) )
+       EndMenu();
 }
 
 /***********************************************************************
@@ -3163,13 +2944,19 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo,
       {
           MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags);
           MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL);
-          DestroyWindow(SubMenuInfo.Wnd);
-          SubMenuInfo.Wnd = NULL;
-          MenuSetRosMenuInfo(&SubMenuInfo);
 
+          DestroyWindow(SubMenuInfo.Wnd);
+          /* Native returns handle to destroyed window */
           if (!(wFlags & TPM_NONOTIFY))
              SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu,
                                  MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) );
+          ////
+          // Call WM_UNINITMENUPOPUP FIRST before destroy!!
+          // Fixes todo_wine User32 test menu.c line 2233 GetMenuBarInfo callback....
+          //
+          SubMenuInfo.Wnd = NULL;
+          MenuSetRosMenuInfo(&SubMenuInfo);
+          ////
       }
   }
 }
@@ -3281,7 +3068,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags)
  * Return TRUE if we can go on with menu tracking.
  */
 static BOOL FASTCALL
-MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
 {
   int Index;
   ROSMENUINFO MenuInfo;
@@ -3344,7 +3131,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
  *
  */
 static INT FASTCALL
-MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
 {
   INT Id;
   ROSMENUINFO MenuInfo;
@@ -3399,56 +3186,41 @@ MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
  * Walks menu chain trying to find a menu pt maps to.
  */
 static HMENU FASTCALL
-MenuPtMenu(HMENU Menu, POINT Pt)
+MENU_PtMenu(HMENU hMenu, POINT pt)
 {
-  extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
-  HMENU Ret = NULL;
-  INT Ht;
+  MENU *menu;
+  PITEM pItem;
+  HMENU ret = NULL;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
-    {
-      return NULL;
-    }
+  menu = MENU_GetMenu( hMenu );
+  if (!menu) return NULL;
 
   /* try subpopup first (if any) */
-  if (NO_SELECTED_ITEM != MenuInfo.iItem)
-    {
-      MenuInitRosMenuItemInfo(&ItemInfo);
-      if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) &&
-          0 != (ItemInfo.hSubMenu) &&
-          0 != (ItemInfo.fState & MF_MOUSESELECT))
-        {
-          Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt);
-          if (NULL != Ret)
-            {
-              MenuCleanupRosMenuItemInfo(&ItemInfo);
-              return Ret;
-            }
-        }
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-    }
+  if (menu->iItem != NO_SELECTED_ITEM)
+  {
+     pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+     if ( pItem ) pItem = &pItem[menu->iItem];
+     if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT)
+     {
+        PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
+        ret = MENU_PtMenu( UserHMGetHandle(pSubMenu), pt);
+     }
+  }
 
   /* check the current window (avoiding WM_HITTEST) */
-  Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt);
-  if (0 != (MenuInfo.fFlags & MNF_POPUP))
-    {
-      if (HTNOWHERE != Ht && HTERROR != Ht)
-        {
-          Ret = Menu;
-        }
-    }
-  else if (HTSYSMENU == Ht)
-    {
-      Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE);
-    }
-  else if (HTMENU == Ht)
-    {
-      Ret = GetMenu(MenuInfo.Wnd);
-    }
-
-  return Ret;
+  if (!ret)
+  {
+     INT ht = DefWndNCHitTest(menu->hWnd, pt);
+     if ( menu->fFlags & MNF_POPUP )
+     {
+        if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu;
+     }
+     else if (ht == HTSYSMENU)
+        ret = NtUserGetSystemMenu(menu->hWnd, FALSE);
+     else if (ht == HTMENU)
+        ret = GetMenu( menu->hWnd );
+  }
+  return ret;
 }
 
 /***********************************************************************
@@ -3513,32 +3285,25 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
  *
  * Return the handle of the selected sub-popup menu (if any).
  */
-static HMENU FASTCALL
-MenuGetSubPopup(HMENU Menu)
+static
+HMENU MENU_GetSubPopup( HMENU hmenu )
 {
-  ROSMENUINFO MenuInfo;
-  ROSMENUITEMINFO ItemInfo;
+    MENU *menu;
+    ITEM *item;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Menu)
-      || NO_SELECTED_ITEM == MenuInfo.iItem)
-    {
-      return NULL;
-    }
+    menu = MENU_GetMenu( hmenu );
 
-  MenuInitRosMenuItemInfo(&ItemInfo);
-  if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo))
-    {
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-      return NULL;
-    }
-  if (0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT))
+    if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0;
+
+    //item = &menu->rgItems[menu->iItem];
+    item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+    if (item) item = &item[menu->iItem];
+    if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT))
     {
-      MenuCleanupRosMenuItemInfo(&ItemInfo);
-      return ItemInfo.hSubMenu;
+       PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu);
+       return UserHMGetHandle(pSubMenu);
     }
-
-  MenuCleanupRosMenuItemInfo(&ItemInfo);
-  return NULL;
+    return 0;
 }
 
 /***********************************************************************
@@ -3726,7 +3491,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags)
           while (MenuTmp != Mt->CurrentMenu)
             {
               MenuPrev = MenuTmp;
-              MenuTmp = MenuGetSubPopup(MenuPrev);
+              MenuTmp = MENU_GetSubPopup(MenuPrev);
             }
 
           if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
@@ -3757,13 +3522,8 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
 
   MenuPrev = MenuTmp = Mt->TopMenu;
 
-  if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
-    {
-      return;
-    }
-
   /* Try to move 1 column left (if possible) */
-  if ( (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo)) != NO_SELECTED_ITEM)
+  if ( (PrevCol = MENU_GetStartOfPrevColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
   {
      if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
      {
@@ -3776,7 +3536,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags)
   while (MenuTmp != Mt->CurrentMenu)
     {
       MenuPrev = MenuTmp;
-      MenuTmp = MenuGetSubPopup(MenuPrev);
+      MenuTmp = MENU_GetSubPopup(MenuPrev);
     }
 
   if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev))
@@ -3844,13 +3604,8 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags)
       if (hmenutmp != Mt->CurrentMenu) return;
     }
 
-    if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
-    {
-      return;
-    }
-
     /* Check to see if there's another column */
-    if ( (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo)) != NO_SELECTED_ITEM)
+    if ( (NextCol = MENU_GetStartOfNextColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
     {
        TRACE("Going to %d.\n", NextCol);
        if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
@@ -3899,6 +3654,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     MSG msg;
     ROSMENUINFO MenuInfo;
     ROSMENUITEMINFO ItemInfo;
+    PMENU menu;
     BOOL fRemove;
     INT executedMenuId = -1;
     MTRACKER mt;
@@ -3918,12 +3674,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
 
     if (!IsMenu(hmenu))
     {
-        WARN("Invalid menu handle %p\n", hmenu);
-        SetLastError( ERROR_INVALID_MENU_HANDLE );
+        WARN("Invalid menu handle %p\n", hmenu); // Error already set in IsMenu.
         return FALSE;
     }
 
-    fEndMenu = FALSE;
     if (! MenuGetRosMenuInfo(&MenuInfo, hmenu))
     {
         return FALSE;
@@ -3932,7 +3686,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     if (wFlags & TPM_BUTTONDOWN)
     {
         /* Get the result in order to start the tracking or not */
-        fRemove = MenuButtonDown( &mt, hmenu, wFlags );
+        fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
         fEndMenu = !fRemove;
     }
 
@@ -3943,10 +3697,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
     NtUserxSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1
     SetCapture(capture_win);                                          // 2
 
-    while (! fEndMenu)
+    while (!fEndMenu)
     {
         BOOL ErrorExit = FALSE;
-        PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU);
+        menu = MENU_GetMenu( mt.CurrentMenu );
         if (!menu) /* sometimes happens if I do a window manager close */
            break;
 
@@ -3964,7 +3718,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             else
             {
                 /* ReactOS Check */
-                if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd))
+                if (!ValidateHwndNoErr(mt.OwnerWnd) || !ValidateHwndNoErr(MenuInfo.Wnd))
                 {
                    ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works.
                    break;
@@ -4012,14 +3766,13 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
             mt.Pt.y = (short)HIWORD(msg.lParam);
 
             /* Find a menu for this mouse event */
-            hmenu = MenuPtMenu(mt.TopMenu, mt.Pt);
+            hmenu = MENU_PtMenu(mt.TopMenu, mt.Pt);
 
             switch(msg.message)
             {
                 /* no WM_NC... messages in captured state */
 
                 case WM_RBUTTONDBLCLK:
-                    ERR("WM_RBUTTONDBLCLK\n");
                 case WM_RBUTTONDOWN:
                      if (!(wFlags & TPM_RIGHTBUTTON)) break;
                     /* fall through */
@@ -4027,7 +3780,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                 case WM_LBUTTONDOWN:
                     /* If the message belongs to the menu, removes it from the queue */
                     /* Else, end menu tracking */
-                    fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+                    fRemove = MENU_ButtonDown(&mt, hmenu, wFlags);
                     fEndMenu = !fRemove;
                     break;
 
@@ -4038,7 +3791,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     /* Check if a menu was selected by the mouse */
                     if (hmenu)
                     {
-                        executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+                        executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
                         TRACE("executedMenuId %d\n", executedMenuId);
 
                     /* End the loop if executedMenuId is an item ID */
@@ -4080,10 +3833,8 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     case VK_END:
                         if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
                         {
-                            MenuSelectItem(mt.OwnerWnd, &MenuInfo,
-                                    NO_SELECTED_ITEM, FALSE, 0 );
-                            MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                              VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+                            MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
+                            MenuMoveSelection(mt.OwnerWnd, &MenuInfo, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
                         }
                         break;
 
@@ -4097,8 +3848,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                                     mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
                             }
                             else      /* otherwise try to move selection */
-                                MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
-                                       (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
+                                MenuMoveSelection(mt.OwnerWnd, &MenuInfo, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
                         }
                         break;
 
@@ -4168,14 +3918,12 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     /* We will find a better way real soon... */
                     if (msg.wParam < 32) break;
 
-                    pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo,
-                                          LOWORD(msg.wParam), FALSE);
+                    pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE);
                     if (pos == (UINT)-2) fEndMenu = TRUE;
                     else if (pos == (UINT)-1) MessageBeep(0);
                     else
                     {
-                        MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos,
-                            TRUE, 0);
+                        MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, TRUE, 0);
                         executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
                         fEndMenu = (executedMenuId != -2);
                     }
@@ -4219,6 +3967,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
                     IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
                     DestroyWindow(MenuInfo.Wnd);
                     MenuInfo.Wnd = NULL;
+                    MenuSetRosMenuInfo(&MenuInfo);
 
                     if (!(wFlags & TPM_NONOTIFY))
                       SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu,
@@ -4259,11 +4008,19 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
      * It also enables menus to be displayed in more than one window,
      * but there are some bugs left that need to be fixed in this case.
      */
-    if (MenuGetRosMenuInfo(&MenuInfo, hMenu))
+    if (!bPopup && (MenuGetRosMenuInfo(&MenuInfo, hMenu)))
     {
         MenuInfo.Wnd = hWnd;
         MenuSetRosMenuInfo(&MenuInfo);
     }
+    //if (!bPopup) menu->hWnd = hWnd;
+    if (!top_popup)
+    {
+       top_popup = MenuInfo.Wnd;//menu->hWnd;
+       top_popup_hmenu = hMenu;
+    }
+
+    fEndMenu = FALSE;
 
     /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
     if (!(wFlags & TPM_NONOTIFY))
@@ -4294,6 +4051,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
                        CHILDID_SELF, 0);
     return TRUE;
 }
+
 /***********************************************************************
  *           MenuExitTracking
  */
@@ -4337,7 +4095,6 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
     }
 }
 
-
 /***********************************************************************
  *           MenuTrackKbdMenuBar
  *
@@ -4373,6 +4130,9 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
 
     MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags );
 
+    /* fetch the window menu again, it may have changed */
+    hTrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( hwnd ) : GetMenu( hwnd );
+
     if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu))
     {
       goto track_menu;
@@ -4380,7 +4140,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
 
     if( wChar && wChar != ' ' )
     {
-        uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) );
+        uItem = MENU_FindItemByKey( hwnd, hTrackMenu, wChar, (wParam & HTSYSMENU) );
         if ( uItem >= (UINT)(-2) )
         {
             if( uItem == (UINT)(-1) ) MessageBeep(0);
@@ -4408,42 +4168,59 @@ track_menu:
 /**********************************************************************
  *           TrackPopupMenuEx   (USER32.@)
  */
-BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
-                              HWND Wnd, LPTPMPARAMS Tpm)
+BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, int x, int y,
+                              HWND hWnd, LPTPMPARAMS lpTpm)
 {
     BOOL ret = FALSE;
-    ROSMENUINFO MenuInfo;
+    MENU *menu;
+
+    TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n",
+            hMenu, wFlags, x, y, hWnd, lpTpm,
+            lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
 
-    if (!IsMenu(Menu))    
+    /* Parameter check */
+    /* FIXME: this check is performed several times, here and in the called
+       functions. That could be optimized */
+    if (!(menu = MENU_GetMenu( hMenu )))
     {
       SetLastError( ERROR_INVALID_MENU_HANDLE );
       return FALSE;
     }
 
-    /* ReactOS Check */
-    if (!ValidateHwnd(Wnd))
-    {
-       /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */
-       return FALSE;
-    }
-
-    MenuGetRosMenuInfo(&MenuInfo, Menu);
-    if (IsWindow(MenuInfo.Wnd))
+    if (IsWindow(menu->hWnd))
     {
         SetLastError( ERROR_POPUP_ALREADY_ACTIVE );
         return FALSE;
     }
 
-    MenuInitTracking(Wnd, Menu, TRUE, Flags);
+    if (MENU_InitPopup( hWnd, hMenu, wFlags ))
+    {
+       MenuInitTracking(hWnd, hMenu, TRUE, wFlags);
+
+       /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+       if (!(wFlags & TPM_NONOTIFY))
+           SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0);
 
-    /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
-    if (!(Flags & TPM_NONOTIFY))
-        SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+       if (MenuShowPopup(hWnd, hMenu, 0, wFlags, x, y, 0, 0 ))
+          ret = MenuTrackMenu(hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,
+                              lpTpm ? &lpTpm->rcExclude : NULL);
+       MenuExitTracking(hWnd, TRUE);
 
-    if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
-       ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd,
-                           Tpm ? &Tpm->rcExclude : NULL);
-    MenuExitTracking(Wnd, TRUE);
+       if (menu->hWnd)
+       {
+          ROSMENUINFO MenuInfo;
+          if (IsWindow( menu->hWnd )) // wine hack around this with their destroy function.
+             DestroyWindow( menu->hWnd ); // Fix wrong error return.
+          //menu->hWnd = 0;
+          MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+          MenuInfo.Wnd = 0;
+          MenuSetRosMenuInfo(&MenuInfo);
+          
+          if (!(wFlags & TPM_NONOTIFY))
+             SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu,
+                                            MAKELPARAM(0, IS_SYSTEM_MENU(menu)) );  
+       }
+    }
     return ret;
 }
 
@@ -4456,164 +4233,63 @@ BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y,
     return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL);
 }
 
-/*
- *  From MSDN:
- *  The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
- *  with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType.
- *
- *  Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE.
- *
- *  MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows
- *  2K/XP: MIIM_TYPE is replaced by  MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
- *  MFT_STRING is replaced by MIIM_STRING.
- *  (So, I guess we should use MIIM_STRING only for strings?)
- *
- *  MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member.
- *
- *  Based on wine, SetMenuItemInfo_common:
- *  1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE,
- *     it will result in a error.
- *  2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error.
- *     These conditions are addressed in Win32k IntSetMenuItemInfo.
+/**********************************************************************
+ *         MENU_mnu2mnuii
  *
+ * Uses flags, id and text ptr, passed by InsertMenu() and
+ * ModifyMenu() to setup a MenuItemInfo structure.
  */
-static
-BOOL
-FASTCALL
-MenuSetItemData(
-  LPMENUITEMINFOW mii,
-  UINT Flags,
-  UINT_PTR IDNewItem,
-  LPCWSTR NewItem,
-  BOOL Unicode)
+static void MENU_mnu2mnuii( UINT flags, UINT_PTR id, LPCWSTR str, LPMENUITEMINFOW pmii, BOOL Unicode)
 {
-/*
- * Let us assume MIIM_FTYPE is set and building a new menu item structure.
- */
-  if(Flags & MF_BITMAP)
-  {
-     mii->fMask |= MIIM_BITMAP;   /* Use the new way of seting hbmpItem.*/
-     mii->hbmpItem = (HBITMAP) NewItem;
-
-     if (Flags & MF_HELP)
-     {
-         /* increase ident */
-         mii->fType |= MF_HELP;
-     }
-  }
-  else if(Flags & MF_OWNERDRAW)
-  {
-    mii->fType |= MFT_OWNERDRAW;
-    mii->fMask |= MIIM_DATA;
-    mii->dwItemData = (DWORD_PTR) NewItem;
-  }
-  else if (Flags & MF_SEPARATOR)
-  {
-    mii->fType |= MFT_SEPARATOR;
-    if (!(Flags & (MF_GRAYED|MF_DISABLED)))
-      Flags |= MF_GRAYED|MF_DISABLED;
-  }
-  else /* Default action MF_STRING. */
-  {
-    /* Item beginning with a backspace is a help item */
-    if (NewItem != NULL)
-    {
-       if (Unicode)
-       {
-          if (*NewItem == '\b')
-          {
-             mii->fType |= MF_HELP;
-             NewItem++;
-          }
-       }
-       else
-       {
-          LPCSTR NewItemA = (LPCSTR) NewItem;
-          if (*NewItemA == '\b')
-          {
-             mii->fType |= MF_HELP;
-             NewItemA++;
-             NewItem = (LPCWSTR) NewItemA;
-          }
-       }
-
-       if (Flags & MF_HELP)
-         mii->fType |= MF_HELP;
-       mii->fMask |= MIIM_STRING;
-       mii->fType |= MFT_STRING; /* Zero */
-       mii->dwTypeData = (LPWSTR)NewItem;
-       if (Unicode)
-         mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem));
-       else
-         mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem));
-    }
-    else
-    {
-      mii->fType |= MFT_SEPARATOR;
-      if (!(Flags & (MF_GRAYED|MF_DISABLED)))
-        Flags |= MF_GRAYED|MF_DISABLED;
-    }
-  }
-
-  if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */
-  {
-    mii->fType |= MFT_RIGHTJUSTIFY;
-  }
-
-  if(Flags & MF_MENUBREAK)
-  {
-    mii->fType |= MFT_MENUBREAK;
-  }
-  else if(Flags & MF_MENUBARBREAK)
-  {
-    mii->fType |= MFT_MENUBARBREAK;
-  }
-
-  if(Flags & MF_GRAYED || Flags & MF_DISABLED)
-  {
-    if (Flags & MF_GRAYED)
-      mii->fState |= MF_GRAYED;
-
-    if (Flags & MF_DISABLED)
-      mii->fState |= MF_DISABLED;
-
-    mii->fMask |= MIIM_STATE;
-  }
-  else if (Flags & MF_HILITE)
-  {
-    mii->fState |= MF_HILITE;
-    mii->fMask |= MIIM_STATE;
-  }
-  else /* default state */
-  {
-    mii->fState |= MFS_ENABLED;
-    mii->fMask |= MIIM_STATE;
-  }
-
-  if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem))
-  {
-    mii->fMask |= MIIM_SUBMENU;
-    mii->hSubMenu = (HMENU)IDNewItem;
-  }
-  mii->fMask |= MIIM_ID;
-  mii->wID = (UINT)IDNewItem;
-  return TRUE;
-}
-
-NTSTATUS WINAPI
-User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
-{
-  PLOADMENU_CALLBACK_ARGUMENTS Common;
-  LRESULT Result;  
-
-  Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
-  
-  Result = (LRESULT)LoadMenuW( Common->hModule,
-                               IS_INTRESOURCE(Common->MenuName[0]) ?
-                                  MAKEINTRESOURCE(Common->MenuName[0]) :
-                                        (LPCWSTR)&Common->MenuName);
-
-  return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+    RtlZeroMemory( pmii, sizeof( MENUITEMINFOW));
+    pmii->cbSize = sizeof( MENUITEMINFOW);
+    pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
+    /* setting bitmap clears text and vice versa */
+    if( IS_STRING_ITEM(flags)) {
+        pmii->fMask |= MIIM_STRING | MIIM_BITMAP;
+        if( !str)
+            flags |= MF_SEPARATOR;
+        /* Item beginning with a backspace is a help item */
+        /* FIXME: wrong place, this is only true in win16 */
+        else
+        {
+            if (Unicode)
+           {
+              if (*str == '\b')
+              {
+                flags |= MF_HELP;
+                str++;
+              }
+           }
+           else
+           {
+              LPCSTR NewItemA = (LPCSTR) str;
+              if (*NewItemA == '\b')
+              {
+                 flags |= MF_HELP;
+                 NewItemA++;
+                 str = (LPCWSTR) NewItemA;
+              }
+              TRACE("A cch %d\n",strlen(NewItemA));
+           }
+        }
+        pmii->dwTypeData = (LPWSTR)str;
+    } else if( flags & MFT_BITMAP){
+        pmii->fMask |= MIIM_BITMAP | MIIM_STRING;
+        pmii->hbmpItem = (HBITMAP)str;
+    }
+    if( flags & MF_OWNERDRAW){
+        pmii->fMask |= MIIM_DATA;
+        pmii->dwItemData = (ULONG_PTR) str;
+    }
+    if( flags & MF_POPUP && MENU_GetMenu((HMENU)id)) {
+        pmii->fMask |= MIIM_SUBMENU;
+        pmii->hSubMenu = (HMENU)id;
+    }
+    if( flags & MF_SEPARATOR) flags |= MF_GRAYED | MF_DISABLED;
+    pmii->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT;
+    pmii->fType = flags & MENUITEMINFO_TYPE_MASK;
+    pmii->wID = (UINT)id;
 }
 
 /**********************************************************************
@@ -4670,6 +4346,104 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in,
     return TRUE;
 }
 
+BOOL
+MenuInit(VOID)
+{
+  NONCLIENTMETRICSW ncm;
+
+  /* get the menu font */
+  if(!hMenuFont || !hMenuFontBold)
+  {
+    ncm.cbSize = sizeof(ncm);
+    if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+    {
+      ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
+      return FALSE;
+    }
+
+    hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFont == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
+      return FALSE;
+    }
+
+    ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+    hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
+    if(hMenuFontBold == NULL)
+    {
+      ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+      DeleteObject(hMenuFont);
+      hMenuFont = NULL;
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+VOID
+MenuCleanup(VOID)
+{
+  if (hMenuFont)
+  {
+    DeleteObject(hMenuFont);
+    hMenuFont = NULL;
+  }
+
+  if (hMenuFontBold)
+  {
+    DeleteObject(hMenuFontBold);
+    hMenuFontBold = NULL;
+  }
+}
+
+NTSTATUS WINAPI
+User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+  HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
+  LRESULT Result = (LRESULT)hmenu;
+  MENUINFO menuinfo = {0};
+  MENUITEMINFOW info = {0};
+
+  // removing space for checkboxes from menu
+  menuinfo.cbSize = sizeof(menuinfo);
+  menuinfo.fMask = MIM_STYLE;
+  GetMenuInfo(hmenu, &menuinfo);
+  menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
+  SetMenuInfo(hmenu, &menuinfo);
+
+  // adding bitmaps to menu items
+  info.cbSize = sizeof(info);
+  info.fMask |= MIIM_BITMAP;
+  info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_RESTORE;
+  SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+  SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
+  info.hbmpItem = HBMMENU_POPUP_CLOSE;
+  SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
+
+  return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
+}
+
+NTSTATUS WINAPI
+User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+  PLOADMENU_CALLBACK_ARGUMENTS Common;
+  LRESULT Result;
+
+  Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
+
+  Result = (LRESULT)LoadMenuW( Common->hModule,
+                               IS_INTRESOURCE(Common->MenuName[0]) ?
+                                  MAKEINTRESOURCE(Common->MenuName[0]) :
+                                        (LPCWSTR)&Common->MenuName);
+
+  return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
@@ -4682,7 +4456,33 @@ AppendMenuA(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCSTR lpNewItem)
 {
-  return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("AMA Handle bitmaps\n");
+  }
+  ////// Answer a question, why a -1? To hunt for the end of the item list. Get it, to Append?
+  res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -4694,7 +4494,23 @@ AppendMenuW(HMENU hMenu,
            UINT_PTR uIDNewItem,
            LPCWSTR lpNewItem)
 {
-  return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+  MENUITEMINFOW mii;
+  UNICODE_STRING MenuText;
+  BOOL res;
+
+  RtlInitUnicodeString(&MenuText, 0);    
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -4720,7 +4536,6 @@ CheckMenuItem(HMENU hmenu,
   return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck);
 }
 
-
 /*
  * @implemented
  */
@@ -4855,7 +4670,7 @@ EndMenu(VOID)
       /* don't end up with an orphaned menu */
       PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
   }
-  return TRUE;
+  return fEndMenu;
 }
 
 BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
@@ -4891,7 +4706,6 @@ GetMenu(HWND hWnd)
        return UlongToHandle(Wnd->IDMenu);
 }
 
-
 /*
  * @implemented
  */
@@ -5005,28 +4819,10 @@ UINT WINAPI
 GetMenuItemID(HMENU hMenu,
              int nPos)
 {
-  PMENU pMenu;
-  PITEM pItem;
-  INT i = 0;
-
-  if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU)))
-     return -1;
-
-  pItem = pMenu->rgItems ? DesktopPtrToUser(pMenu->rgItems) : NULL;
-  if ( nPos >= 0 )
-  {
-     //pItem = &menu->rgItems[nPos]; or pItem[nPos]; after dptu.
-     while(pItem) // Do this for now.
-     {
-        if (i < (INT)pMenu->cItems)
-        {
-           if ( nPos == i && !pItem->spSubMenu) return pItem->wID;
-        }
-        pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
-        i++;
-     }
-  }
-  return -1;
+  ITEM * lpmi;
+  if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1;
+  if (lpmi->spSubMenu) return -1;
+  return lpmi->wID;
 }
 
 /*
@@ -5096,18 +4892,21 @@ GetMenuState(
   UINT uFlags)
 {
   PITEM pItem;
+  UINT Type = 0;
   TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags);
   if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1;
 
+  if (!pItem->Xlpstr && pItem->hbmp) Type = MFT_BITMAP;
+
   if (pItem->spSubMenu)
   {
      PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
      HMENU hsubmenu = UserHMGetHandle(pSubMenu);
      if (!IsMenu(hsubmenu)) return (UINT)-1;
-     else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff);
+     else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|Type) & 0xff);
   }
   else
-     return (pItem->fType | pItem->fState);  
+     return (pItem->fType | pItem->fState | Type);  
 }
 
 /*
@@ -5122,18 +4921,6 @@ GetMenuStringA(
   int nMaxCount,
   UINT uFlag)
 {
-/*  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.dwTypeData = lpString;
-  mii.fMask = MIIM_STRING;
-  mii.cbSize = sizeof(MENUITEMINFOA);
-  mii.cch = nMaxCount;
-
-  if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
-     return 0;
-  else
-     return mii.cch;
-*/
   ITEM *item;
   LPWSTR text;
   ////// wine Code, seems to be faster.
@@ -5153,7 +4940,7 @@ GetMenuStringA(
   if (!lpString || !nMaxCount) return WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL );
   if (!WideCharToMultiByte( CP_ACP, 0, text, -1, lpString, nMaxCount, NULL, NULL ))
       lpString[nMaxCount-1] = 0;
-  ERR("returning %s\n", lpString);
+  TRACE("A returning %s\n", lpString);
   return strlen(lpString);
 }
 
@@ -5169,19 +4956,6 @@ GetMenuStringW(
   int nMaxCount,
   UINT uFlag)
 {
-/*  MENUITEMINFOW miiW;
-  memset( &miiW, 0, sizeof(miiW) );
-  miiW.dwTypeData = lpString;
-  miiW.fMask = MIIM_STRING | MIIM_FTYPE;
-  miiW.fType = MFT_STRING;
-  miiW.cbSize = sizeof(MENUITEMINFOW);
-  miiW.cch = nMaxCount;
-
-  if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
-     return 0;
-  else
-     return miiW.cch;
-*/
   ITEM *item;
   LPWSTR text;
 
@@ -5204,7 +4978,7 @@ GetMenuStringW(
       return 0;
   }
   lstrcpynW( lpString, text, nMaxCount );
-  ERR("returning %S\n", lpString);
+  TRACE("W returning %S\n", lpString);
   return strlenW(lpString);
 }
 
@@ -5257,18 +5031,32 @@ InsertMenuA(
   UINT_PTR uIDNewItem,
   LPCSTR lpNewItem)
 {
-  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOA);
-  mii.fMask = MIIM_FTYPE;
-
-  MenuSetItemData((LPMENUITEMINFOW) &mii,
-                  uFlags,
-                  uIDNewItem,
-                 (LPCWSTR) lpNewItem,
-                  FALSE);
-
-  return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -5307,7 +5095,7 @@ InsertMenuItemA(
   }
   else
   {
-      UnicodeString.Buffer = NULL;
+      TRACE("Handle bitmaps\n");
   }
   res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString);
   if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
@@ -5365,17 +5153,22 @@ InsertMenuW(
   LPCWSTR lpNewItem)
 {
   MENUITEMINFOW mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOW);
-  mii.fMask = MIIM_FTYPE;
+  UNICODE_STRING MenuText;
+  BOOL res;
 
-  MenuSetItemData( &mii,
-                  uFlags,
-                  uIDNewItem,
-                  lpNewItem,
-                  TRUE);
+  RtlInitUnicodeString(&MenuText, 0);    
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
 
-  return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -5489,30 +5282,38 @@ MenuItemFromPoint(
 BOOL
 WINAPI
 ModifyMenuA(
-  HMENU hMnu,
+  HMENU hMenu,
   UINT uPosition,
   UINT uFlags,
   UINT_PTR uIDNewItem,
   LPCSTR lpNewItem)
 {
-  MENUITEMINFOA mii;
-  memset( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOA); 
-  mii.fMask = MIIM_FTYPE;
-
-  MenuSetItemData((LPMENUITEMINFOW) &mii,
-                  uFlags,
-                  uIDNewItem,
-                 (LPCWSTR) lpNewItem,
-                  FALSE);
-
-  //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
-  //  NtUserDestroyMenu( mii.hSubMenu );   /* ModifyMenu() spec */
-
-  return SetMenuItemInfoA( hMnu,
-                           uPosition,
-                          (BOOL)(MF_BYPOSITION & uFlags),
-                           &mii);
+  MENUITEMINFOW mii;
+  UNICODE_STRING UnicodeString;
+  BOOL res;
+
+  RtlInitUnicodeString(&UnicodeString, 0);
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+      if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+      {
+        SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+      }
+      mii.dwTypeData = UnicodeString.Buffer;
+      mii.cch = UnicodeString.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString);
+  if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+  return res;
 }
 
 /*
@@ -5521,31 +5322,33 @@ ModifyMenuA(
 BOOL
 WINAPI
 ModifyMenuW(
-  HMENU hMnu,
+  HMENU hMenu,
   UINT uPosition,
   UINT uFlags,
   UINT_PTR uIDNewItem,
   LPCWSTR lpNewItem)
 {
   MENUITEMINFOW mii;
-  memset ( &mii, 0, sizeof(mii) );
-  mii.cbSize = sizeof(MENUITEMINFOW);
-  mii.fMask = MIIM_FTYPE;
-
-  /* Init new data for this menu item */
-  MenuSetItemData( &mii,
-                  uFlags,
-                  uIDNewItem,
-                  lpNewItem,
-                  TRUE);
-
-  //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
-  //  NtUserDestroyMenu( mii.hSubMenu );   /* ModifyMenu() spec */
-
-  return SetMenuItemInfoW( hMnu,
-                           uPosition,
-                           (BOOL)(MF_BYPOSITION & uFlags),
-                           &mii);
+  UNICODE_STRING MenuText;
+  BOOL res;
+
+  RtlInitUnicodeString(&MenuText, 0);    
+
+  MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+  /* copy the text string, it wll be one or the other */
+  if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+  {
+    RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+    mii.dwTypeData = MenuText.Buffer;
+    mii.cch = MenuText.Length / sizeof(WCHAR);
+  }
+  else
+  {
+      TRACE("Handle bitmaps\n");
+  }
+  res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText);
+  return res;
 }
 
 /*
@@ -5729,8 +5532,6 @@ NEWTrackPopupMenu(
                                  NULL); // LPTPMPARAMS is null
 }
 
-
-
 /*
  * @unimplemented
  */
@@ -5756,7 +5557,6 @@ MenuWindowProcA(
      return FALSE;
   }
   return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE);
-
 }
 
 /*
index a780e82..3b6db97 100644 (file)
@@ -1,6 +1,6 @@
 // SVC_(<NAME>, <ARG_COUNT>)
 //
-// Funcs, order, should, match, Windows, XP, 5.1.2600, SP2)
+// Funcs order should match Windows XP 5.1.2600 SP2
 //
 SVC_(GdiAbortDoc, 1)
 SVC_(GdiAbortPath, 1)
@@ -235,7 +235,7 @@ SVC_(GdiMonoBitmap, 1)
 SVC_(GdiMoveTo, 4)
 SVC_(GdiOffsetClipRgn, 3)
 SVC_(GdiOffsetRgn, 3)
-SVC_(GdiOpenDCW, 8)
+SVC_(GdiOpenDCW, 8) /* FIXME: 7 params on XP/2k3 */
 SVC_(GdiPatBlt, 6)
 SVC_(GdiPolyPatBlt, 5)
 SVC_(GdiPathToRegion, 1)
@@ -374,8 +374,7 @@ SVC_(UserEndDeferWindowPosEx, 2)
 SVC_(UserEndMenu, 0)
 SVC_(UserEndPaint, 2)
 SVC_(UserEnumDisplayDevices, 4)
-// SVC_(UserEnumDisplayMonitors, 4, Wrong, number, of, param, ?)
-SVC_(UserEnumDisplayMonitors, 5)
+SVC_(UserEnumDisplayMonitors, 5) /* FIXME: 4 on XP/2k3 */
 SVC_(UserEnumDisplaySettings, 4)
 SVC_(UserEvent, 1)
 SVC_(UserExcludeUpdateRgn, 2)
@@ -496,7 +495,7 @@ SVC_(UserRealInternalGetMessage, 6)
 SVC_(UserRealWaitMessageEx, 2)
 SVC_(UserRedrawWindow, 4)
 SVC_(UserRegisterClassExWOW, 7)
-SVC_(UserRegisterUserApiHook, 4)
+SVC_(UserRegisterUserApiHook, 4) /* Note: 2 params on XP, 4 on 2k3 */
 SVC_(UserRegisterHotKey, 4)
 SVC_(UserRegisterRawInputDevices, 3)
 SVC_(UserRegisterTasklist, 1)
@@ -590,7 +589,7 @@ SVC_(UserUnregisterUserApiHook, 0)
 SVC_(UserUnregisterHotKey, 2)
 SVC_(UserUpdateInputContext, 3)
 SVC_(UserUpdateInstance, 3)
-SVC_(UserUpdateLayeredWindow, 10)
+SVC_(UserUpdateLayeredWindow, 10) /* Note: 9 params on XP, 10 on 2k3 */
 SVC_(UserGetLayeredWindowAttributes, 4)
 SVC_(UserSetLayeredWindowAttributes, 4)
 SVC_(UserUpdatePerUserSystemParameters, 2)