--- /dev/null
- HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","OS",0x00020000,"ReactOS"
+[Version]
+Signature = "$ReactOS$"
+
+[AddReg]
+
+HKLM,"SYSTEM\CurrentControlSet\Control","CurrentUser",2,"USERNAME"
+HKLM,"SYSTEM\CurrentControlSet\Control","WaitToKillServiceTimeout",2,"20000"
+HKLM,"SYSTEM\CurrentControlSet\Control\Biosinfo","InfName",2,"biosinfo.inf"
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP",,0x00000012
+
+HKLM,"SYSTEM\CurrentControlSet\Control\FileSystem","NtfsDisable8dot3NameCreation",0x00010003,0
+HKLM,"SYSTEM\CurrentControlSet\Control\FileSystem","Win31FileSystem",0x00010001,0
+HKLM,"SYSTEM\CurrentControlSet\Control\FileSystem","Win95TruncatedExtensions",0x00010001,1
+
+; Device classes (this list is incomplete... and should be generated from .inf files during installation)
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Client"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetClient"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}","Icon",0x00000000,"-7"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}","Installer32",0x00000000,"NetCfgx.dll,NetClassInstaller"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}","NoDisplayClass",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E973-E325-11CE-BFC1-08002BE10318}","NoInstallClass",0x00000000,"1"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Service"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetService"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}","Icon",0x00000000,"-7"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}","Installer32",0x00000000,"NetCfgx.dll,NetClassInstaller"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}","NoDisplayClass",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E974-E325-11CE-BFC1-08002BE10318}","NoInstallClass",0x00000000,"1"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Protocol"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetTrans"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}","Icon",0x00000000,"-6"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}","Installer32",0x00000000,"NetCfgx.dll,NetClassInstaller"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}","NoDisplayClass",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE10318}","NoInstallClass",0x00000000,"1"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{9D6D66A6-0B0C-4563-9077-A0E9A7955AE4}",,0x00000000,"Ramdisk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{9D6D66A6-0B0C-4563-9077-A0E9A7955AE4}","Class",0x00000000,"Ramdisk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{9D6D66A6-0B0C-4563-9077-A0E9A7955AE4}","Icon",0x00000000,"-5"
+
+; Default computer name settings
+HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName","ComputerName",0x00000002,"COMPUTERNAME"
+
+; Device classes key
+HKLM,"SYSTEM\CurrentControlSet\Control\DeviceClasses",,0x00000012
+
+; HAL Chipset Hacks
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","10390530",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","10390620",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","10B90533",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","10B91533",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","11060596",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","11060686",0x00010001,0x5
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","1166004F",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","11660050",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","11660200",0x00010001,0x1
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","80862410",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","80862420",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","80862440",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","8086244C",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","80862480",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","8086248C",0x00010001,0x8
+HKLM,"SYSTEM\CurrentControlSet\Control\HAL","80867110",0x00010001,0x1
+
+; Hardware profile settings
+HKLM,"SYSTEM\CurrentControlSet\Control\IDConfigDB",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\IDConfigDB","CurrentConfig",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Control\IDConfigDB\Hardware Profiles\0000","FriendlyName",0x00000000,"New Hardware Profile"
+
+; Keyboard Layouts
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000401","Layout File",0x00000000,"kbda1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000401","Layout Text",0x00000000,"Arabic (101)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000401","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5084"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010401","Layout File",0x00000000,"kbda2.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010401","Layout Text",0x00000000,"Arabic (102)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010401","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5085"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020401","Layout File",0x00000000,"kbda3.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020401","Layout Text",0x00000000,"Arabic (102) AZERTY"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020401","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5086"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000402","Layout File",0x00000000,"kbdbgm.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000402","Layout Text",0x00000000,"Bulgarian BDS 5237-1978"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000402","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5136"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020402","Layout File",0x00000000,"kbdbgt.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020402","Layout Text",0x00000000,"Bulgarian phonetic classic"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020402","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5134"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030402","Layout File",0x00000000,"kbdbga.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030402","Layout Text",0x00000000,"Bulgarian phonetic BDS 5237-2006"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030402","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5135"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000406","Layout File",0x00000000,"kbdda.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000406","Layout Text",0x00000000,"Danish"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000406","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5007"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030407","Layout File",0x00000000,"kbdgerg.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030407","Layout Text",0x00000000,"German (de_ergo)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030407","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5139"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020407","Layout File",0x00000000,"kbdgneo.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020407","Layout Text",0x00000000,"German (NEO-1.1)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020407","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5138"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010407","Layout File",0x00000000,"kbdgrist.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010407","Layout Text",0x00000000,"German (RISTOME)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010407","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5137"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000407","Layout File",0x00000000,"kbdgr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000407","Layout Text",0x00000000,"German"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000407","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5011"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000807","Layout File",0x00000000,"kbdsg.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000807","Layout Text",0x00000000,"Swiss (German)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000807","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5024"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000408","Layout File",0x00000000,"kbdhe.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000408","Layout Text",0x00000000,"Greek"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000408","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5046"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000409","Layout File",0x00000000,"kbdus.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000409","Layout Text",0x00000000,"United States"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5000"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000809","Layout File",0x00000000,"kbduk.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000809","Layout Text",0x00000000,"United Kingdom"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000809","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5025"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010409","Layout File",0x00000000,"kbddv.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010409","Layout Id", 0x00000000,"0002"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010409","Layout Text",0x00000000,"US-Dvorak"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5092"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020409","Layout File",0x00000000,"kbdusx.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020409","Layout Id", 0x00000000,"0001"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020409","Layout Text",0x00000000,"US International"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00020409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5026"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030409","Layout File",0x00000000,"kbdusl.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030409","Layout Id", 0x00000000,"001A"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030409","Layout Text",0x00000000,"US Dvorak for left hand"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00030409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5027"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00040409","Layout File",0x00000000,"kbdusr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00040409","Layout Id", 0x00000000,"001B"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00040409","Layout Text",0x00000000,"US Dvorak for right hand"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00040409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5028"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00050409","Layout File",0x00000000,"kbdusa.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00050409","Layout Id", 0x00000000,"000B"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00050409","Layout Text",0x00000000,"US English (IBM Arabic 238_L)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00050409","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5123"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00001809","Layout File",0x00000000,"kbdir.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00001809","Layout Text",0x00000000,"Irish"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00001809","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5014"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040a","Layout File",0x00000000,"kbdes.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040a","Layout Text",0x00000000,"Spanish"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5020"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080a","Layout File",0x00000000,"kbdla.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080a","Layout Text",0x00000000,"Latin American"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5017"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040b","Layout File",0x00000000,"kbdfi.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040b","Layout Text",0x00000000,"Finnish"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040b","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5009"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040c","Layout File",0x00000000,"kbdfr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040c","Layout Text",0x00000000,"French"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5010"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040d","Layout File",0x00000000,"kbdheb.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040d","Layout Text",0x00000000,"Hebrew"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040d","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5083"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040e","Layout File",0x00000000,"kbdhu.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040e","Layout Text",0x00000000,"Hungarian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040e","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5033"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040f","Layout File",0x00000000,"kbdic.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040f","Layout Text",0x00000000,"Icelandic"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000040f","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5013"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000410","Layout File",0x00000000,"kbdit.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000410","Layout Text",0x00000000,"Italian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000410","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5015"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout File",0x00000000,"kbdja.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout Text",0x00000000,"Japanese"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5061"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041c","Layout File",0x00000000,"kbdal.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041c","Layout Text",0x00000000,"Albanian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5029"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041f","Layout File",0x00000000,"kbdtuq.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041f","Layout Text",0x00000000,"Turkish Q"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041f","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5060"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041f","Layout File",0x00000000,"kbdtuf.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041f","Layout Text",0x00000000,"Turkish F"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041f","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5059"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041f","Layout Id",0x00000000,"0014"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080c","Layout File",0x00000000,"kbdbe.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080c","Layout Text",0x00000000,"Belgian (French)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000080c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5002"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000413","Layout File",0x00000000,"kbdne.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000413","Layout Text",0x00000000,"Dutch"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000413","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5008"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000813","Layout File",0x00000000,"kbdbe.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000813","Layout Text",0x00000000,"Belgian (Dutch)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000813","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5001"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000415","Layout File",0x00000000,"kbdpl1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000415","Layout Text",0x00000000,"Polish (Programmers)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000415","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5035"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010416","Layout File",0x00000000,"kbdbr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010416","Layout Text",0x00000000,"Portuguese (Brazilian ABNT2)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010416","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5126"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000816","Layout File",0x00000000,"kbdpo.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000816","Layout Text",0x00000000,"Portuguese (Portugal)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000816","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5019"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000418","Layout File",0x00000000,"kbdro.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000418","Layout Text",0x00000000,"Romanian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000418","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5037"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000419","Layout File",0x00000000,"kbdru.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000419","Layout Text",0x00000000,"Russian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000419","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5055"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010419","Layout File",0x00000000,"kbdru1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010419","Layout Text",0x00000000,"Russian (Typewriter)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010419","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5056"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041a","Layout File",0x00000000,"kbdcr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041a","Layout Text",0x00000000,"Croatian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5030"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041b","Layout File",0x00000000,"kbdsk.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041b","Layout Text",0x00000000,"Slovak"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041b","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5039"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041b","Layout File",0x00000000,"kbdsk1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041b","Layout Text",0x00000000,"Slovak (QWERTY)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041b","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5040"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041d","Layout File",0x00000000,"kbdsw.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041d","Layout Text",0x00000000,"Swedish"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041d","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5022"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041e","Layout File",0x00000000,"kbdth0.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041e","Layout Text",0x00000000,"Thai Kedmanee"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000041e","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5079"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041e","Layout File",0x00000000,"kbdth1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041e","Layout Text",0x00000000,"Thai Pattachote"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001041e","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5080"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0002041e","Layout File",0x00000000,"kbdth2.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0002041e","Layout Text",0x00000000,"Thai Kedmanee (non-ShiftLock)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0002041e","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5081"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0003041e","Layout File",0x00000000,"kbdth3.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0003041e","Layout Text",0x00000000,"Thai Pattachote (non-ShiftLock)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0003041e","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5082"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000422","Layout File",0x00000000,"kbdur.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000422","Layout Text",0x00000000,"Ukrainian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000422","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5058"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010422","Layout File",0x00000000,"kbdurs.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010422","Layout Text",0x00000000,"Ukrainian (Student)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010422","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5141"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000423","Layout File",0x00000000,"kbdblr.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000423","Layout Text",0x00000000,"Belarusian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000423","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5052"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000425","Layout File",0x00000000,"kbdest.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000425","Layout Text",0x00000000,"Estonian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000425","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5042"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000426","Layout File",0x00000000,"kbdlv.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000426","Layout Text",0x00000000,"Latvian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000426","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5043"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010427","Layout File",0x00000000,"kbdlt1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010427","Layout Text",0x00000000,"Lithuanian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010427","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5088"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042a","Layout File",0x00000000,"kbdvntc.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042a","Layout Text",0x00000000,"Vietnamese"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5118"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042b","Layout File",0x00000000,"kbdarme.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042b","Layout Text",0x00000000,"Armenian Eastern"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042b","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5120"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001042b","Layout File",0x00000000,"kbdarmw.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001042b","Layout Text",0x00000000,"Armenian Western"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0001042b","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5121"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042c","Layout File",0x00000000,"kbdazel.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042c","Layout Text",0x00000000,"Azeri Latin"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5117"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000082c","Layout File",0x00000000,"kbdaze.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000082c","Layout Text",0x00000000,"Azeri Cyrillic"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000082c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5115"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042f","Layout File",0x00000000,"kbdmac.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042f","Layout Text",0x00000000,"Macedonian (FYRO)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000042f","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5109"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000437","Layout File",0x00000000,"kbdgeo.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000437","Layout Text",0x00000000,"Georgian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000437","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5119"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000439","Layout File",0x00000000,"kbdindev.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000439","Layout Text",0x00000000,"Devanagari - INSCRIPT"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000439","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5096"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000043f","Layout File",0x00000000,"kbdkaz.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000043f","Layout Text",0x00000000,"Kazakh"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000043f","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5113"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000843","Layout File",0x00000000,"kbduzb.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000843","Layout Text",0x00000000,"Uzbek (Cyrillic)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000843","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5114"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000444","Layout File",0x00000000,"kbdtat.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000444","Layout Text",0x00000000,"Tatar"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000444","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5116"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000445","Layout File",0x00000000,"kbdinben.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000445","Layout Text",0x00000000,"Bengali"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000445","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5135"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000447","Layout File",0x00000000,"kbdinguj.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000447","Layout Text",0x00000000,"Gujarati"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000447","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5097"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044c","Layout File",0x00000000,"kbdinmal.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044c","Layout Text",0x00000000,"Malayalam"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5139"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044d","Layout File",0x00000000,"kbdinasa.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044d","Layout Text",0x00000000,"ASSAMESE - INSCRIPT"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000044d","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5177"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000455","Layout File",0x00000000,"kbdbur.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000455","Layout Text",0x00000000,"Burmese"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000455","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5140"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000414","Layout File",0x00000000,"kbdno.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000414","Layout Text",0x00000000,"Norwegian"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000414","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5018"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000405","Layout File",0x00000000,"kbdcz.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000405","Layout Text",0x00000000,"Czech"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000405","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5031"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010405","Layout File",0x00000000,"kbdcz1.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010405","Layout Text",0x00000000,"Czech (QWERTY)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010405","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5032"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00011009","Layout File",0x00000000,"kbdcan.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00011009","Layout Id", 0x00000000,"0020"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00011009","Layout Text",0x00000000,"Canadian Multilingual Standard"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00011009","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5110"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c0c","Layout File",0x00000000,"kbdfc.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c0c","Layout Text",0x00000000,"Canadian French (Legacy)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c0c","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5005"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c1a","Layout File",0x00000000,"kbdycc.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c1a","Layout Text",0x00000000,"Serbian (Cyrillic)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000c1a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5057"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000081a","Layout File",0x00000000,"kbdycl.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000081a","Layout Text",0x00000000,"Serbian (Latin)"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\0000081a","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5038"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout File",0x00000000,"kbdko.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout Text",0x00000000,"Korean"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000412","Layout Display Name",0x00000000,"@%SystemRoot%\system32\input.dll,-5063"
+
+; Keyboard layouts
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000402",2,"bg"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000404",2,"ch"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000405",2,"cz"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000406",2,"dk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000407",2,"gr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000408",2,"gk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000409",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000040A",2,"sp"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000040B",2,"su"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000040C",2,"fr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000040E",2,"hu"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000040F",2,"is"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000410",2,"it"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000411",2,"jp"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000412",2,"ko"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000413",2,"nl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000414",2,"no"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000415",2,"pl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000416",2,"br"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000418",2,"ro"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000419",2,"ru"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000041A",2,"yu"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000041B",2,"sl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000041C",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000041D",2,"sv"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000041F",2,"tr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000422",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000423",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000424",2,"yu"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000425",2,"et"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000426",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000427",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000804",2,"ch"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000807",2,"sg"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000809",2,"uk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000080A",2,"la"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000080C",2,"be"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000813",2,"be"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000816",2,"po"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000C0C",2,"cf"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00000C1A",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00001009",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0000100C",2,"sf"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00001809",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010402",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010405",2,"cz"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010407",2,"gr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010408",2,"gk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010409",2,"dv"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0001040A",2,"sp"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0001040E",2,"hu"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010410",2,"it"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010415",2,"pl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010419",2,"ru"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0001041B",2,"sl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","0001041F",2,"tr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010426",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010C0C",2,"cf"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00010C1A",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00020408",2,"gk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00020409",2,"us"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00030409",2,"usl"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00040409",2,"usr"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes","00050408",2,"gk"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","00000410",2,"141"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","0000041F",2,"179"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","00010408",2,"220"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","00010410",2,"142"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","00010415",2,"214"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","0001041F",2,"440"
+HKLM,"SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybIDs","00020408",2,"319"
+
+; Network
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Adapters"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"Net"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E973-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Client"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E973-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetClient"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E974-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Service"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E974-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetService"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}",,0x00000000,"Network Protocol"
+HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}","Class",0x00000000,"NetTrans"
+HKLM,"SYSTEM\CurrentControlSet\Control\NetworkProvider\Order","ProviderOrder",0x00000000,""
+
+; NLS Files
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","37",0x00000000,"c_037.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","424",0x00000000,"c_424.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","437",0x00000000,"c_437.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","500",0x00000000,"c_500.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","737",0x00000000,"c_737.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","775",0x00000000,"c_775.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","850",0x00000000,"c_850.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","852",0x00000000,"c_852.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","855",0x00000000,"c_855.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","856",0x00000000,"c_856.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","857",0x00000000,"c_857.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","860",0x00000000,"c_860.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","861",0x00000000,"c_861.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","862",0x00000000,"c_862.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","863",0x00000000,"c_863.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","864",0x00000000,"c_864.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","865",0x00000000,"c_865.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","866",0x00000000,"c_866.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","869",0x00000000,"c_869.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","874",0x00000000,"c_874.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","875",0x00000000,"c_875.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","878",0x00000000,"c_878.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","932",0x00000000,"c_932.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","936",0x00000000,"c_936.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","949",0x00000000,"c_949.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","950",0x00000000,"c_950.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1006",0x00000000,"c_1006.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1026",0x00000000,"c_1026.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1250",0x00000000,"c_1250.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1251",0x00000000,"c_1251.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1252",0x00000000,"c_1252.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1253",0x00000000,"c_1253.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1254",0x00000000,"c_1254.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1255",0x00000000,"c_1255.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1256",0x00000000,"c_1256.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1257",0x00000000,"c_1257.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1258",0x00000000,"c_1258.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10000",0x00000000,"c_10000.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10006",0x00000000,"c_10006.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10007",0x00000000,"c_10007.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10029",0x00000000,"c_10029.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10079",0x00000000,"c_10079.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10081",0x00000000,"c_10081.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","20866",0x00000000,"c_20866.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","21866",0x00000000,"c_21866.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28591",0x00000000,"c_28591.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28592",0x00000000,"c_28592.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28593",0x00000000,"c_28593.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28594",0x00000000,"c_28594.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28595",0x00000000,"c_28595.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28596",0x00000000,"c_28596.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28597",0x00000000,"c_28597.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28598",0x00000000,"c_28598.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28599",0x00000000,"c_28599.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28600",0x00000000,"c_28600.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28603",0x00000000,"c_28603.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28604",0x00000000,"c_28604.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28605",0x00000000,"c_28605.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28606",0x00000000,"c_28606.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","ACP",0x00000000,"1252"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","OEMCP",0x00000000,"437"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","MACCP",0x00000000,"10000"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","932",2,"F040-F9FC"
+HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","936",2,"AAA1-AFFE,F8A1-FEFE,A140-A7A0"
+HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","949",2,"C9A1-C9FE,FEA1-FEFE"
+HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","950",2,"FA40-FEFE,8E40-A0FE,8140-8DFE,C6A1-C8FE"
+HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","Unicode",2,"E000-F8FF"
+
+; NLS Language settings
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0402",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0403",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0404",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0804",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c04",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1004",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1404",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0405",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0406",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0407",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0807",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c07",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1407",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0408",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0409",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0809",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c09",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1009",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1409",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1809",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c09",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2009",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3009",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3409",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100a",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c0a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","200a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","240a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","280a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2c0a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","300a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","340a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","380a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3c0a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","400a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","440a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","480a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","4c0a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","500a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040b",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040d",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040e",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040f",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0410",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0810",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0411",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0412",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0413",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0813",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0814",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0415",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0416",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0816",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0417",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0418",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0419",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c1a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041b",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041d",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081d",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041e",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041f",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0420",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0421",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0422",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0423",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0424",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0425",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0426",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0427",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0429",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042a",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042b",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042c",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","082c",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042d",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042f",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0436",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0437",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0438",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0439",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043e",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","083e",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043f",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0440",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0441",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0443",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0843",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0445",0x00000000,"l_intl.nls"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0455",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0456",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","048f",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0490",0x00000000,"l_intl.nls"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","Default",0x00000000,"0409"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","InstallLanguage",0x00000000,"0409"
+
+; Supported and installed locales
+; If you add/uncomment an entry here, please also add the appropriate Language
+; in the previous section.
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000402",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000403",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000404",0x00000000,"9"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000804",0x00000000,"a"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000405",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000406",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000407",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000807",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c07",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001407",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000408",0x00000000,"4"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000409",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000809",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c09",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001009",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001409",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001809",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c09",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002009",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003009",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003409",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100a",0x00000000,"1"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c0a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000200a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000240a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000280a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002c0a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000300a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000340a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000380a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003c0a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000400a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000440a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000480a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00004c0a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000500a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040b",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040d",0x00000000,"c"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040e",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040f",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000410",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000810",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000411",0x00000000,"7"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000412",0x00000000,"8"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000413",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000813",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000414",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000814",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000415",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000416",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000816",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000417",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000418",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000419",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041a",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c1a",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041b",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041c",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041d",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081d",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041e",0x00000000,"b"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041f",0x00000000,"6"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000420",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000421",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000422",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000423",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000424",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000425",0x00000000,"3"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000426",0x00000000,"3"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000427",0x00000000,"3"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000429",0x00000000,""
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042a",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042b",0x00000000,"11"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042c",0x00000000,"6"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000082c",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042d",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042f",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000436",0x00000000,"1"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000437",0x00000000,"10"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000438",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000439",0x00000000,"f"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043e",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000083e",0x00000000,"1"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043f",0x00000000,"5"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000440",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000441",0x00000000,"1"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000443",0x00000000,"6"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000843",0x00000000,"5"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000445",0x00000000,"f"
+;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000455",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000456",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000048f",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000490",0x00000000,"1"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","1",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","2",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","3",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","4",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","5",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","6",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","7",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","8",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","9",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","10",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","11",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","a",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","b",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","c",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","d",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","e",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","f",0x00000000,"1"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010407",0x00000000,"1"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","0001040e",0x00000000,"2"
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010437",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00020804",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021004",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021404",0x00000000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00030404",0x00000000,""
+
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82441FX",0x00030003,\
+01,00,00,00,86,80,37,12,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82439HX",0x00030003,\
+01,00,00,00,86,80,50,12,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82439TX",0x00030003,\
+01,00,00,00,86,80,00,71,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82443LX/EX",0x00030003,\
+01,00,00,00,86,80,80,71,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82443BX1",0x00030003,\
+01,00,00,00,86,80,90,71,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82443BX2",0x00030003,\
+01,00,00,00,86,80,92,71,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82443GX",0x00030003,\
+01,00,00,00,86,80,a0,71,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","VIA Tech1",0x00030003,\
+01,00,00,00,06,11,01,05,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","VIA Tech2",0x00030003,\
+01,00,00,00,06,11,91,06,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Toshiba",0x00030003,\
+01,00,00,00,79,11,01,06,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Ali",0x00030003,\
+01,00,00,00,b9,10,21,15,00,00,00,00,00,00,00,00
+
+HKLM,"SYSTEM\CurrentControlSet\Control\Print","MajorVersion",0x00010001,2
+HKLM,"SYSTEM\CurrentControlSet\Control\Print","MinorVersion",0x00010003,0
+HKLM,"SYSTEM\CurrentControlSet\Control\Print","PriorityClass",0x00010003,0
+HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors",,0x00000012
+HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port","Driver",2,"localspl.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers",,0x00000012
+
+HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"WinNT"
+HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,""
+
+HKLM,"SYSTEM\CurrentControlSet\Control\SecurityProviders","SecurityProviders",2,"schannel.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\SecurityProviders\SaslProfiles",,0x00000012
+
+; Some installers check for SP6
+HKLM,"SYSTEM\CurrentControlSet\Control\Windows","CSDVersion",0x00010001,0x00000600
+
+; Service groups
+HKLM,"SYSTEM\CurrentControlSet\Control\ServiceGroupOrder","List",0x00010000, \
+ "Boot Bus Extender", \
+ "System Bus Extender", \
+ "SCSI Port", \
+ "SCSI Miniport", \
+ "Primary Disk", \
+ "SCSI Class Helper", \
+ "SCSI Class", \
+ "Boot File System", \
+ "Base", \
+ "Pointer Port", \
+ "Keyboard Port", \
+ "Pointer Class", \
+ "Keyboard Class", \
+ "Debug", \
+ "Video Init", \
+ "Video", \
+ "Video Save", \
+ "File System", \
+ "Event log", \
+ "COM Infrastructure", \
+ "NDIS", \
+ "PNP_TDI", \
+ "TDI", \
+ "PlugPlay", \
+ "SpoolerGroup", \
+ "Extended Base"
+
+; Set the timeout for directx/ReactX graphic surface lock see _EDD_DIRECTDRAW_GLOBAL struct for more info
+HKLM,"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\DCI","Timeout",0x00010001,0x00000007
+HKLM,"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\UseNewKey",,0x00000012
+
+; Group order, the first DWORD is the count of entries,
+; the following dwords are the tag entries for the load order.
+HKLM,"SYSTEM\CurrentControlSet\Control\GroupOrderList","Video Save", 0x00000001, \
+ 0x02, 0x00, 0x00, 0x00, \
+ 0x01, 0x00, 0x00, 0x00, \
+ 0x02, 0x00, 0x00, 0x00
+HKLM,"SYSTEM\CurrentControlSet\Control\GroupOrderList","SCSI Miniport", 0x00000001, \
+ 0x02, 0x00, 0x00, 0x00, \
+ 0x10, 0x00, 0x00, 0x00, \
+ 0x20, 0x00, 0x00, 0x00
+
+; Session Manager stuff
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager","BootExecute", 0x00010000, \
+ "autocheck autochk *"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager","ObjectDirectories",0x00010000, \
+ "\Windows", \
+ "\RPC Control"
+
+; DOS devices
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","AUX",0x00000000,"\DosDevices\COM1"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","MAILSLOT",0x00000000,"\Device\MailSlot"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","NUL",0x00000000,"\Device\Null"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","PIPE",0x00000000,"\Device\NamedPipe"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","PRN",0x00000000,"\DosDevices\LPT1"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices","UNC",0x00000000,"\Device\Mup"
+
+; System environment settings
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","ComSpec",0x00020000,"%SystemRoot%\system32\cmd.exe"
- HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","PATHEXT",0x00020000,".COM;.EXE;.BAT;.CMD"
- HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","PROCESSOR_ARCHITECTURE",0x00020000,"x86"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","Path",0x00020000,"%SystemRoot%\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\system32\wbem"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","windir",0x00020000,"%SystemRoot%"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","TEMP",0x00020000,"%SystemDrive%\TEMP"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","TMP",0x00020000,"%SystemDrive%\TEMP"
- HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ErrorControl",0x00010001,0x00000000
- HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Group",0x00000000,"Network"
- HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ImagePath",0x00020000,"%SystemRoot%\system32\dhcp.exe"
++HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","PATHEXT",0x00000000,".COM;.EXE;.BAT;.CMD"
+
+
+; Known DLLs
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","DllDirectory",0x00020000,"%SystemRoot%\system32"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","advapi32",0x00000000,"advapi32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","comdlg32",0x00000000,"comdlg32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","gdi32",0x00000000,"gdi32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","imagehlp",0x00000000,"imagehlp.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","kernel32",0x00000000,"kernel32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","lz32",0x00000000,"lz32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","ole32",0x00000000,"ole32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","oleaut32",0x00000000,"oleaut32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olecli32",0x00000000,"olecli32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olesvr32",0x00000000,"olesvr32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","olethk32",0x00000000,"olethk32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","rpcrt4",0x00000000,"rpcrt4.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","shell32",0x00000000,"shell32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","url",0x00000000,"url.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","urlmon",0x00000000,"urlmon.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","user32",0x00000000,"user32.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","version",0x00000000,"version.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","wininet",0x00000000,"wininet.dll"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\KnownDlls","wldap32",0x00000000,"wldap32.dll"
+
+; Pagefile settings
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management","PagingFiles",0x00010000, \
+ "C:\pagefile.sys"
+
+; Subsystems
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Debug",0x00020000,""
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Kmode",0x00020000,"%SystemRoot%\system32\win32k.sys"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Optional",0x00010000,"Posix","Os2","Vms"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Os2",0x00020000,"%SystemRoot%\system32\csr.exe ObjectDirectory=\OS2 SharedSection=128 Windows=Off SubSystemType=Text ServerDll=os2srv,1 ProfileControl=Off RequestThreads=2 MaxRequestThreads=2 Sessions=Off"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Posix",0x00020000,"%SystemRoot%\system32\csr.exe ObjectDirectory=\POSIX SharedSection=128 Windows=Off SubSystemType=Text ServerDll=psxsrv,1 ProfileControl=Off RequestThreads=2 MaxRequestThreads=2 Sessions=Off"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Required",0x00010000,"Debug","Windows"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Vms",0x00020000,"%SystemRoot%\system32\csr.exe ObjectDirectory=\VMS SharedSection=128 Windows=Off SubSystemType=Text ServerDll=vmssrv,1 ProfileControl=Off RequestThreads=2 MaxRequestThreads=2 Sessions=Off"
+HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Windows",0x00020000,"%SystemRoot%\system32\csrss.exe"
+
+; WOW Support
+HKLM,"SYSTEM\CurrentControlSet\Control\Wow","",0x00000000,""
+
+; PNP Root device
+HKLM,"SYSTEM\CurrentControlSet\Enum\HTREE\ROOT\0","",0x00000000,""
+
+; Afd driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Afd","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Afd","Group",0x00000000,"TDI"
+HKLM,"SYSTEM\CurrentControlSet\Services\Afd","ImagePath",0x00020000,"system32\drivers\afd.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Afd","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Afd","Type",0x00010001,0x00000001
+
+; UniATA/Atapi miniport driver
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","Group",0x00000000,"System Bus Extender"
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","ImagePath",0x00020000,"system32\drivers\uniata.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\UniATA","Tag",0x00010001,0x00000010
+
+; Audio Service
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","DisplayName",0x00000000,"Audio Service"
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","Description",0x00000000,"Provides audio facilities to applications"
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","Group",0x00000000,"Audio"
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","ImagePath",0x00020000,"%SystemRoot%\system32\audiosrv.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","Start",0x00010001,0x00000003
+HKLM,"SYSTEM\CurrentControlSet\Services\RosAudioSrv","Type",0x00010001,0x00000010
+
+; BusLogic 958 miniport driver
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Group",0x00000000,"SCSI Miniport"
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","ImagePath",0x00020000,"system32\drivers\buslogic.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Tag",0x00010001,0x00000020
+
+; Beep device driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Beep","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Beep","Group",0x00000000,"Base"
+HKLM,"SYSTEM\CurrentControlSet\Services\Beep","ImagePath",0x00020000,"system32\drivers\beep.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Beep","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Beep","Type",0x00010001,0x00000001
+
+; BlueScreen device driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Group",0x00000000,"Video Init"
+HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ImagePath",0x00020000,"system32\drivers\blue.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Type",0x00010001,0x00000001
+
+; Cdfs (ISO96660) filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Group",0x00000000,"File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","ImagePath",0x00020000,"system32\drivers\cdfs.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdfs","Type",0x00010001,0x00000002
+
+; Cdrom class driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Group",0x00000000,"SCSI Class"
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","ImagePath",0x00020000,"system32\drivers\cdrom.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Type",0x00010001,0x00000001
+
+; Class2 driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Class2","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Class2","Group",0x00000000,"SCSI Class Helper"
+HKLM,"SYSTEM\CurrentControlSet\Services\Class2","ImagePath",0x00020000,"system32\drivers\class2.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Class2","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Class2","Type",0x00010001,0x00000001
+
+; Debug output driver
+HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Group",0x00000000,"Debug"
+HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","ImagePath",0x00020000,"system32\drivers\debugout.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Type",0x00010001,0x00000001
+
+; Disk class driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Disk","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Group",0x00000000,"SCSI Class"
+HKLM,"SYSTEM\CurrentControlSet\Services\Disk","ImagePath",0x00020000,"system32\drivers\disk.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Type",0x00010001,0x00000001
+
+; DHCP client service
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","DisplayName",0x00000000,"DHCP Client"
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Description",0x00000000,"Attempts to obtain network settings automatically from an available DHCP server"
- HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000010
++HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ErrorControl",0x00010001,0x00000001
++HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Group",0x00000000,"TDI"
++HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ImagePath",0x00020000,"%SystemRoot%\system32\svchost.exe -k netsvcs"
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Start",0x00010001,0x00000002
++HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000020
++HKLM,"SYSTEM\CurrentControlSet\Services\DHCP\Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dhcpcsvc.dll"
+
+; Event logging service
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog",,0x00000010
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","DisplayName",0x00000000,"Event Logger"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Description",0x00000000,"Logs events or messages sent by the operating system in a database accessible via the event log viewer"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Group",0x00000000,"Event log"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ImagePath",0x00020000,"%SystemRoot%\system32\eventlog.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Start",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Type",0x00010001,0x00000010
+
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\Application",,0x00000010
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\Application","File",0x00020000,"%SystemRoot%\system32\config\AppEvent.Evt"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\Security",,0x00000010
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\Security","File",0x00020000,"%SystemRoot%\system32\config\SecEvent.Evt"
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\System",,0x00000010
+HKLM,"SYSTEM\CurrentControlSet\Services\EventLog\System","File",0x00020000,"%SystemRoot%\system32\config\SysEvent.Evt"
+
+; Floppy driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Group",0x00000000,"Primary Disk"
+HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","ImagePath",0x00020000,"system32\drivers\floppy.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Type",0x00010001,0x00000001
+
+; Filesystem recognizer driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Group",0x00000000,"Boot file system"
+HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","ImagePath",0x00020000,"system32\drivers\fs_rec.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Type",0x00010001,0x00000008
+
+; Kernel-Mode Tests
+;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","ErrorControl",0x00010001,0x00000000
+;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Group",0x00000000,"Base"
+;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","ImagePath",0x00020000,"system32\drivers\kmtest.sys"
+;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Start",0x00010001,0x00000001
+;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Type",0x00010001,0x00000001
+
+; Keyboard class driver
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Group",0x00000000,"Keyboard Class"
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ImagePath",0x00020000,"system32\drivers\kbdclass.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass\Parameters","ConnectMultiplePorts",0x00010001,1
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"kbdclass"
+
+; MPU-401 MIDI driver
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Group",0x00000000,"Base"
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ServiceType",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys"
+
+; Mouse class driver
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Group",0x00000000,"Pointer Class"
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ImagePath",0x00020000,"system32\drivers\mouclass.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass"
+
+; Mailslot filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","Group",0x00000000,"File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","ImagePath",0x00020000,"system32\drivers\msfs.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","Type",0x00010001,0x00000002
+
+; NDIS driver - the only boot-start network driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Group",0x00000000,"NDIS"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","ImagePath",0x00020000,"system32\drivers\ndis.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Type",0x00010001,0x00000001
+
+; NetLogon
+;HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","DisplayName",0x00000000,"Net Logon"
+;HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","Description",0x00000000,"Sets up a secure channel to a domain controller for domain authentication"
+;HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","ErrorControl",0x00010001,0x00000001
+;HKLM,"SYSTEM\CurrentControlSet\Services\Netlogon","ImagePath",0x00020000,"%SystemRoot%\system32\lsass.exe"
+;HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","Start",0x00010001,0x00000003
+;HKLM,"SYSTEM\CurrentControlSet\Services\Netlogon","Type",0x00010001,0x00000020
+
+; Named Pipe filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","Group",0x00000000,"File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","ImagePath",0x00020000,"system32\drivers\npfs.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","Type",0x00010001,0x00000002
+
+; NTFS filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Ntfs","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Ntfs","Group",0x00000000,"File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ntfs","ImagePath",0x00020000,"system32\drivers\ntfs.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ntfs","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Ntfs","Type",0x00010001,0x00000002
+
+; Null device driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Null","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Null","Group",0x00000000,"Base"
+HKLM,"SYSTEM\CurrentControlSet\Services\Null","ImagePath",0x00020000,"system32\drivers\null.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Null","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Null","Type",0x00010001,0x00000001
+
+; NMI device driver
+HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Group",0x00000000,"Base"
+HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","ImagePath",0x00020000,"system32\drivers\nmidebug.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Type",0x00010001,0x00000001
+
+; Packet driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Group",0x00000000,"PNP_TDI"
+HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ImagePath",0x00020000,"system32\drivers\packet.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Type",0x00010001,0x00000001
+
+; Plug and Play manager
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","DisplayName",0x00000000,"Plug and Play"
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Description",0x00000000,"Detects hardware changes and installs needed software if possible"
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Group",0x00000000,"PlugPlay"
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ImagePath",0x00020000,"%SystemRoot%\system32\umpnpmgr.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Type",0x00010001,0x00000010
+
+; RPC service
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","DisplayName",0x00000000,"Remote Procedure Call"
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Description",0x00000000,"RPC subsystem which is responsible for Remote procedure Calls on the local machine"
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Group",0x00000000,"COM Infrastructure"
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ImagePath",0x00020000,"%SystemRoot%\system32\rpcss.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Start",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Type",0x00010001,0x00000010
+
+; Scsiport driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Scsiport","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Scsiport","Group",0x00000000,"SCSI Port"
+HKLM,"SYSTEM\CurrentControlSet\Services\Scsiport","ImagePath",0x00020000,"system32\drivers\scsiport.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Scsiport","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Scsiport","Type",0x00010001,0x00000001
+
+; Spooler service
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","DependOnService",0x00010000,"RPCSS"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","DisplayName",0x00000000,"Printer Spooler"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","Description",0x00000000,"Printer Spooler"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","Group",0x00000000,"SpoolerGroup"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","ImagePath",0x00020000,"%SystemRoot%\system32\spoolsv.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","Start",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\Spooler","Type",0x00010001,0x00000110
+
+; WLAN service
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","DependOnService",0x00010000,"RPCSS"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","DisplayName",0x00000000,"WLAN Service"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Description",0x00000000,"WLAN Service"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Group",0x00000000,"TDI"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ImagePath",0x00020000,"%SystemRoot%\system32\wlansvc.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Start",0x00010001,0x00000003
+HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Type",0x00010001,0x00000110
+
+; Simple TCP services
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Description",0x00000000,"Supports the following TCP/IP services: Chargen, Daytime, Discard, Echo, QOTD"
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","DisplayName",0x00000000,"Simple TCP/IP Services"
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Group",0x00000000,"Network"
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","ImagePath",0x00020000,"%SystemRoot%\system32\tcpsvcs.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Start",0x00010001,0x00000003
+HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Type",0x00010001,0x00000020
+
+; ReactOS Telnet Daemon
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Description",0x00000000,"ReactOS Telnet Daemon"
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","DisplayName",0x00000000,"ReactOS Telnet Daemon"
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Group",0x00000000,"Network"
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ImagePath",0x00020000,"%SystemRoot%\system32\telnetd.exe"
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Start",0x00010001,0x00000003
+HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Type",0x00010001,0x00000020
+
+; Sound Blaster (NT4)
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Description",0x00000000,"Sound Blaster (NT4)"
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ErrorControl",0x00010001,0x00000001
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base"
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ImagePath",0x00020000,"system32\drivers\sndblst.sys"
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Start",0x00010001,0x00000003
+;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Type",0x00010001,0x00000001
+
+; Virtual FAT filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\fastfat","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\fastfat","Group",0x00000000,"Boot File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\fastfat","ImagePath",0x00020000,"system32\drivers\fastfat.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\fastfat","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\fastfat","Type",0x00010001,0x00000002
+
+; RAM Disk class driver
+HKLM,"SYSTEM\CurrentControlSet\Services\RamDisk","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\RamDisk","Group",0x00000000,"Boot File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\RamDisk","ImagePath",0x00020000,"system32\drivers\ramdisk.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\RamDisk","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\RamDisk","Type",0x00010001,0x00000002
+
+; EXT2 Filesystem driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Ext2fs","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Ext2fs","Group",0x00000000,"Boot File System"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ext2fs","ImagePath",0x00020000,"system32\drivers\ext2.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Ext2fs","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Ext2fs","Type",0x00010001,0x00000002
+
+; VBE SVGA driver
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Group",0x00000000,"Video Save"
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","ImagePath",0x00020000,"system32\drivers\vbemp.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Tag",0x00010001,0x00000001
+
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","InstalledDisplayDrivers",0x00010000,"framebuf"
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.VRefresh",0x00010001,1
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.BitsPerPel",0x00010001,8
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.XResolution",0x00010001,640
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.YResolution",0x00010001,480
+
+; VGA miniport driver
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Group",0x00000000,"Video Save"
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","ImagePath",0x00020000,"system32\drivers\vgamp.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Start",0x00010001,0x00000004
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Tag",0x00010001,0x00000002
+
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","InstalledDisplayDrivers",0x00010000,"vgaddi"
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.VRefresh",0x00010001,1
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.BitsPerPel",0x00010001,8
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.XResolution",0x00010001,640
+HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.YResolution",0x00010001,480
+
+; USB uhci/ehci driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbdriver","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\usbdriver","Group",0x00000000,"Base"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbdriver","ImagePath",0x00020000,"system32\drivers\usbdriver.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbdriver","Start",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbdriver","Type",0x00010001,0x00000001
+
+; USB storage driver
+;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ErrorControl",0x00010001,0x00000000
+;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Group",0x00000000,"Extended Base"
+;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ImagePath",0x00020000,"system32\drivers\usbstor.sys"
+;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Start",0x00010001,0x00000003
+;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Type",0x00010001,0x00000001
+
+; Windows Installer Service
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","DisplayName",0x00000000,"ReactOS Installer"
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Description",0x00000000,"Controls installation, maintenance, and removal of software packaged as an msi (Windows Installer)"
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Group",0x00000000,"Windows Installer"
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","ImagePath",0x00020000,"system32\msiexec.exe /V"
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Start",0x00010001,0x00000003
+HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Type",0x00010001,0x00000020
+
+; ControlSet selection settings
+HKLM,"SYSTEM\Select","Current",0x00010001,0x00000001
+HKLM,"SYSTEM\Select","Default",0x00010001,0x00000001
+HKLM,"SYSTEM\Select","Failed",0x00010001,0x00000000
+HKLM,"SYSTEM\Select","LastKnownGood",0x00010001,0x00000000
+
+; System setup settings
+HKLM,"SYSTEM\Setup","CmdLine",0x00000000,"setup -newsetup"
+HKLM,"SYSTEM\Setup","OsLoaderPath",0x00000000,"\"
+HKLM,"SYSTEM\Setup","SetupType",0x00010001,0x00000001
+HKLM,"SYSTEM\Setup","SystemPartition",0x00000000,"\Device\Harddisk0\Partition1"
+HKLM,"SYSTEM\Setup","SystemSetupInProgress",0x00010001,0x00000001
+
+; Debug channels
+;HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Environment","DEBUGCHANNEL",0x00020000,"+ole,+rpc"
+
+; EOF
--- /dev/null
- base\services\dhcp\dhcp.exe 1
+; Main ReactOS package
+
+.Set DiskLabelTemplate="ReactOS" ; Label of disk
+.Set CabinetNameTemplate="reactos.cab" ; reactos.cab
+.Set InfFileName="reactos.inf" ; reactos.inf
+
+
+;.Set Cabinet=on
+;.Set Compress=on
+
+.InfBegin
+[Version]
+Signature = "$ReactOS$"
+
+[Directories]
+1 = system32
+2 = system32\drivers
+3 = Fonts
+4 =
+5 = system32\drivers\etc
+6 = inf
+7 = bin
+8 = media
+
+.InfEnd
+
+; Contents of disk
+.InfBegin
+[SourceFiles]
+.InfEnd
+
+
+; Base files
+base\applications\cacls\cacls.exe 1
+base\applications\calc\calc.exe 1
+base\applications\charmap\charmap.exe 1
+base\applications\cmdutils\dbgprint\dbgprint.exe 1
+base\applications\cmdutils\doskey\doskey.exe 1
+base\applications\cmdutils\find\find.exe 1
+base\applications\cmdutils\hostname\hostname.exe 1
+base\applications\cmdutils\lodctr\lodctr.exe 1
+base\applications\cmdutils\more\more.exe 1
+base\applications\cmdutils\reg\reg.exe 1
+base\applications\cmdutils\xcopy\xcopy.exe 1
+base\applications\control\control.exe 1
+base\applications\dxdiag\dxdiag.exe 1
+base\applications\fontview\fontview.exe 1
+base\applications\mscutils\devmgmt\devmgmt.exe 1
+base\applications\mscutils\eventvwr\eventvwr.exe 1
+base\applications\games\solitaire\sol.exe 1
+base\applications\games\spider\spider.exe 1
+base\applications\games\winemine\winemine.exe 1
+base\applications\hh\hh.exe 4
+base\applications\kbswitch\kbswitch.exe 1
+base\applications\kbswitch\kbsdll\kbsdll.dll 1
+base\applications\logoff\logoff.exe 1
+base\applications\magnify\magnify.exe 1
+base\applications\mplay32\mplay32.exe 1
+base\applications\msconfig\msconfig.exe 1
+base\applications\mstsc\mstsc.exe 1
+base\applications\network\arp\arp.exe 1
+base\applications\network\dwnl\dwnl.exe 1
+base\applications\network\route\route.exe 1
+base\applications\network\finger\finger.exe 1
+base\applications\network\ftp\ftp.exe 1
+base\applications\network\ipconfig\ipconfig.exe 1
+base\applications\network\netstat\netstat.exe 1
+base\applications\network\nslookup\nslookup.exe 1
+base\applications\network\ping\ping.exe 1
+base\applications\network\telnet\telnet.exe 1
+base\applications\network\tracert\tracert.exe 1
+base\applications\network\whois\whois.exe 1
+base\applications\notepad\notepad.exe 1
+base\applications\paint\paint.exe 1
+base\applications\rapps\rapps.exe 1
+base\applications\regedit\regedit.exe 4
+base\applications\regedit\clb\clb.dll 1
+base\applications\regedt32\regedt32.exe 1
+base\applications\sc\sc.exe 1
+base\applications\screensavers\3dtext\3dtext.scr 1
+base\applications\screensavers\logon\logon.scr 1
+base\applications\mscutils\servman\servman.exe 1
+base\applications\shutdown\shutdown.exe 1
+base\applications\sndrec32\sndrec32.exe 1
+base\applications\sndvol32\sndvol32.exe 1
+base\applications\taskmgr\taskmgr.exe 1
+base\applications\winhlp32\winhlp32.exe 4
+base\applications\winver\winver.exe 1
+base\applications\wordpad\wordpad.exe 1
+base\applications\write\write.exe 1
+
+base\services\audiosrv\audiosrv.exe 1
+base\services\eventlog\eventlog.exe 1
+base\services\rpcss\rpcss.exe 1
+base\services\spoolsv\spoolsv.exe 1
+base\services\tcpsvcs\tcpsvcs.exe 1
+base\services\telnetd\telnetd.exe 1
+base\services\tcpsvcs\quotes 5
+base\services\umpnpmgr\umpnpmgr.exe 1
+base\services\wlansvc\wlansvc.exe 1
+base\services\svchost\svchost.exe 1
+
+base\setup\setup\setup.exe 1
+base\setup\vmwinst\vmwinst.exe 1
+
+base\shell\cmd\cmd.exe 1
+base\shell\explorer\explorer.exe 4
+base\shell\explorer\explorer-cfg-template.xml 4
+base\shell\explorer\notifyhook\notifyhook.dll 1
+base\shell\explorer-new\explorer_new.exe 4 optional
+
+base\system\autochk\autochk.exe 1
+base\system\bootok\bootok.exe 1
+base\system\format\format.exe 1
+base\system\lsass\lsass.exe 1
+base\system\msiexec\msiexec.exe 1
+base\system\regsvr32\regsvr32.exe 1
+base\system\rundll32\rundll32.exe 1
+base\system\runonce\runonce.exe 1
+base\system\services\services.exe 1
+base\system\userinit\userinit.exe 1
+base\system\winlogon\winlogon.exe 1
+base\system\expand\expand.exe 1
+base\system\smss\smss.exe 1
+
+
+; Dynamic Link Libraries
+dll\3rdparty\mesa32\mesa32.dll 1
+dll\3rdparty\libjpeg\libjpeg.dll 1
+dll\3rdparty\libxslt\libxslt.dll 1
+dll\3rdparty\dxtn\dxtn.dll 1 optional
+
+dll\cpl\access\access.cpl 1
+dll\cpl\appwiz\appwiz.cpl 1
+dll\cpl\console\console.dll 1
+dll\cpl\desk\desk.cpl 1
+dll\cpl\hdwwiz\hdwwiz.cpl 1
+dll\cpl\input\input.dll 1
+dll\cpl\intl\intl.cpl 1
+dll\cpl\joy\joy.cpl 1
+;dll\cpl\liccpa\liccpa.cpl 1
+dll\cpl\main\main.cpl 1
+dll\cpl\mmsys\mmsys.cpl 1
+dll\cpl\ncpa\ncpa.cpl 1
+;dll\cpl\odbccp32\odbccp32.cpl 1
+dll\cpl\powercfg\powercfg.cpl 1
+dll\cpl\sysdm\sysdm.cpl 1
+;dll\cpl\telephon\telephon.cpl 1
+dll\cpl\timedate\timedate.cpl 1
+;dll\cpl\usrmgr\usrmgr.cpl 1
+
+dll\directx\amstream\amstream.dll 1
+dll\directx\bdaplgin\bdaplgin.ax 1
+dll\directx\dinput\dinput.dll 1
+dll\directx\dinput8\dinput8.dll 1
+dll\directx\dmusic\dmusic.dll 1
+dll\directx\dplay\dplay.dll 1
+dll\directx\dplayx\dplayx.dll 1
+dll\directx\dsound\dsound.dll 1
+dll\directx\dxdiagn\dxdiagn.dll 1
+dll\directx\wine\ddraw\ddraw.dll 1
+dll\directx\d3d8thk\d3d8thk.dll 1
+dll\directx\devenum\devenum.dll 1
+dll\directx\ksproxy\ksproxy.ax 1
+dll\directx\ksuser\ksuser.dll 1
+dll\directx\msdmo\msdmo.dll 1
+dll\directx\msdvbnp\msdvbnp.ax 1
+dll\directx\msvidctl\msvidctl.dll 1
+dll\directx\quartz\quartz.dll 1
+dll\directx\qedit\qedit.dll 1
+dll\directx\wine\d3d8\d3d8.dll 1
+dll\directx\wine\wined3d\wined3d.dll 1
+dll\directx\wine\d3d9\d3d9.dll 1
+
+dll\keyboard\kbda1\kbda1.dll 1
+dll\keyboard\kbda2\kbda2.dll 1
+dll\keyboard\kbda3\kbda3.dll 1
+dll\keyboard\kbdal\kbdal.dll 1
+dll\keyboard\kbdarme\kbdarme.dll 1
+dll\keyboard\kbdarmw\kbdarmw.dll 1
+dll\keyboard\kbdaze\kbdaze.dll 1
+dll\keyboard\kbdazel\kbdazel.dll 1
+dll\keyboard\kbdbgm\kbdbgm.dll 1
+dll\keyboard\kbdbgt\kbdbgt.dll 1
+dll\keyboard\kbdblr\kbdblr.dll 1
+dll\keyboard\kbdbr\kbdbr.dll 1
+dll\keyboard\kbdbga\kbdbga.dll 1
+dll\keyboard\kbdbe\kbdbe.dll 1
+dll\keyboard\kbdbur\kbdbur.dll 1
+dll\keyboard\kbdcan\kbdcan.dll 1
+dll\keyboard\kbdcr\kbdcr.dll 1
+dll\keyboard\kbdcz\kbdcz.dll 1
+dll\keyboard\kbdcz1\kbdcz1.dll 1
+dll\keyboard\kbdda\kbdda.dll 1
+dll\keyboard\kbddv\kbddv.dll 1
+dll\keyboard\kbdes\kbdes.dll 1
+dll\keyboard\kbdest\kbdest.dll 1
+dll\keyboard\kbdfc\kbdfc.dll 1
+dll\keyboard\kbdfi\kbdfi.dll 1
+dll\keyboard\kbdfr\kbdfr.dll 1
+dll\keyboard\kbdgeo\kbdgeo.dll 1
+dll\keyboard\kbdgerg\kbdgerg.dll 1
+dll\keyboard\kbdgneo\kbdgneo.dll 1
+dll\keyboard\kbdgrist\kbdgrist.dll 1
+dll\keyboard\kbdgr\kbdgr.dll 1
+dll\keyboard\kbdhe\kbdhe.dll 1
+dll\keyboard\kbdheb\kbdheb.dll 1
+dll\keyboard\kbdhu\kbdhu.dll 1
+dll\keyboard\kbdic\kbdic.dll 1
+dll\keyboard\kbdinasa\kbdinasa.dll 1
+dll\keyboard\kbdinben\kbdinben.dll 1
+dll\keyboard\kbdindev\kbdindev.dll 1
+dll\keyboard\kbdinguj\kbdinguj.dll 1
+dll\keyboard\kbdinmal\kbdinmal.dll 1
+dll\keyboard\kbdir\kbdir.dll 1
+dll\keyboard\kbdit\kbdit.dll 1
+dll\keyboard\kbdja\kbdja.dll 1
+dll\keyboard\kbdkaz\kbdkaz.dll 1
+dll\keyboard\kbdla\kbdla.dll 1
+dll\keyboard\kbdlt1\kbdlt1.dll 1
+dll\keyboard\kbdlv\kbdlv.dll 1
+dll\keyboard\kbdmac\kbdmac.dll 1
+dll\keyboard\kbdne\kbdne.dll 1
+dll\keyboard\kbdno\kbdno.dll 1
+dll\keyboard\kbdpl1\kbdpl1.dll 1
+dll\keyboard\kbdpo\kbdpo.dll 1
+dll\keyboard\kbdro\kbdro.dll 1
+dll\keyboard\kbdru\kbdru.dll 1
+dll\keyboard\kbdru1\kbdru1.dll 1
+dll\keyboard\kbdsg\kbdsg.dll 1
+dll\keyboard\kbdsk\kbdsk.dll 1
+dll\keyboard\kbdsk1\kbdsk1.dll 1
+dll\keyboard\kbdsw\kbdsw.dll 1
+dll\keyboard\kbdtat\kbdtat.dll 1
+dll\keyboard\kbdth0\kbdth0.dll 1
+dll\keyboard\kbdth1\kbdth1.dll 1
+dll\keyboard\kbdth2\kbdth2.dll 1
+dll\keyboard\kbdth3\kbdth3.dll 1
+dll\keyboard\kbdtuf\kbdtuf.dll 1
+dll\keyboard\kbdtuq\kbdtuq.dll 1
+dll\keyboard\kbduk\kbduk.dll 1
+dll\keyboard\kbdur\kbdur.dll 1
+dll\keyboard\kbdurs\kbdurs.dll 1
+dll\keyboard\kbdus\kbdus.dll 1
+dll\keyboard\kbdusa\kbdusa.dll 1
+dll\keyboard\kbdusl\kbdusl.dll 1
+dll\keyboard\kbdusr\kbdusr.dll 1
+dll\keyboard\kbdusx\kbdusx.dll 1
+dll\keyboard\kbduzb\kbduzb.dll 1
+dll\keyboard\kbdvntc\kbdvntc.dll 1
+dll\keyboard\kbdycc\kbdycc.dll 1
+dll\keyboard\kbdycl\kbdycl.dll 1
+dll\keyboard\kbdko\kbdko.dll 1
+
+dll\ntdll\ntdll.dll 1
+
+dll\win32\acledit\acledit.dll 1
+dll\win32\aclui\aclui.dll 1
+dll\win32\activeds\activeds.dll 1
+dll\win32\advapi32\advapi32.dll 1
+dll\win32\advpack\advpack.dll 1
+dll\win32\actxprxy\actxprxy.dll 1
+dll\win32\atl\atl.dll 1
+dll\win32\authz\authz.dll 1
+dll\win32\avicap32\avicap32.dll 1
+dll\win32\avifil32\avifil32.dll 1
+dll\win32\batt\batt.dll 1
+dll\win32\bcrypt\bcrypt.dll 1
+dll\win32\beepmidi\beepmidi.dll 1
+dll\win32\browseui\browseui.dll 1
+dll\win32\cabinet\cabinet.dll 1
+dll\win32\cards\cards.dll 1
+dll\win32\cfgmgr32\cfgmgr32.dll 1
+dll\win32\clusapi\clusapi.dll 1
+dll\win32\comcat\comcat.dll 1
+dll\win32\comctl32\comctl32.dll 1
+dll\win32\comdlg32\comdlg32.dll 1
+dll\win32\compstui\compstui.dll 1
+dll\win32\credui\credui.dll 1
+dll\win32\crtdll\crtdll.dll 1
+dll\win32\crypt32\crypt32.dll 1
+dll\win32\cryptdlg\cryptdlg.dll 1
+dll\win32\cryptdll\cryptdll.dll 1
+dll\win32\cryptnet\cryptnet.dll 1
+dll\win32\cryptui\cryptui.dll 1
+dll\win32\dbghelp\dbghelp.dll 1
+dll\win32\dciman32\dciman32.dll 1
+dll\win32\dwmapi\dwmapi.dll 1
+dll\win32\devmgr\devmgr.dll 1
+dll\win32\dhcpcsvc\dhcpcsvc.dll 1
+dll\win32\dnsapi\dnsapi.dll 1
+dll\win32\faultrep\faultrep.dll 1
+dll\win32\fmifs\fmifs.dll 1
+dll\win32\fusion\fusion.dll 1
+dll\win32\gdi32\gdi32.dll 1
+dll\win32\gdiplus\gdiplus.dll 1
+dll\win32\getuname\getuname.dll 1
+dll\win32\glu32\glu32.dll 1
+dll\win32\hhctrl.ocx\hhctrl.ocx 1
+dll\win32\hid\hid.dll 1
+dll\win32\hlink\hlink.dll 1
+dll\win32\hnetcfg\hnetcfg.dll 1
+dll\win32\httpapi\httpapi.dll 1
+dll\win32\iccvid\iccvid.dll 1
+dll\win32\icmp\icmp.dll 1
+dll\win32\imaadp32.acm\imaadp32.acm 1
+dll\win32\imagehlp\imagehlp.dll 1
+dll\win32\imm32\imm32.dll 1
+dll\win32\inetcomm\inetcomm.dll 1
+dll\win32\inetmib1\inetmib1.dll 1
+dll\win32\initpki\initpki.dll 1
+dll\win32\inseng\inseng.dll 1
+dll\win32\iphlpapi\iphlpapi.dll 1
+dll\win32\itircl\itircl.dll 1
+dll\win32\itss\itss.dll 1
+dll\win32\jscript\jscript.dll 1
+dll\win32\kernel32\kernel32.dll 1
+dll\win32\loadperf\loadperf.dll 1
+dll\win32\localspl\localspl.dll 1
+dll\win32\localui\localui.dll 1
+dll\win32\lsasrv\lsasrv.dll 1
+dll\win32\lz32\lz32.dll 1
+dll\win32\mapi32\mapi32.dll 1
+dll\win32\mciavi32\mciavi32.dll 1
+dll\win32\mcicda\mcicda.dll 1
+dll\win32\mciqtz32\mciqtz32.dll 1
+dll\win32\mciseq\mciseq.dll 1
+dll\win32\mciwave\mciwave.dll 1
+dll\win32\mlang\mlang.dll 1
+dll\win32\mmdrv\mmdrv.dll 1
+dll\win32\modemui\modemui.dll 1
+dll\win32\mpr\mpr.dll 1
+dll\win32\mprapi\mprapi.dll 1
+dll\win32\msacm32\msacm32.dll 1
+dll\win32\msacm32\msacm32.drv\msacm32.drv 1
+dll\win32\msadp32.acm\msadp32.acm 1
+dll\win32\msafd\msafd.dll 1
+dll\win32\mscat32\mscat32.dll 1
+dll\win32\mscms\mscms.dll 1
+dll\win32\mscoree\mscoree.dll 1
+dll\win32\msctf\msctf.dll 1
+dll\win32\msftedit\msftedit.dll 1
+dll\win32\msg711.acm\msg711.acm 1
+dll\win32\msgina\msgina.dll 1
+dll\win32\msgsm32.acm\msgsm32.acm 1
+dll\win32\mshtml\mshtml.dll 1
+dll\win32\mshtml.tlb\mshtml.tlb 1
+dll\win32\msi\msi.dll 1
+dll\win32\msimg32\msimg32.dll 1
+dll\win32\msimtf\msimtf.dll 1
+dll\win32\msisip\msisip.dll 1
+dll\win32\msisys.ocx\msisys.ocx 1
+dll\win32\msnet32\msnet32.dll 1
+dll\win32\msrle32\msrle32.dll 1
+dll\win32\mssign32\mssign32.dll 1
+dll\win32\mssip32\mssip32.dll 1
+dll\win32\mstask\mstask.dll 1
+dll\win32\msvcrt\msvcrt.dll 1
+dll\win32\msvcrt20\msvcrt20.dll 1
+dll\win32\msvcrt40\msvcrt40.dll 1
+dll\win32\msvfw32\msvfw32.dll 1
+dll\win32\msvidc32\msvidc32.dll 1
+dll\win32\mswsock\mswsock.dll 1
+dll\win32\msxml3\msxml3.dll 1
+dll\win32\nddeapi\nddeapi.dll 1
+dll\win32\netapi32\netapi32.dll 1
+dll\win32\netcfgx\netcfgx.dll 1
+dll\win32\netid\netid.dll 1
+dll\win32\netshell\netshell.dll 1
+dll\win32\newdev\newdev.dll 1
+dll\win32\ntdsapi\ntdsapi.dll 1
+dll\win32\ntlanman\ntlanman.dll 1
+dll\win32\ntmarta\ntmarta.dll 1
+dll\win32\ntprint\ntprint.dll 1
+dll\win32\objsel\objsel.dll 1
+dll\win32\odbc32\odbc32.dll 1
+dll\win32\odbccp32\odbccp32.dll 1
+dll\win32\ole32\ole32.dll 1
+dll\win32\oleacc\oleacc.dll 1
+dll\win32\oleaut32\oleaut32.dll 1
+dll\win32\olecli32\olecli32.dll 1
+dll\win32\oledlg\oledlg.dll 1
+dll\win32\olepro32\olepro32.dll 1
+dll\win32\olesvr32\olesvr32.dll 1
+dll\win32\olethk32\olethk32.dll 1
+dll\win32\opengl32\opengl32.dll 1
+dll\win32\pdh\pdh.dll 1
+dll\win32\pidgen\pidgen.dll 1
+dll\win32\powrprof\powrprof.dll 1
+dll\win32\printui\printui.dll 1
+dll\win32\psapi\psapi.dll 1
+dll\win32\pstorec\pstorec.dll 1
+dll\win32\qmgr\qmgr.dll 1
+dll\win32\qmgrprxy\qmgrprxy.dll 1
+dll\win32\query\query.dll 1
+dll\win32\rasadhlp\rasadhlp.dll 1
+dll\win32\rasapi32\rasapi32.dll 1
+dll\win32\rasdlg\rasdlg.dll 1
+dll\win32\resutils\resutils.dll 1
+dll\win32\rasman\rasman.dll 1
+dll\win32\riched20\riched20.dll 1
+dll\win32\riched32\riched32.dll 1
+dll\win32\rpcrt4\rpcrt4.dll 1
+dll\win32\rsabase\rsabase.dll 1
+dll\win32\rsaenh\rsaenh.dll 1
+dll\win32\samlib\samlib.dll 1
+dll\win32\samsrv\samsrv.dll 1
+dll\win32\sccbase\sccbase.dll 1
+dll\win32\schannel\schannel.dll 1
+dll\win32\secur32\secur32.dll 1
+dll\win32\security\security.dll 1
+dll\win32\sensapi\sensapi.dll 1
+dll\win32\serialui\serialui.dll 1
+dll\win32\setupapi\setupapi.dll 1
+dll\win32\sfc\sfc.dll 1
+dll\win32\sfc_os\sfc_os.dll 1
+dll\win32\shdoclc\shdoclc.dll 1
+dll\win32\shdocvw\shdocvw.dll 1
+dll\win32\shell32\shell32.dll 1
+dll\win32\shfolder\shfolder.dll 1
+dll\win32\shimgvw\shimgvw.dll 1
+dll\win32\shlwapi\shlwapi.dll 1
+dll\win32\slbcsp\slbcsp.dll 1
+dll\win32\smdll\smdll.dll 1
+dll\win32\snmpapi\snmpapi.dll 1
+dll\win32\softpub\softpub.dll 1
+dll\win32\spoolss\spoolss.dll 1
+dll\win32\srclient\srclient.dll 1
+dll\win32\stdole2.tlb\stdole2.tlb 1
+dll\win32\stdole32.tlb\stdole32.tlb 1
+dll\win32\sti\sti.dll 1
+dll\win32\sxs\sxs.dll 1
+dll\win32\syssetup\syssetup.dll 1
+dll\win32\t2embed\t2embed.dll 1
+dll\win32\tapi32\tapi32.dll 1
+dll\win32\tapiui\tapiui.dll 1
+dll\win32\traffic\traffic.dll 1
+dll\win32\twain_32\twain_32.dll 1
+dll\win32\uext2\uext2.dll 1
+dll\win32\ufat\ufat.dll 1
+dll\win32\ufatx\ufatx.dll 1 optional
+dll\win32\untfs\untfs.dll 1
+dll\win32\updspapi\updspapi.dll 1
+dll\win32\url\url.dll 1
+dll\win32\urlmon\urlmon.dll 1
+dll\win32\user32\user32.dll 1
+dll\win32\userenv\userenv.dll 1
+dll\win32\usp10\usp10.dll 1
+dll\win32\uxtheme\uxtheme.dll 1
+dll\win32\vdmdbg\vdmdbg.dll 1
+dll\win32\version\version.dll 1
+dll\win32\windowscodecs\windowscodecs.dll 1
+dll\win32\winemp3.acm\winemp3.acm 1
+dll\win32\winfax\winfax.dll 1
+dll\win32\winhttp\winhttp.dll 1
+dll\win32\wininet\wininet.dll 1
+dll\win32\winmm\winmm.dll 1
+dll\win32\winspool\winspool.drv 1
+dll\win32\winsta\winsta.dll 1
+dll\win32\wlanapi\wlanapi.dll 1
+dll\win32\wintrust\wintrust.dll 1
+dll\win32\wldap32\wldap32.dll 1
+dll\win32\wmi\wmi.dll 1
+dll\win32\ws2_32\ws2_32.dll 1
+dll\win32\ws2help\ws2help.dll 1
+dll\win32\wshirda\wshirda.dll 1
+dll\win32\wshtcpip\wshtcpip.dll 1
+dll\win32\wsock32\wsock32.dll 1
+dll\win32\wtsapi32\wtsapi32.dll 1
+dll\win32\wuapi\wuapi.dll 1
+dll\win32\xinput1_1\xinput1_1.dll 1
+dll\win32\xinput1_2\xinput1_2.dll 1
+dll\win32\xinput1_3\xinput1_3.dll 1
+dll\win32\xinput9_1_0\xinput9_1_0.dll 1
+dll\win32\xmllite\xmllite.dll 1
+dll\win32\winmm\midimap\midimap.dll 1
+dll\win32\wdmaud.drv\wdmaud.drv 1
+
+; Shell Extensions
+dll\shellext\deskadp\deskadp.dll 1
+dll\shellext\deskmon\deskmon.dll 1
+
+; Drivers
+drivers\base\bootvid\bootvid.dll 1
+drivers\base\beep\beep.sys 2
+drivers\base\null\null.sys 2
+drivers\base\nmidebug\nmidebug.sys 2
+
+drivers\battery\battc\battc.sys 2
+
+drivers\bus\acpi\cmbatt\cmbatt.sys 2
+drivers\bus\acpi\compbatt\compbatt.sys 2
+
+drivers\directx\dxapi\dxapi.sys 2
+drivers\directx\dxg\dxg.sys 2
+drivers\directx\dxgthk\dxgthk.sys 2
+
+drivers\filesystems\fs_rec\fs_rec.sys 2
+drivers\filesystems\msfs\msfs.sys 2
+drivers\filesystems\mup\mup.sys 2
+drivers\filesystems\npfs\npfs.sys 2
+
+drivers\input\mouclass\mouclass.sys 2
+drivers\input\sermouse\sermouse.sys 2
+
+drivers\ksfilter\ks\ks.sys 2
+drivers\multimedia\bdasup\bdasup.sys 2
+
+drivers\network\afd\afd.sys 2
+drivers\network\ndis\ndis.sys 2
+drivers\network\tcpip\tcpip.sys 2
+drivers\network\tdi\tdi.sys 2
+drivers\network\dd\ne2000\ne2000.sys 2
+drivers\network\dd\pcnet\pcnet.sys 2
+
+drivers\serial\serenum\serenum.sys 2
+drivers\serial\serial\serial.sys 2
+
+drivers\storage\ide\pciide\pciide.sys 2
+drivers\storage\ide\pciidex\pciidex.sys 2
+
+;drivers\usb\miniport\usbohci\usbohci.sys 2
+;drivers\usb\miniport\usbuhci\usbuhci.sys 2
+;drivers\usb\usbhub\usbhub.sys 2
+;drivers\usb\usbport\usbport.sys 2
+drivers\usb\nt4compat\usbdriver\usbdriver.sys 2
+
+drivers\video\displays\vga\vgaddi.dll 1
+drivers\video\displays\framebuf\framebuf.dll 1
+drivers\video\miniport\vga\vgamp.sys 2
+drivers\video\miniport\vbe\vbemp.sys 2
+drivers\video\videoprt\videoprt.sys 2
+drivers\video\font\ftfd\ftfd.dll 1
+
+drivers\wdm\audio\filters\kmixer\kmixer.sys 2
+drivers\wdm\audio\sysaudio\sysaudio.sys 2
+drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2
+drivers\wdm\audio\backpln\portcls\portcls.sys 2
+drivers\wdm\audio\drm\drmk\drmk.sys 2
+drivers\wmi\wmilib.sys 2
+
+; Media
+media\fonts\DejaVuSans.ttf 3
+media\fonts\DejaVuSans-Bold.ttf 3
+media\fonts\DejaVuSans-BoldOblique.ttf 3
+media\fonts\DejaVuSansMono.ttf 3
+media\fonts\DejaVuSansMono-Bold.ttf 3
+media\fonts\DejaVuSansMono-BoldOblique.ttf 3
+media\fonts\DejaVuSansMono-Oblique.ttf 3
+media\fonts\DejaVuSans-Oblique.ttf 3
+media\fonts\DejaVuSerif.ttf 3
+media\fonts\DejaVuSerif-Bold.ttf 3
+media\fonts\DejaVuSerif-BoldItalic.ttf 3
+media\fonts\DejaVuSerif-Italic.ttf 3
+
+media\fonts\FreeMono.ttf 3
+media\fonts\FreeMonoBold.ttf 3
+media\fonts\FreeMonoBoldOblique.ttf 3
+media\fonts\FreeMonoOblique.ttf 3
+
+media\fonts\LiberationMono-Bold.ttf 3
+media\fonts\LiberationMono-BoldItalic.ttf 3
+media\fonts\LiberationMono-Italic.ttf 3
+media\fonts\LiberationMono-Regular.ttf 3
+media\fonts\LiberationSans-Bold.ttf 3
+media\fonts\LiberationSans-BoldItalic.ttf 3
+media\fonts\LiberationSans-Italic.ttf 3
+media\fonts\LiberationSans-Regular.ttf 3
+media\fonts\LiberationSerif-Bold.ttf 3
+media\fonts\LiberationSerif-BoldItalic.ttf 3
+media\fonts\LiberationSerif-Italic.ttf 3
+media\fonts\LiberationSerif-Regular.ttf 3
+
+media\fonts\Marlett.ttf 3
+media\fonts\symbol.ttf 3
+media\fonts\tahoma.ttf 3
+media\fonts\tahomabd.ttf 3
+
+media\vgafonts\vgafonts.cab 4
+
+media\nls\c_037.nls 1
+media\nls\c_424.nls 1
+media\nls\c_500.nls 1
+media\nls\c_737.nls 1
+media\nls\c_775.nls 1
+media\nls\c_850.nls 1
+media\nls\c_852.nls 1
+media\nls\c_855.nls 1
+media\nls\c_856.nls 1
+media\nls\c_857.nls 1
+media\nls\c_860.nls 1
+media\nls\c_861.nls 1
+media\nls\c_862.nls 1
+media\nls\c_863.nls 1
+media\nls\c_864.nls 1
+media\nls\c_865.nls 1
+media\nls\c_866.nls 1
+media\nls\c_869.nls 1
+media\nls\c_874.nls 1
+media\nls\c_875.nls 1
+media\nls\c_878.nls 1
+media\nls\c_932.nls 1
+media\nls\c_936.nls 1
+media\nls\c_949.nls 1
+media\nls\c_950.nls 1
+media\nls\c_1006.nls 1
+media\nls\c_1026.nls 1
+media\nls\c_1250.nls 1
+media\nls\c_1251.nls 1
+media\nls\c_1253.nls 1
+media\nls\c_1254.nls 1
+media\nls\c_1255.nls 1
+media\nls\c_1256.nls 1
+media\nls\c_1257.nls 1
+media\nls\c_1258.nls 1
+media\nls\c_10000.nls 1
+media\nls\c_10006.nls 1
+media\nls\c_10007.nls 1
+media\nls\c_10029.nls 1
+media\nls\c_10079.nls 1
+media\nls\c_10081.nls 1
+media\nls\c_20866.nls 1
+media\nls\c_21866.nls 1
+media\nls\c_28591.nls 1
+media\nls\c_28592.nls 1
+media\nls\c_28593.nls 1
+media\nls\c_28594.nls 1
+media\nls\c_28595.nls 1
+media\nls\c_28596.nls 1
+media\nls\c_28597.nls 1
+media\nls\c_28598.nls 1
+media\nls\c_28599.nls 1
+media\nls\c_28600.nls 1
+media\nls\c_28603.nls 1
+media\nls\c_28604.nls 1
+media\nls\c_28605.nls 1
+media\nls\c_28606.nls 1
+media\drivers\etc\hosts 5
+media\drivers\etc\services 5
+media\inf\audio.inf 6
+media\inf\acpi.inf 6
+media\inf\battery.inf 6
+media\inf\cdrom.inf 6
+media\inf\cpu.inf 6
+media\inf\display.inf 6
+media\inf\font.inf 6
+media\inf\fdc.inf 6
+media\inf\hdc.inf 6
+media\inf\intl.inf 6
+media\inf\layout.inf 6
+media\inf\machine.inf 6
+media\inf\msmouse.inf 6
+media\inf\keyboard.inf 6
+media\inf\ks.inf 6
+media\inf\NET_NIC.inf 6
+media\inf\netamd.inf 6
+media\inf\netisa.inf 6
+media\inf\netrtpnt.inf 6
+media\inf\nettcpip.inf 6
+media\inf\ports.inf 6
+media\inf\scsi.inf 6
+media\inf\syssetup.inf 6
+media\inf\usbport.inf 6
+media\inf\usb.inf 6
+media\inf\usbstor.inf 6
+media\inf\xboxdisp.inf 6
+
+
+; Media Files
+media\sounds\ReactOS_LogOn.wav 8
+
+; Ini Files
+boot\bootdata\system.ini 4
+
+; Regression Testing
+boot\bootdata\bootcdregtest\regtest.cmd 7 optional
+
+; Subsystems
+subsystems\win32\csrss\csrss.exe 1
+subsystems\win32\csrss\win32csr\win32csr.dll 1
+subsystems\win32\csrss\csrsrv\csrsrv.dll 1
+subsystems\ntvdm\ntvdm.exe 1
+subsystems\win32\win32k\win32k.sys 1
+
+; Optional/proprietary files
+modules\optional\DroidSansFallback.ttf 3 optional
+modules\optional\NOTICE_for_Droid_Font.txt 4 optional
+modules\optional\netkvm2k.inf 6 optional
+modules\optional\netkvm2k.cat 6 optional
+modules\optional\netkvm.sys 2 optional
+modules\optional\alcxwdm.inf 6 optional
+modules\optional\alcxwdm.sys 2 optional
+modules\optional\mfc42.dll 1 optional
+modules\optional\mfc42u.dll 1 optional
+modules\optional\mfc71.dll 1 optional
+modules\optional\mfc71u.dll 1 optional
+modules\optional\msvbvm50.dll 1 optional
+modules\optional\msvbvm60.dll 1 optional
+modules\optional\msvcirt.dll 1 optional
+modules\optional\msvcp71.dll 1 optional
+modules\optional\msvcr71.dll 1 optional
+modules\optional\vmx_fb.dll 1 optional
+modules\optional\vmx_mode.dll 1 optional
+modules\optional\vmx_svga.inf 6 optional
+modules\optional\vmx_svga.sys 2 optional
+modules\optional\wine_gecko-1.0.0-x86.cab 4 optional
+
+; Rosapps
+modules\rosapps\applications\screensavers\cylfrac\cylfrac.scr 1 optional
+modules\rosapps\applications\screensavers\matrix\matrix.scr 1 optional
+modules\rosapps\applications\screensavers\blankscr\scrnsave.scr 1 optional
+modules\rosapps\applications\screensavers\starfield\starfield.scr 1 optional
+modules\rosapps\applications\screensavers\mazescr\mazescr.scr 1 optional
+modules\rosapps\applications\screensavers\butterflies\butterflies.scr 1 optional
+modules\rosapps\applications\cmdutils\comp\comp.exe 1 optional
+modules\rosapps\applications\cmdutils\mode\mode.exe 1 optional
+modules\rosapps\applications\cmdutils\sort\sort.exe 1 optional
+modules\rosapps\applications\cmdutils\tee\tee.exe 1 optional
+modules\rosapps\applications\cmdutils\touch\touch.exe 1 optional
+modules\rosapps\applications\cmdutils\uptime\uptime.exe 1 optional
+modules\rosapps\applications\cmdutils\y\y.exe 1 optional
+modules\rosapps\applications\devutils\gdb2\gdb2.exe 1 optional
+modules\rosapps\applications\devutils\gdihv\gdihv.exe 1 optional
+modules\rosapps\applications\devutils\genguid\genguid.exe 1 optional
+modules\rosapps\applications\sysutils\gettype\gettype.exe 1 optional
+modules\rosapps\applications\net\ncftp\ncftp.exe 1 optional
+modules\rosapps\applications\net\netreg\netreg.exe 1 optional
+modules\rosapps\applications\net\niclist\niclist.exe 1 optional
+modules\rosapps\applications\net\roshttpd\roshttpd.exe 1 optional
+modules\rosapps\applications\notevil\notevil.exe 1 optional
+modules\rosapps\applications\sysutils\chkdsk\chkdsk.exe 1 optional
+modules\rosapps\applications\sysutils\systeminfo\systeminfo.exe 1 optional
+modules\rosapps\applications\sysutils\chklib\chklib.exe 1 optional
+modules\rosapps\applications\sysutils\ctm\ctm.exe 1 optional
+modules\rosapps\applications\sysutils\kill\kill.exe 1 optional
+modules\rosapps\applications\sysutils\lsdd\lsdd.exe 1 optional
+modules\rosapps\applications\sysutils\man\man.exe 1 optional
+modules\rosapps\applications\sysutils\pedump\pedump.exe 1 optional
+modules\rosapps\applications\sysutils\regexpl\regexpl.exe 1 optional
+modules\rosapps\applications\sysutils\tcat\tcat.exe 1 optional
+modules\rosapps\applications\sysutils\tlist\tlist.exe 1 optional
+modules\rosapps\applications\sysutils\screenshot\screenshot.exe 1 optional
+modules\rosapps\applications\sysutils\utils\binpatch\binpatch.exe 1 optional
+modules\rosapps\applications\sysutils\utils\cat\cat.exe 1 optional
+modules\rosapps\applications\sysutils\utils\driver\load\load.exe 1 optional
+modules\rosapps\applications\sysutils\utils\driver\unload\unload.exe 1 optional
+modules\rosapps\applications\sysutils\utils\infinst\infinst.exe 1 optional
+modules\rosapps\applications\sysutils\utils\nts2w32err\nts2w32err.exe 1 optional
+modules\rosapps\applications\sysutils\utils\objdir\objdir.exe 1 optional
+modules\rosapps\applications\sysutils\utils\partinfo\partinfo.exe 1 optional
+modules\rosapps\applications\sysutils\utils\ps\ps.exe 1 optional
+modules\rosapps\applications\sysutils\utils\rosperf\rosperf.exe 1 optional
+modules\rosapps\applications\sysutils\utils\stats\stats.exe 1 optional
+modules\rosapps\applications\sysutils\utils\tickcount\tickcount.exe 1 optional
+modules\rosapps\applications\winfile\winfile.exe 1 optional
+modules\rosapps\demos\maze\maze.exe 1 optional
+modules\rosapps\drivers\green\green.sys 2 optional
+
+; Rostests
+modules\rostests\rosautotest\rosautotest.exe 1 optional
++modules\rostests\drivers\kmtest\kmtest.sys 2 optional
++modules\rostests\drivers\kmtest\kmtestassist.sys 2 optional
+modules\rostests\tests\pseh2\pseh2_test.exe 7 optional
+modules\rostests\winetests\advapi32\advapi32_winetest.exe 7 optional
+modules\rostests\winetests\advpack\advpack_winetest.exe 7 optional
+modules\rostests\winetests\browseui\browseui_winetest.exe 7 optional
+modules\rostests\winetests\cabinet\cabinet_winetest.exe 7 optional
+modules\rostests\winetests\comcat\comcat_winetest.exe 7 optional
+modules\rostests\winetests\comctl32\comctl32_winetest.exe 7 optional
+modules\rostests\winetests\comdlg32\comdlg32_winetest.exe 7 optional
+modules\rostests\winetests\crypt32\crypt32_winetest.exe 7 optional
+modules\rostests\winetests\cryptnet\cryptnet_winetest.exe 7 optional
+modules\rostests\winetests\dsound\dsound_winetest.exe 7 optional
+modules\rostests\winetests\gdi32\gdi32_winetest.exe 7 optional
+modules\rostests\winetests\gdiplus\gdiplus_winetest.exe 7 optional
+modules\rostests\winetests\hlink\hlink_winetest.exe 7 optional
+modules\rostests\winetests\icmp\icmp_winetest.exe 7 optional
+modules\rostests\winetests\iphlpapi\iphlpapi_winetest.exe 7 optional
+modules\rostests\winetests\jscript\jscript_winetest.exe 7 optional
+modules\rostests\winetests\kernel32\kernel32_winetest.exe 7 optional
+modules\rostests\winetests\lz32\lz32_winetest.exe 7 optional
+modules\rostests\winetests\mapi32\mapi32_winetest.exe 7 optional
+modules\rostests\winetests\mlang\mlang_winetest.exe 7 optional
+modules\rostests\winetests\mshtml\mshtml_winetest.exe 7 optional
+modules\rostests\winetests\msi\msi_winetest.exe 7 optional
+modules\rostests\winetests\mstask\mstask_winetest.exe 7 optional
+modules\rostests\winetests\msvcrt\msvcrt_winetest.exe 7 optional
+modules\rostests\winetests\msxml3\msxml3_winetest.exe 7 optional
+modules\rostests\winetests\netapi32\netapi32_winetest.exe 7 optional
+modules\rostests\winetests\ntdll\ntdll_winetest.exe 7 optional
+modules\rostests\winetests\odbccp32\odbccp32_winetest.exe 7 optional
+modules\rostests\winetests\ole32\ole32_winetest.exe 7 optional
+modules\rostests\winetests\oleaut32\oleaut32_winetest.exe 7 optional
+modules\rostests\winetests\powrprof\powrprof_winetest.exe 7 optional
+modules\rostests\winetests\psapi\psapi_winetest.exe 7 optional
+modules\rostests\winetests\riched20\riched20_winetest.exe 7 optional
+modules\rostests\winetests\rpcrt4\rpcrt4_winetest.exe 7 optional
+modules\rostests\winetests\rsabase\rsabase_winetest.exe 7 optional
+modules\rostests\winetests\rsaenh\rsaenh_winetest.exe 7 optional
+modules\rostests\winetests\schannel\schannel_winetest.exe 7 optional
+modules\rostests\winetests\secur32\secur32_winetest.exe 7 optional
+modules\rostests\winetests\setupapi\setupapi_winetest.exe 7 optional
+modules\rostests\winetests\shdocvw\shdocvw_winetest.exe 7 optional
+modules\rostests\winetests\shell32\shell32_winetest.exe 7 optional
+modules\rostests\winetests\shlwapi\shlwapi_winetest.exe 7 optional
+modules\rostests\winetests\urlmon\urlmon_winetest.exe 7 optional
+modules\rostests\winetests\user32\user32_winetest.exe 7 optional
+modules\rostests\winetests\usp10\usp10_winetest.exe 7 optional
+modules\rostests\winetests\uxtheme\uxtheme_winetest.exe 7 optional
+modules\rostests\winetests\version\version_winetest.exe 7 optional
+modules\rostests\winetests\winhttp\winhttp_winetest.exe 7 optional
+modules\rostests\winetests\wininet\wininet_winetest.exe 7 optional
+modules\rostests\winetests\winmm\winmm_winetest.exe 7 optional
+modules\rostests\winetests\wintrust\wintrust_winetest.exe 7 optional
+modules\rostests\winetests\wlanapi\wlanapi_winetest.exe 7 optional
+modules\rostests\winetests\ws2_32\ws2_32_winetest.exe 7 optional
+modules\rostests\winetests\xmllite\xmllite_winetest.exe 7 optional
+
+
+modules\wallpaper\Angelus_02_ROSWP.bmp 4 optional
+
+modules\drivers\video\cirrus\cirrus.inf 6 optional
+modules\drivers\video\cirrus\cirrus.dll 1 optional
+modules\drivers\video\cirrus\cirrus.sys 2 optional
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
+<module name="win32csr" type="win32dll" installbase="system32" installname="win32csr.dll">
+ <importlibrary definition="win32csr.spec" />
+ <include base="win32csr">.</include>
+ <include base="csrss">include</include>
+ <include base="ReactOS">include/reactos/subsys</include>
+ <include base="ReactOS">include/reactos/drivers</include>
+ <include base="console">.</include>
+ <compilerflag compilerset="gcc">-fms-extensions</compilerflag>
+ <library>ntdll</library>
+ <library delayimport="true">user32</library>
+ <library delayimport="true">gdi32</library>
+ <library delayimport="true">advapi32</library>
+ <library>delayimp</library>
+ <library>win32ksys</library>
+ <library>psapi</library>
+ <library>pseh</library>
+ <pch>w32csr.h</pch>
+ <file>alias.c</file>
+ <file>conio.c</file>
+ <file>desktopbg.c</file>
+ <file>dllmain.c</file>
+ <file>exitros.c</file>
+ <file>guiconsole.c</file>
++ <file>handle.c</file>
+ <file>harderror.c</file>
+ <file>tuiconsole.c</file>
+ <file>appswitch.c</file>
+ <file>win32csr.rc</file>
+</module>
--- /dev/null
- BOOL FASTCALL
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * We handle two types of cursors/icons:
+ * - Private
+ * Loaded without LR_SHARED flag
+ * Private to a process
+ * Can be deleted by calling NtDestroyCursorIcon()
+ * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
+ * - Shared
+ * Loaded with LR_SHARED flag
+ * Possibly shared by multiple processes
+ * Immune to NtDestroyCursorIcon()
+ * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
+ * There's a M:N relationship between processes and (shared) cursor/icons.
+ * A process can have multiple cursor/icons and a cursor/icon can be used
+ * by multiple processes. To keep track of this we keep a list of all
+ * cursor/icons (CurIconList) and per cursor/icon we keep a list of
+ * CURICON_PROCESS structs starting at CurIcon->ProcessList.
+ */
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+static PAGED_LOOKASIDE_LIST gProcessLookasideList;
+static LIST_ENTRY gCurIconList;
+
+SYSTEM_CURSORINFO gSysCursorInfo;
+
- PSYSTEM_CURSORINFO FASTCALL
++BOOL
+InitCursorImpl()
+{
+ ExInitializePagedLookasideList(&gProcessLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(CURICON_PROCESS),
+ TAG_DIB,
+ 128);
+ InitializeListHead(&gCurIconList);
+
+ gSysCursorInfo.Enabled = FALSE;
+ gSysCursorInfo.ButtonsDown = 0;
+ gSysCursorInfo.CursorClipInfo.IsClipped = FALSE;
+ gSysCursorInfo.LastBtnDown = 0;
+ gSysCursorInfo.CurrentCursorObject = NULL;
+ gSysCursorInfo.ShowingCursor = 0;
+ gSysCursorInfo.ClickLockActive = FALSE;
+ gSysCursorInfo.ClickLockTime = 0;
+
+ return TRUE;
+}
+
- BOOL UserSetCursorPos( INT x, INT y)
++PSYSTEM_CURSORINFO
+IntGetSysCursorInfo()
+{
+ return &gSysCursorInfo;
+}
+
+/* This function creates a reference for the object! */
+PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
+{
+ PCURICON_OBJECT CurIcon;
+
+ if (!hCurIcon)
+ {
+ SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
+ return NULL;
+ }
+
+ CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon);
+ if (!CurIcon)
+ {
+ /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
+ SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
+ return NULL;
+ }
+
+ ASSERT(CurIcon->head.cLockObj >= 1);
+ return CurIcon;
+}
+
+HCURSOR
+FASTCALL
+UserSetCursor(
+ PCURICON_OBJECT NewCursor,
+ BOOL ForceChange)
+{
+ PSYSTEM_CURSORINFO CurInfo;
+ PCURICON_OBJECT OldCursor;
+ HCURSOR hOldCursor = (HCURSOR)0;
+ HDC hdcScreen;
+ BOOL bResult;
+
+ CurInfo = IntGetSysCursorInfo();
+
+ OldCursor = CurInfo->CurrentCursorObject;
+ if (OldCursor)
+ {
+ hOldCursor = (HCURSOR)OldCursor->Self;
+ }
+
+ /* Is the new cursor the same as the old cursor? */
+ if (OldCursor == NewCursor)
+ {
+ /* Nothing to to do in this case */
+ return hOldCursor;
+ }
+
+ /* Get the screen DC */
+ if(!(hdcScreen = IntGetScreenDC()))
+ {
+ return (HCURSOR)0;
+ }
+
+ /* Do we have a new cursor? */
+ if (NewCursor)
+ {
+ UserReferenceObject(NewCursor);
+
+ CurInfo->ShowingCursor = 1;
+ CurInfo->CurrentCursorObject = NewCursor;
+
+ /* Call GDI to set the new screen cursor */
+ bResult = GreSetPointerShape(hdcScreen,
+ NewCursor->IconInfo.hbmMask,
+ NewCursor->IconInfo.hbmColor,
+ NewCursor->IconInfo.xHotspot,
+ NewCursor->IconInfo.yHotspot,
+ gpsi->ptCursor.x,
+ gpsi->ptCursor.y);
+
+
+ }
+ else
+ {
+ /* Check if were diplaying a cursor */
+ if (OldCursor && CurInfo->ShowingCursor)
+ {
+ /* Remove the cursor */
+ GreMovePointer(hdcScreen, -1, -1);
+ DPRINT("Removing pointer!\n");
+ }
+
+ CurInfo->CurrentCursorObject = NULL;
+ CurInfo->ShowingCursor = 0;
+ }
+
+ /* OldCursor is not in use anymore */
+ if (OldCursor)
+ {
+ UserDereferenceObject(OldCursor);
+ }
+
+ /* Return handle of the old cursor */
+ return hOldCursor;
+}
+
- MsqInsertSystemMessage(&Msg);
++BOOL UserSetCursorPos( INT x, INT y, BOOL CallHooks)
+{
+ PWINDOW_OBJECT DesktopWindow;
+ PSYSTEM_CURSORINFO CurInfo;
++ LARGE_INTEGER LargeTickCount;
++ MSLLHOOKSTRUCT MouseHookData;
+ HDC hDC;
+ MSG Msg;
+
+ if(!(hDC = IntGetScreenDC()))
+ {
+ return FALSE;
+ }
+
+ CurInfo = IntGetSysCursorInfo();
+
+ DesktopWindow = UserGetDesktopWindow();
+
+ if (DesktopWindow)
+ {
+ if(x >= DesktopWindow->Wnd->rcClient.right)
+ x = DesktopWindow->Wnd->rcClient.right - 1;
+ if(y >= DesktopWindow->Wnd->rcClient.bottom)
+ y = DesktopWindow->Wnd->rcClient.bottom - 1;
+ }
+
+ if(x < 0)
+ x = 0;
+ if(y < 0)
+ y = 0;
+
+ //Clip cursor position
+ if(CurInfo->CursorClipInfo.IsClipped)
+ {
+ if(x >= (LONG)CurInfo->CursorClipInfo.Right)
+ x = (LONG)CurInfo->CursorClipInfo.Right - 1;
+ if(x < (LONG)CurInfo->CursorClipInfo.Left)
+ x = (LONG)CurInfo->CursorClipInfo.Left;
+ if(y >= (LONG)CurInfo->CursorClipInfo.Bottom)
+ y = (LONG)CurInfo->CursorClipInfo.Bottom - 1;
+ if(y < (LONG)CurInfo->CursorClipInfo.Top)
+ y = (LONG)CurInfo->CursorClipInfo.Top;
+ }
+
+ //Store the new cursor position
+ gpsi->ptCursor.x = x;
+ gpsi->ptCursor.y = y;
+
++ KeQueryTickCount(&LargeTickCount);
++ Msg.time = MsqCalculateMessageTime(&LargeTickCount);
++
+ //Move the mouse pointer
+ GreMovePointer(hDC, x, y);
+
+ //Generate a mouse move message
+ Msg.message = WM_MOUSEMOVE;
+ Msg.wParam = CurInfo->ButtonsDown;
+ Msg.lParam = MAKELPARAM(x, y);
+ Msg.pt = gpsi->ptCursor;
- PCURICON_OBJECT FASTCALL
+
++ MouseHookData.pt.x = LOWORD(Msg.lParam);
++ MouseHookData.pt.y = HIWORD(Msg.lParam);
++ switch(Msg.message)
++ {
++ case WM_MOUSEWHEEL:
++ MouseHookData.mouseData = MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg.wParam));
++ break;
++ case WM_XBUTTONDOWN:
++ case WM_XBUTTONUP:
++ case WM_XBUTTONDBLCLK:
++ case WM_NCXBUTTONDOWN:
++ case WM_NCXBUTTONUP:
++ case WM_NCXBUTTONDBLCLK:
++ MouseHookData.mouseData = MAKELONG(0, HIWORD(Msg.wParam));
++ break;
++ default:
++ MouseHookData.mouseData = 0;
++ break;
++ }
++
++ MouseHookData.flags = 0;
++ MouseHookData.time = Msg.time;
++ MouseHookData.dwExtraInfo = 0;
++
++ if (CallHooks)
++ {
++ /* If the hook procedure returned non zero, dont send the message */
++ if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg.message, (LPARAM) &MouseHookData))
++ return FALSE;
++ }
++
++ MsqInsertSystemMessage(&Msg);
+ return TRUE;
+}
+
+/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
+ * User32 macro NtUserShowCursor */
+int UserShowCursor(BOOL bShow)
+{
+ PSYSTEM_CURSORINFO CurInfo = IntGetSysCursorInfo();
+ HDC hdcScreen;
+
+ if (!(hdcScreen = IntGetScreenDC()))
+ {
+ return 0; /* No mouse */
+ }
+
+ if (bShow == FALSE)
+ {
+ /* Check if were diplaying a cursor */
+ if (CurInfo->ShowingCursor == 1)
+ {
+ /* Remove the pointer */
+ GreMovePointer(hdcScreen, -1, -1);
+ DPRINT("Removing pointer!\n");
+ }
+ CurInfo->ShowingCursor--;
+ }
+ else
+ {
+ if (CurInfo->ShowingCursor == 0)
+ {
+ /*Show the pointer*/
+ GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
+ }
+ CurInfo->ShowingCursor++;
+ }
+
+ return CurInfo->ShowingCursor;
+}
+
+/*
+ * We have to register that this object is in use by the current
+ * process. The only way to do that seems to be to walk the list
+ * of cursor/icon objects starting at W32Process->CursorIconListHead.
+ * If the object is already present in the list, we don't have to do
+ * anything, if it's not present we add it and inc the ProcessCount
+ * in the object. Having to walk the list kind of sucks, but that's
+ * life...
+ */
+static BOOLEAN FASTCALL
+ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
+{
+ PPROCESSINFO Win32Process;
+ PCURICON_PROCESS Current;
+
+ Win32Process = PsGetCurrentProcessWin32Process();
+
+ LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+ {
+ if (Current->Process == Win32Process)
+ {
+ /* Already registered for this process */
+ return TRUE;
+ }
+ }
+
+ /* Not registered yet */
+ Current = ExAllocateFromPagedLookasideList(&gProcessLookasideList);
+ if (NULL == Current)
+ {
+ return FALSE;
+ }
+ InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
+ Current->Process = Win32Process;
+
+ return TRUE;
+}
+
+PCURICON_OBJECT FASTCALL
+IntFindExistingCurIconObject(HMODULE hModule,
+ HRSRC hRsrc, LONG cx, LONG cy)
+{
+ PCURICON_OBJECT CurIcon;
+
+ LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
+ {
+
+ // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
+// UserReferenceObject( CurIcon);
+// {
+ if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
+ {
+ if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy)))
+ {
+// UserDereferenceObject(CurIcon);
+ continue;
+ }
+ if (! ReferenceCurIconByProcess(CurIcon))
+ {
+ return NULL;
+ }
+
+ return CurIcon;
+ }
+// }
+// UserDereferenceObject(CurIcon);
+
+ }
+
+ return NULL;
+}
+
- UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y);
++PCURICON_OBJECT
+IntCreateCurIconHandle()
+{
+ PCURICON_OBJECT CurIcon;
+ HANDLE hCurIcon;
+
+ CurIcon = UserCreateObject(gHandleTable, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
+
+ if (!CurIcon)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ CurIcon->Self = hCurIcon;
+ InitializeListHead(&CurIcon->ProcessList);
+
+ if (! ReferenceCurIconByProcess(CurIcon))
+ {
+ DPRINT1("Failed to add process\n");
+ UserDeleteObject(hCurIcon, otCursorIcon);
+ UserDereferenceObject(CurIcon);
+ return NULL;
+ }
+
+ InsertHeadList(&gCurIconList, &CurIcon->ListEntry);
+
+ return CurIcon;
+}
+
+BOOLEAN FASTCALL
+IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
+{
+ PSYSTEM_CURSORINFO CurInfo;
+ HBITMAP bmpMask, bmpColor;
+ BOOLEAN Ret;
+ PCURICON_PROCESS Current = NULL;
+ PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
+
+ /* Private objects can only be destroyed by their own process */
+ if (NULL == CurIcon->hModule)
+ {
+ ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
+ Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
+ if (Current->Process != W32Process)
+ {
+ DPRINT1("Trying to destroy private icon/cursor of another process\n");
+ return FALSE;
+ }
+ }
+ else if (! ProcessCleanup)
+ {
+ DPRINT("Trying to destroy shared icon/cursor\n");
+ return FALSE;
+ }
+
+ /* Now find this process in the list of processes referencing this object and
+ remove it from that list */
+ LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+ {
+ if (Current->Process == W32Process)
+ {
+ RemoveEntryList(&Current->ListEntry);
+ break;
+ }
+ }
+
+ ExFreeToPagedLookasideList(&gProcessLookasideList, Current);
+
+ /* If there are still processes referencing this object we can't destroy it yet */
+ if (! IsListEmpty(&CurIcon->ProcessList))
+ {
+ return TRUE;
+ }
+
+
+ if (! ProcessCleanup)
+ {
+ RemoveEntryList(&CurIcon->ListEntry);
+ }
+
+ CurInfo = IntGetSysCursorInfo();
+
+ if (CurInfo->CurrentCursorObject == CurIcon)
+ {
+ /* Hide the cursor if we're destroying the current cursor */
+ UserSetCursor(NULL, TRUE);
+ }
+
+ bmpMask = CurIcon->IconInfo.hbmMask;
+ bmpColor = CurIcon->IconInfo.hbmColor;
+
+ /* delete bitmaps */
+ if (bmpMask)
+ {
+ GDIOBJ_SetOwnership(bmpMask, PsGetCurrentProcess());
+ GreDeleteObject(bmpMask);
+ CurIcon->IconInfo.hbmMask = NULL;
+ }
+ if (bmpColor)
+ {
+ GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess());
+ GreDeleteObject(bmpColor);
+ CurIcon->IconInfo.hbmColor = NULL;
+ }
+
+ /* We were given a pointer, no need to keep the reference anylonger! */
+ UserDereferenceObject(CurIcon);
+ Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
+
+ return Ret;
+}
+
+VOID FASTCALL
+IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
+{
+ PCURICON_OBJECT CurIcon, tmp;
+ PCURICON_PROCESS ProcessData;
+
+ LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
+ {
+ UserReferenceObject(CurIcon);
+ // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
+ {
+ LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+ {
+ if (Win32Process == ProcessData->Process)
+ {
+ RemoveEntryList(&CurIcon->ListEntry);
+ IntDestroyCurIconObject(CurIcon, TRUE);
+ CurIcon = NULL;
+ break;
+ }
+ }
+
+// UserDereferenceObject(Object);
+ }
+
+ if (CurIcon)
+ {
+ UserDereferenceObject(CurIcon);
+ }
+ }
+
+}
+
+/*
+ * @implemented
+ */
+HANDLE
+APIENTRY
+NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL, BOOL Indirect)
+{
+ PCURICON_OBJECT CurIcon;
+ PSURFACE psurfBmp;
+ NTSTATUS Status;
+ HANDLE Ret;
+ DECLARE_RETURN(HANDLE);
+
+ DPRINT("Enter NtUserCreateCursorIconHandle\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = IntCreateCurIconHandle()))
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ RETURN((HANDLE)0);
+ }
+
+ Ret = CurIcon->Self;
+
+ if (IconInfo)
+ {
+ Status = MmCopyFromCaller(&CurIcon->IconInfo, IconInfo, sizeof(ICONINFO));
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy bitmaps and size info */
+ if (Indirect)
+ {
+ // FIXME: WTF?
+ CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
+ if(CurIcon->IconInfo.hbmColor)
+ {
+ CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
+ }
+ }
+ else
+ {
+ if (CurIcon->IconInfo.hbmColor &&
+ (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
+ {
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
+ SURFACE_UnlockSurface(psurfBmp);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
+ }
+ if (CurIcon->IconInfo.hbmMask &&
+ (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
+ {
+ if(!CurIcon->IconInfo.hbmColor)
+ {
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy*2;
+ }
+ SURFACE_UnlockSurface(psurfBmp);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
+ }
+ }
+
+ /* Calculate icon hotspot */
+ if (CurIcon->IconInfo.fIcon == TRUE)
+ {
+ CurIcon->IconInfo.xHotspot = CurIcon->Size.cx >> 1;
+ CurIcon->IconInfo.yHotspot = CurIcon->Size.cy >> 1;
+ }
+ }
+ else
+ {
+ SetLastNtError(Status);
+ /* FIXME - Don't exit here */
+ }
+ }
+
+ UserDereferenceObject(CurIcon);
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserGetIconInfo(
+ HANDLE hCurIcon,
+ PICONINFO IconInfo,
+ PUNICODE_STRING lpInstName, // optional
+ PUNICODE_STRING lpResName, // optional
+ LPDWORD pbpp, // optional
+ BOOL bInternal)
+{
+ ICONINFO ii;
+ PCURICON_OBJECT CurIcon;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL Ret = FALSE;
+ DWORD colorBpp = 0;
+
+ DPRINT("Enter NtUserGetIconInfo\n");
+ UserEnterExclusive();
+
+ if (!IconInfo)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ goto leave;
+ }
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ goto leave;
+ }
+
+ RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO));
+
+ /* Copy bitmaps */
+ ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
+ ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
+
+ if (pbpp)
+ {
+ PSURFACE psurfBmp;
+
+ psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
+ if (psurfBmp)
+ {
+ colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
+ SURFACE_UnlockSurface(psurfBmp);
+ }
+ }
+
+ /* Copy fields */
+ _SEH2_TRY
+ {
+ ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
+ RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
+
+ if (pbpp)
+ {
+ ProbeForWrite(pbpp, sizeof(DWORD), 1);
+ *pbpp = colorBpp;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (NT_SUCCESS(Status))
+ Ret = TRUE;
+ else
+ SetLastNtError(Status);
+
+ UserDereferenceObject(CurIcon);
+
+leave:
+ DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret);
+ UserLeave();
+
+ return Ret;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserGetIconSize(
+ HANDLE hCurIcon,
+ UINT istepIfAniCur,
+ PLONG plcx, // &size.cx
+ PLONG plcy) // &size.cy
+{
+ PCURICON_OBJECT CurIcon;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL bRet = FALSE;
+
+ DPRINT("Enter NtUserGetIconSize\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ goto cleanup;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(plcx, sizeof(LONG), 1);
+ RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG));
+ ProbeForWrite(plcy, sizeof(LONG), 1);
+ RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (NT_SUCCESS(Status))
+ bRet = TRUE;
+ else
+ SetLastNtError(Status); // maybe not, test this
+
+ UserDereferenceObject(CurIcon);
+
+cleanup:
+ DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet);
+ UserLeave();
+ return bRet;
+}
+
+
+/*
+ * @unimplemented
+ */
+DWORD
+APIENTRY
+NtUserGetCursorFrameInfo(
+ DWORD Unknown0,
+ DWORD Unknown1,
+ DWORD Unknown2,
+ DWORD Unknown3)
+{
+ UNIMPLEMENTED
+
+ return 0;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserGetCursorInfo(
+ PCURSORINFO pci)
+{
+ CURSORINFO SafeCi;
+ PSYSTEM_CURSORINFO CurInfo;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCURICON_OBJECT CurIcon;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetCursorInfo\n");
+ UserEnterExclusive();
+
+ CurInfo = IntGetSysCursorInfo();
+ CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject;
+
+ SafeCi.cbSize = sizeof(CURSORINFO);
+ SafeCi.flags = ((CurInfo->ShowingCursor && CurIcon) ? CURSOR_SHOWING : 0);
+ SafeCi.hCursor = (CurIcon ? (HCURSOR)CurIcon->Self : (HCURSOR)0);
+
+ SafeCi.ptScreenPos = gpsi->ptCursor;
+
+ _SEH2_TRY
+ {
+ if (pci->cbSize == sizeof(CURSORINFO))
+ {
+ ProbeForWrite(pci, sizeof(CURSORINFO), 1);
+ RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO));
+ Ret = TRUE;
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ }
+
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL
+APIENTRY
+UserClipCursor(
+ RECTL *prcl)
+{
+ /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
+ PSYSTEM_CURSORINFO CurInfo;
+ PWINDOW_OBJECT DesktopWindow = NULL;
+
+ CurInfo = IntGetSysCursorInfo();
+
+ DesktopWindow = UserGetDesktopWindow();
+
+ if (prcl != NULL &&
+ (prcl->right > prcl->left) &&
+ (prcl->bottom > prcl->top) &&
+ DesktopWindow != NULL)
+ {
+ CurInfo->CursorClipInfo.IsClipped = TRUE;
+ CurInfo->CursorClipInfo.Left = max(prcl->left, DesktopWindow->Wnd->rcWindow.left);
+ CurInfo->CursorClipInfo.Top = max(prcl->top, DesktopWindow->Wnd->rcWindow.top);
+ CurInfo->CursorClipInfo.Right = min(prcl->right, DesktopWindow->Wnd->rcWindow.right);
+ CurInfo->CursorClipInfo.Bottom = min(prcl->bottom, DesktopWindow->Wnd->rcWindow.bottom);
+
++ UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+ }
+ else
+ {
+ CurInfo->CursorClipInfo.IsClipped = FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserClipCursor(
+ RECTL *prcl)
+{
+ /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
+ RECTL rclLocal;
+ BOOL bResult;
+
+ if (prcl)
+ {
+ _SEH2_TRY
+ {
+ /* Probe and copy rect */
+ ProbeForRead(prcl, sizeof(RECTL), 1);
+ rclLocal = *prcl;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ _SEH2_YIELD(return FALSE;)
+ }
+ _SEH2_END
+
+ prcl = &rclLocal;
+ }
+
+ UserEnterExclusive();
+
+ /* Call the internal function */
+ bResult = UserClipCursor(prcl);
+
+ UserLeave();
+
+ return bResult;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserDestroyCursor(
+ HANDLE hCurIcon,
+ DWORD Unknown)
+{
+ PCURICON_OBJECT CurIcon;
+ BOOL ret;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserDestroyCursorIcon\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ RETURN(FALSE);
+ }
+
+ ret = IntDestroyCurIconObject(CurIcon, FALSE);
+ /* Note: IntDestroyCurIconObject will remove our reference for us! */
+
+ RETURN(ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * @implemented
+ */
+HICON
+APIENTRY
+NtUserFindExistingCursorIcon(
+ HMODULE hModule,
+ HRSRC hRsrc,
+ LONG cx,
+ LONG cy)
+{
+ PCURICON_OBJECT CurIcon;
+ HANDLE Ret = (HANDLE)0;
+ DECLARE_RETURN(HICON);
+
+ DPRINT("Enter NtUserFindExistingCursorIcon\n");
+ UserEnterExclusive();
+
+ CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy);
+ if (CurIcon)
+ {
+ Ret = CurIcon->Self;
+
+// IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
+ RETURN(Ret);
+ }
+
+ SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
+ RETURN((HANDLE)0);
+
+CLEANUP:
+ DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserGetClipCursor(
+ RECTL *lpRect)
+{
+ /* FIXME - check if process has WINSTA_READATTRIBUTES */
+ PSYSTEM_CURSORINFO CurInfo;
+ RECTL Rect;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetClipCursor\n");
+ UserEnterExclusive();
+
+ if (!lpRect)
+ RETURN(FALSE);
+
+ CurInfo = IntGetSysCursorInfo();
+ if (CurInfo->CursorClipInfo.IsClipped)
+ {
+ Rect.left = CurInfo->CursorClipInfo.Left;
+ Rect.top = CurInfo->CursorClipInfo.Top;
+ Rect.right = CurInfo->CursorClipInfo.Right;
+ Rect.bottom = CurInfo->CursorClipInfo.Bottom;
+ }
+ else
+ {
+ Rect.left = 0;
+ Rect.top = 0;
+ Rect.right = UserGetSystemMetrics(SM_CXSCREEN);
+ Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+ }
+
+ Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * @implemented
+ */
+HCURSOR
+APIENTRY
+NtUserSetCursor(
+ HCURSOR hCursor)
+{
+ PCURICON_OBJECT CurIcon;
+ HICON OldCursor;
+ DECLARE_RETURN(HCURSOR);
+
+ DPRINT("Enter NtUserSetCursor\n");
+ UserEnterExclusive();
+
+ if (hCursor)
+ {
+ if (!(CurIcon = UserGetCurIconObject(hCursor)))
+ {
+ RETURN(NULL);
+ }
+ }
+ else
+ {
+ CurIcon = NULL;
+ }
+
+ OldCursor = UserSetCursor(CurIcon, FALSE);
+
+ if (CurIcon)
+ {
+ UserDereferenceObject(CurIcon);
+ }
+
+ RETURN(OldCursor);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserSetCursorContents(
+ HANDLE hCurIcon,
+ PICONINFO UnsafeIconInfo)
+{
+ PCURICON_OBJECT CurIcon;
+ ICONINFO IconInfo;
+ PSURFACE psurfBmp;
+ NTSTATUS Status;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSetCursorContents\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ RETURN(FALSE);
+ }
+
+ /* Copy fields */
+ Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ goto done;
+ }
+
+ /* Delete old bitmaps */
+ if (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)
+ {
+ GreDeleteObject(CurIcon->IconInfo.hbmColor);
+ }
+ if (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
+ {
+ GreDeleteObject(CurIcon->IconInfo.hbmMask);
+ }
+
+ /* Copy new IconInfo field */
+ CurIcon->IconInfo = IconInfo;
+
+ psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
+ if (psurfBmp)
+ {
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
+ SURFACE_UnlockSurface(psurfBmp);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
+ }
+ else
+ {
+ psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask);
+ if (!psurfBmp)
+ goto done;
+
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
+
+ SURFACE_UnlockSurface(psurfBmp);
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
+ }
+
+ Ret = TRUE;
+
+done:
+
+ if (CurIcon)
+ {
+ UserDereferenceObject(CurIcon);
+ }
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * @implemented
+ */
+#if 0
+BOOL
+APIENTRY
+NtUserSetCursorIconData(
+ HANDLE Handle,
+ HMODULE hModule,
+ PUNICODE_STRING pstrResName,
+ PICONINFO pIconInfo)
+{
+ PCURICON_OBJECT CurIcon;
+ PSURFACE psurfBmp;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSetCursorIconData\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = UserGetCurIconObject(Handle)))
+ {
+ RETURN(FALSE);
+ }
+
+ CurIcon->hModule = hModule;
+ CurIcon->hRsrc = NULL; //hRsrc;
+ CurIcon->hGroupRsrc = NULL; //hGroupRsrc;
+
+ _SEH2_TRY
+ {
+ ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
+ RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO));
+
+ CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask);
+ CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor);
+
+ if (CurIcon->IconInfo.hbmColor)
+ {
+ if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
+ {
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
+ SURFACE_UnlockSurface(psurfBmp);
+ GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
+ }
+ }
+ if (CurIcon->IconInfo.hbmMask)
+ {
+ if (CurIcon->IconInfo.hbmColor == NULL)
+ {
+ if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
+ {
+ CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
+ CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
+ SURFACE_UnlockSurface(psurfBmp);
+ }
+ }
+ GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (!NT_SUCCESS(Status))
+ SetLastNtError(Status);
+ else
+ Ret = TRUE;
+
+ UserDereferenceObject(CurIcon);
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+#else
+BOOL
+APIENTRY
+NtUserSetCursorIconData(
+ HANDLE hCurIcon,
+ PBOOL fIcon,
+ POINT *Hotspot,
+ HMODULE hModule,
+ HRSRC hRsrc,
+ HRSRC hGroupRsrc)
+{
+ PCURICON_OBJECT CurIcon;
+ NTSTATUS Status;
+ POINT SafeHotspot;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSetCursorIconData\n");
+ UserEnterExclusive();
+
+ if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+ {
+ RETURN(FALSE);
+ }
+
+ CurIcon->hModule = hModule;
+ CurIcon->hRsrc = hRsrc;
+ CurIcon->hGroupRsrc = hGroupRsrc;
+
+ /* Copy fields */
+ if (fIcon)
+ {
+ Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ goto done;
+ }
+ }
+ else
+ {
+ if (!Hotspot)
+ Ret = TRUE;
+ }
+
+ if (Hotspot)
+ {
+ Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT));
+ if (NT_SUCCESS(Status))
+ {
+ CurIcon->IconInfo.xHotspot = SafeHotspot.x;
+ CurIcon->IconInfo.yHotspot = SafeHotspot.y;
+
+ Ret = TRUE;
+ }
+ else
+ SetLastNtError(Status);
+ }
+
+ if (!fIcon && !Hotspot)
+ {
+ Ret = TRUE;
+ }
+
+done:
+ UserDereferenceObject(CurIcon);
+ RETURN(Ret);
+
+
+CLEANUP:
+ DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+#endif
+
+/*
+ * @unimplemented
+ */
+BOOL
+APIENTRY
+NtUserSetSystemCursor(
+ HCURSOR hcur,
+ DWORD id)
+{
+ return FALSE;
+}
+
+/* Mostly inspired from wine code */
+BOOL
+UserDrawIconEx(
+ HDC hDc,
+ INT xLeft,
+ INT yTop,
+ PCURICON_OBJECT pIcon,
+ INT cxWidth,
+ INT cyHeight,
+ UINT istepIfAniCur,
+ HBRUSH hbrFlickerFreeDraw,
+ UINT diFlags)
+{
+ BOOL Ret = FALSE;
+ HBITMAP hbmMask, hbmColor;
+ BITMAP bmpColor, bm;
+ BOOL DoFlickerFree;
+ SIZE IconSize;
+ INT iOldBkColor = 0, iOldTxtColor = 0;
+
+ HDC hMemDC, hOffDC = NULL;
+ HGDIOBJ hOldOffBrush = 0;
+ HGDIOBJ hOldOffBmp = 0;
+ HBITMAP hTmpBmp = 0, hOffBmp = 0;
+ BOOL bAlpha = FALSE;
+
+ hbmMask = pIcon->IconInfo.hbmMask;
+ hbmColor = pIcon->IconInfo.hbmColor;
+
+ if (istepIfAniCur)
+ DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
+
+ if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
+ {
+ return FALSE;
+ }
+
+ if (hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
+ {
+ return FALSE;
+ }
+
+ if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
+ {
+ DPRINT1("NtGdiCreateCompatibleDC failed!\n");
+ return FALSE;
+ }
+
+ if (hbmColor)
+ {
+ IconSize.cx = bmpColor.bmWidth;
+ IconSize.cy = bmpColor.bmHeight;
+ }
+ else /* take it from mask */
+ {
+ IconSize.cx = bm.bmWidth;
+ IconSize.cy = bm.bmHeight/2;
+ }
+
+ if (!diFlags)
+ diFlags = DI_NORMAL;
+
+ /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
+ when cxWidth or cyHeight is 0 */
+ if (hbmColor
+ && (bmpColor.bmBitsPixel == 32)
+ && (cxWidth != 0)
+ && (cyHeight != 0)
+ && (diFlags & DI_IMAGE))
+ {
+ SURFACE *psurfOff = NULL;
+ PFN_DIB_GetPixel fnSource_GetPixel = NULL;
+ INT x, y;
+
+ /* In order to correctly display 32 bit icons Windows first scans the image,
+ because information about transparency is not stored in any image's headers */
+ psurfOff = SURFACE_LockSurface(hbmColor);
+ if (psurfOff)
+ {
+ fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
+ if (fnSource_GetPixel)
+ {
+ for (x = 0; x < psurfOff->SurfObj.sizlBitmap.cx; x++)
+ {
+ for (y = 0; y < psurfOff->SurfObj.sizlBitmap.cy; y++)
+ {
+ bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, x, y) >> 24) & 0xff);
+ if (bAlpha)
+ break;
+ }
+ if (bAlpha)
+ break;
+ }
+ }
+ SURFACE_UnlockSurface(psurfOff);
+ }
+ }
+
+ if (!cxWidth)
+ cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
+ UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
+
+ if (!cyHeight)
+ cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
+ UserGetSystemMetrics(SM_CYICON) : IconSize.cy);
+
+ DoFlickerFree = (hbrFlickerFreeDraw &&
+ (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
+
+ if (DoFlickerFree)
+ {
+ hOffDC = NtGdiCreateCompatibleDC(hDc);
+ if(!hOffDC)
+ {
+ DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
+ Ret = FALSE;
+ goto Cleanup ;
+ }
+ hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
+ if(!hOffBmp)
+ {
+ DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
+ goto Cleanup ;
+ }
+ hOldOffBmp = NtGdiSelectBitmap(hOffDC, hOffBmp);
+ hOldOffBrush = NtGdiSelectBrush(hOffDC, hbrFlickerFreeDraw);
+ NtGdiPatBlt(hOffDC, 0, 0, cxWidth, cyHeight, PATCOPY);
+ NtGdiSelectBrush(hOffDC, hOldOffBrush);
+ }
+ else
+ {
+ /* Set Background/foreground colors */
+ iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black
+ iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white
+ }
+
+
+ if (hbmMask && (diFlags & DI_MASK) && !bAlpha)
+ {
+ hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
+ NtGdiStretchBlt(hOffDC ? hOffDC : hDc,
+ hOffDC ? 0 : xLeft,
+ hOffDC ? 0 : yTop,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ 0,
+ IconSize.cx,
+ IconSize.cy,
+ SRCAND,
+ 0);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ }
+
+ if(diFlags & DI_IMAGE)
+ {
+ if (bAlpha)
+ {
+ BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ DWORD Pixel;
+ BYTE Red, Green, Blue, Alpha;
+ DWORD Count = 0;
+ INT i, j;
+ PSURFACE psurf;
+ PBYTE pBits ;
+ HBITMAP hMemBmp = NULL;
+
+ pBits = ExAllocatePoolWithTag(PagedPool,
+ bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
+ TAG_BITMAP);
+ if (pBits == NULL)
+ {
+ Ret = FALSE;
+ goto CleanupAlpha;
+ }
+
+ hMemBmp = BITMAP_CopyBitmap(hbmColor);
+ if(!hMemBmp)
+ {
+ DPRINT1("BITMAP_CopyBitmap failed!");
+ goto CleanupAlpha;
+ }
+
+ psurf = SURFACE_LockSurface(hMemBmp);
+ if(!psurf)
+ {
+ DPRINT1("SURFACE_LockSurface failed!\n");
+ goto CleanupAlpha;
+ }
+ /* get color bits */
+ IntGetBitmapBits(psurf,
+ bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
+ pBits);
+
+ /* premultiply with the alpha channel value */
+ for (i = 0; i < cyHeight; i++)
+ {
+ for (j = 0; j < cxWidth; j++)
+ {
+ Pixel = *(DWORD *)(pBits + Count);
+
+ Alpha = ((BYTE)(Pixel >> 24) & 0xff);
+
+ Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
+ Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
+ Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
+
+ *(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
+
+ Count += sizeof(DWORD);
+ }
+ }
+
+ /* set mem bits */
+ IntSetBitmapBits(psurf,
+ bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
+ pBits);
+ SURFACE_UnlockSurface(psurf);
+
+ hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
+
+ NtGdiAlphaBlend(hOffDC ? hOffDC : hDc,
+ hOffDC ? 0 : xLeft,
+ hOffDC ? 0 : yTop,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ 0,
+ IconSize.cx,
+ IconSize.cy,
+ pixelblend,
+ NULL);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ CleanupAlpha:
+ if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
+ if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
+ }
+ else if (hbmColor)
+ {
+ DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
+ hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
+ NtGdiStretchBlt(hOffDC ? hOffDC : hDc,
+ hOffDC ? 0 : xLeft,
+ hOffDC ? 0 : yTop,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ 0,
+ IconSize.cx,
+ IconSize.cy,
+ rop,
+ 0);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ }
+ }
+
+ if(hOffDC)
+ {
+ NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hOffDC, 0, 0, SRCCOPY, 0, 0);
+ }
+ else
+ {
+ IntGdiSetBkColor(hDc, iOldBkColor);
+ IntGdiSetTextColor(hDc, iOldTxtColor);
+ }
+
+ Ret = TRUE ;
+
+Cleanup:
+ NtGdiDeleteObjectApp(hMemDC);
+ if(hOldOffBmp) NtGdiSelectBitmap(hOffDC, hOldOffBmp);
+ if(hOffDC) NtGdiDeleteObjectApp(hOffDC);
+ if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
+
+ return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserDrawIconEx(
+ HDC hdc,
+ int xLeft,
+ int yTop,
+ HICON hIcon,
+ int cxWidth,
+ int cyHeight,
+ UINT istepIfAniCur,
+ HBRUSH hbrFlickerFreeDraw,
+ UINT diFlags,
+ BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32!
+ PVOID pDIXData)
+{
+ PCURICON_OBJECT pIcon;
+ BOOL Ret;
+
+ DPRINT("Enter NtUserDrawIconEx\n");
+ UserEnterExclusive();
+
+ if (!(pIcon = UserGetCurIconObject(hIcon)))
+ {
+ DPRINT1("UserGetCurIconObject() failed!\n");
+ UserLeave();
+ return FALSE;
+ }
+
+ Ret = UserDrawIconEx(hdc,
+ xLeft,
+ yTop,
+ pIcon,
+ cxWidth,
+ cyHeight,
+ istepIfAniCur,
+ hbrFlickerFreeDraw,
+ diFlags);
+
+ UserDereferenceObject(pIcon);
+
+ UserLeave();
+ return Ret;
+}
+
--- /dev/null
- VOID FASTCALL
- IntGetDesktopWorkArea(PDESKTOP Desktop, RECTL *Rect)
- {
- RECTL *Ret;
-
- ASSERT(Desktop);
-
- Ret = &Desktop->WorkArea;
- if((Ret->right == -1) && ScreenDeviceContext)
- {
- PDC dc;
- SURFACE *psurf;
- dc = DC_LockDc(ScreenDeviceContext);
- /* FIXME - Handle dc == NULL!!!! */
- psurf = dc->dclevel.pSurface;
- if (psurf)
- {
- Ret->right = psurf->SurfObj.sizlBitmap.cx;
- Ret->bottom = psurf->SurfObj.sizlBitmap.cy;
- }
- DC_UnlockDc(dc);
- }
-
- if(Rect)
- {
- *Rect = *Ret;
- }
- }
-
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Desktops
+ * FILE: subsystems/win32/win32k/ntuser/desktop.c
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISION HISTORY:
+ * 06-06-2001 CSH Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+#define TRACE DPRINT
+#define WARN DPRINT1
+#define ERR DPRINT1
+
+static
+VOID
+IntFreeDesktopHeap(
+ IN OUT PDESKTOP Desktop
+);
+
+/* GLOBALS *******************************************************************/
+
+/* Currently active desktop */
+PDESKTOP InputDesktop = NULL;
+HDESK InputDesktopHandle = NULL;
+HDC ScreenDeviceContext = NULL;
+BOOL g_PaintDesktopVersion = FALSE;
+
+GENERIC_MAPPING IntDesktopMapping =
+{
+ STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE |
+ DESKTOP_READOBJECTS,
+ STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU |
+ DESKTOP_CREATEWINDOW |
+ DESKTOP_HOOKCONTROL |
+ DESKTOP_JOURNALPLAYBACK |
+ DESKTOP_JOURNALRECORD |
+ DESKTOP_WRITEOBJECTS,
+ STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
+ STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU |
+ DESKTOP_CREATEWINDOW |
+ DESKTOP_ENUMERATE |
+ DESKTOP_HOOKCONTROL |
+ DESKTOP_JOURNALPLAYBACK |
+ DESKTOP_JOURNALRECORD |
+ DESKTOP_READOBJECTS |
+ DESKTOP_SWITCHDESKTOP |
+ DESKTOP_WRITEOBJECTS
+};
+
+/* OBJECT CALLBACKS **********************************************************/
+
+NTSTATUS
+APIENTRY
+IntDesktopObjectParse(IN PVOID ParseObject,
+ IN PVOID ObjectType,
+ IN OUT PACCESS_STATE AccessState,
+ IN KPROCESSOR_MODE AccessMode,
+ IN ULONG Attributes,
+ IN OUT PUNICODE_STRING CompleteName,
+ IN OUT PUNICODE_STRING RemainingName,
+ IN OUT PVOID Context OPTIONAL,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
+ OUT PVOID *Object)
+{
+ NTSTATUS Status;
+ PDESKTOP Desktop;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PLIST_ENTRY NextEntry, ListHead;
+ PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
+ PUNICODE_STRING DesktopName;
+
+ /* Set the list pointers and loop the window station */
+ ListHead = &WinStaObject->DesktopListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current desktop */
+ Desktop = CONTAINING_RECORD(NextEntry, DESKTOP, ListEntry);
+
+ /* Get its name */
+ DesktopName = GET_DESKTOP_NAME(Desktop);
+ if (DesktopName)
+ {
+ /* Compare the name */
+ if (RtlEqualUnicodeString(RemainingName,
+ DesktopName,
+ (Attributes & OBJ_CASE_INSENSITIVE)))
+ {
+ /* We found a match. Did this come from a create? */
+ if (Context)
+ {
+ /* Unless OPEN_IF was given, fail with an error */
+ if (!(Attributes & OBJ_OPENIF))
+ {
+ /* Name collision */
+ return STATUS_OBJECT_NAME_COLLISION;
+ }
+ else
+ {
+ /* Otherwise, return with a warning only */
+ Status = STATUS_OBJECT_NAME_EXISTS;
+ }
+ }
+ else
+ {
+ /* This was a real open, so this is OK */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Reference the desktop and return it */
+ ObReferenceObject(Desktop);
+ *Object = Desktop;
+ return Status;
+ }
+ }
+
+ /* Go to the next desktop */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* If we got here but this isn't a create, then fail */
+ if (!Context) return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ /* Create the desktop object */
+ InitializeObjectAttributes(&ObjectAttributes, RemainingName, 0, NULL, NULL);
+ Status = ObCreateObject(KernelMode,
+ ExDesktopObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(DESKTOP),
+ 0,
+ 0,
+ (PVOID)&Desktop);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Initialize shell hook window list and set the parent */
+ RtlZeroMemory(Desktop, sizeof(DESKTOP));
+ InitializeListHead(&Desktop->ShellHookWindows);
+ Desktop->rpwinstaParent = (PWINSTATION_OBJECT)ParseObject;
+
+ /* Put the desktop on the window station's list of associated desktops */
+ InsertTailList(&Desktop->rpwinstaParent->DesktopListHead,
+ &Desktop->ListEntry);
+
+ /* Set the desktop object and return success */
+ *Object = Desktop;
+ return STATUS_SUCCESS;
+}
+
+VOID APIENTRY
+IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
+{
+ PDESKTOP Desktop = (PDESKTOP)Parameters->Object;
+
+ DPRINT("Deleting desktop (0x%X)\n", Desktop);
+
+ /* Remove the desktop from the window station's list of associcated desktops */
+ RemoveEntryList(&Desktop->ListEntry);
+
+ IntFreeDesktopHeap(Desktop);
+}
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS
+FASTCALL
+InitDesktopImpl(VOID)
+{
+ /* Set Desktop Object Attributes */
+ ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP);
+ ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FASTCALL
+CleanupDesktopImpl(VOID)
+{
+ return STATUS_SUCCESS;
+}
+
+static int GetSystemVersionString(LPWSTR buffer)
+{
+ RTL_OSVERSIONINFOEXW versionInfo;
+ int len;
+
+ versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+
+ if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
+ return 0;
+
+ if (versionInfo.dwMajorVersion <= 4)
+ len = swprintf(buffer,
+ L"ReactOS Version %d.%d %s Build %d",
+ versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+ else
+ len = swprintf(buffer,
+ L"ReactOS %s (Build %d)",
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+
+ return len;
+}
+
+
+NTSTATUS FASTCALL
+IntParseDesktopPath(PEPROCESS Process,
+ PUNICODE_STRING DesktopPath,
+ HWINSTA *hWinSta,
+ HDESK *hDesktop)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING WinSta, Desktop, FullName;
+ BOOL DesktopPresent = FALSE;
+ BOOL WinStaPresent = FALSE;
+ NTSTATUS Status;
+
+ ASSERT(hWinSta);
+
+ *hWinSta = NULL;
+
+ if(hDesktop != NULL)
+ {
+ *hDesktop = NULL;
+ }
+
+ RtlInitUnicodeString(&WinSta, NULL);
+ RtlInitUnicodeString(&Desktop, NULL);
+
+ if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
+ {
+ PWCHAR c = DesktopPath->Buffer;
+ USHORT wl = 0;
+ USHORT l = DesktopPath->Length;
+
+ /*
+ * Parse the desktop path string which can be in the form "WinSta\Desktop"
+ * or just "Desktop". In latter case WinSta0 will be used.
+ */
+
+ while(l > 0)
+ {
+ if(*c == L'\\')
+ {
+ wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
+ break;
+ }
+ l -= sizeof(WCHAR);
+ c++;
+ }
+
+ if(wl > 0)
+ {
+ WinSta.Length = wl;
+ WinSta.MaximumLength = wl + sizeof(WCHAR);
+ WinSta.Buffer = DesktopPath->Buffer;
+
+ WinStaPresent = TRUE;
+ c++;
+ }
+
+ Desktop.Length = DesktopPath->Length - wl;
+ if(wl > 0)
+ {
+ Desktop.Length -= sizeof(WCHAR);
+ }
+ if(Desktop.Length > 0)
+ {
+ Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
+ Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
+ DesktopPresent = TRUE;
+ }
+ }
+
+ if(!WinStaPresent)
+ {
+#if 0
+ /* search the process handle table for (inherited) window station
+ handles, use a more appropriate one than WinSta0 if possible. */
+ if (!ObFindHandleForObject(Process,
+ NULL,
+ ExWindowStationObjectType,
+ NULL,
+ (PHANDLE)hWinSta))
+#endif
+ {
+ /* we had no luck searching for opened handles, use WinSta0 now */
+ RtlInitUnicodeString(&WinSta, L"WinSta0");
+ }
+ }
+
+ if(!DesktopPresent && hDesktop != NULL)
+ {
+#if 0
+ /* search the process handle table for (inherited) desktop
+ handles, use a more appropriate one than Default if possible. */
+ if (!ObFindHandleForObject(Process,
+ NULL,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)hDesktop))
+#endif
+ {
+ /* we had no luck searching for opened handles, use Desktop now */
+ RtlInitUnicodeString(&Desktop, L"Default");
+ }
+ }
+
+ if(*hWinSta == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the window station */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExWindowStationObjectType,
+ KernelMode,
+ NULL,
+ 0,
+ NULL,
+ (HANDLE*)hWinSta);
+
+ ExFreePoolWithTag(FullName.Buffer, TAG_STRING);
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ if(hDesktop != NULL && *hDesktop == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
+ {
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the desktop object */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ 0,
+ NULL,
+ (HANDLE*)hDesktop);
+
+ ExFreePoolWithTag(FullName.Buffer, TAG_STRING);
+
+ if(!NT_SUCCESS(Status))
+ {
+ *hDesktop = NULL;
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ SetLastNtError(Status);
+ DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * IntValidateDesktopHandle
+ *
+ * Validates the desktop handle.
+ *
+ * Remarks
+ * If the function succeeds, the handle remains referenced. If the
+ * fucntion fails, last error is set.
+ */
+
+NTSTATUS FASTCALL
+IntValidateDesktopHandle(
+ HDESK Desktop,
+ KPROCESSOR_MODE AccessMode,
+ ACCESS_MASK DesiredAccess,
+ PDESKTOP *Object)
+{
+ NTSTATUS Status;
+
+ Status = ObReferenceObjectByHandle(
+ Desktop,
+ DesiredAccess,
+ ExDesktopObjectType,
+ AccessMode,
+ (PVOID*)Object,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ SetLastNtError(Status);
+
+ return Status;
+}
+
- UNICODE_STRING ClassName, WindowName, MenuName;
+PDESKTOP FASTCALL
+IntGetActiveDesktop(VOID)
+{
+ return InputDesktop;
+}
+
+/*
+ * returns or creates a handle to the desktop object
+ */
+HDESK FASTCALL
+IntGetDesktopObjectHandle(PDESKTOP DesktopObject)
+{
+ NTSTATUS Status;
+ HDESK Ret;
+
+ ASSERT(DesktopObject);
+
+ if (!ObFindHandleForObject(PsGetCurrentProcess(),
+ DesktopObject,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)&Ret))
+ {
+ Status = ObOpenObjectByPointer(DesktopObject,
+ 0,
+ NULL,
+ 0,
+ ExDesktopObjectType,
+ UserMode,
+ (PHANDLE)&Ret);
+ if(!NT_SUCCESS(Status))
+ {
+ /* unable to create a handle */
+ DPRINT1("Unable to create a desktop handle\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ DPRINT1("Got handle: %lx\n", Ret);
+ }
+
+ return Ret;
+}
+
+PUSER_MESSAGE_QUEUE FASTCALL
+IntGetFocusMessageQueue(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return(NULL);
+ }
+ return (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
+}
+
+VOID FASTCALL
+IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
+{
+ PUSER_MESSAGE_QUEUE Old;
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return;
+ }
+ if(NewQueue != NULL)
+ {
+ if(NewQueue->Desktop != NULL)
+ {
+ DPRINT("Message Queue already attached to another desktop!\n");
+ return;
+ }
+ IntReferenceMessageQueue(NewQueue);
+ (void)InterlockedExchangePointer((PVOID*)&NewQueue->Desktop, pdo);
+ }
+ Old = (PUSER_MESSAGE_QUEUE)InterlockedExchangePointer((PVOID*)&pdo->ActiveMessageQueue, NewQueue);
+ if(Old != NULL)
+ {
+ (void)InterlockedExchangePointer((PVOID*)&Old->Desktop, 0);
+ IntDereferenceMessageQueue(Old);
+ }
+}
+
+HWND FASTCALL IntGetDesktopWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+ return pdo->DesktopWindow;
+}
+
+PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+
+ return UserGetWindowObject(pdo->DesktopWindow);
+}
+
+HWND FASTCALL IntGetMessageWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+ return pdo->spwndMessage->head.h;
+}
+
+HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP pdo = pti->rpdesk;
+ if (NULL == pdo)
+ {
+ DPRINT1("Thread doesn't have a desktop\n");
+ return NULL;
+ }
+ return pdo->DesktopWindow;
+}
+
+BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
+{
+ if (bEnable)
+ {
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].Name = L"PaintDesktopVersion";
+ QueryTable[0].EntryContext = &g_PaintDesktopVersion;
+
+ /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
+ L"Control Panel\\Desktop",
+ QueryTable, NULL, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
+ Status);
+ g_PaintDesktopVersion = FALSE;
+ return FALSE;
+ }
+
+ DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);
+
+ return TRUE;
+ }
+ else
+ {
+ g_PaintDesktopVersion = FALSE;
+ return TRUE;
+ }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+HDC FASTCALL
+UserGetDesktopDC(ULONG DcType, BOOL EmptyDC, BOOL ValidatehWnd)
+{
+ PWINDOW_OBJECT DesktopObject = 0;
+ HDC DesktopHDC = 0;
+
+ if (DcType == DC_TYPE_DIRECT)
+ {
+ DesktopObject = UserGetDesktopWindow();
+ DesktopHDC = (HDC)UserGetWindowDC(DesktopObject);
+ }
+ else
+ {
+ HDEV hDev;
+ hDev = (HDEV)pPrimarySurface;
+ DesktopHDC = IntGdiCreateDisplayDC(hDev, DcType, EmptyDC);
+ }
+
+ return DesktopHDC;
+}
+
+VOID APIENTRY
+UserRedrawDesktop()
+{
+ PWINDOW_OBJECT Window = NULL;
+
+ Window = UserGetDesktopWindow();
+
+ IntInvalidateWindows( Window,
+ Window->hrgnUpdate,
+ RDW_FRAME |
+ RDW_ERASE |
+ RDW_INVALIDATE |
+ RDW_ALLCHILDREN);
+}
+
+
+NTSTATUS FASTCALL
+co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height)
+{
+ CSR_API_MESSAGE Request;
+
+ Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
+ Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+ Request.Data.ShowDesktopRequest.Width = Width;
+ Request.Data.ShowDesktopRequest.Height = Height;
+
+ return co_CsrNotify(&Request);
+}
+
+NTSTATUS FASTCALL
+IntHideDesktop(PDESKTOP Desktop)
+{
+#if 0
+ CSRSS_API_REQUEST Request;
+ CSRSS_API_REPLY Reply;
+
+ Request.Type = CSRSS_HIDE_DESKTOP;
+ Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+
+ return NotifyCsrss(&Request, &Reply);
+#else
+
+ PWINDOW_OBJECT DesktopWindow;
+ PWND DesktopWnd;
+
+ DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
+ if (! DesktopWindow)
+ {
+ return ERROR_INVALID_WINDOW_HANDLE;
+ }
+ DesktopWnd = DesktopWindow->Wnd;
+ DesktopWnd->style &= ~WS_VISIBLE;
+
+ return STATUS_SUCCESS;
+#endif
+}
+
+
+
+
+static
+HWND* FASTCALL
+UserBuildShellHookHwndList(PDESKTOP Desktop)
+{
+ ULONG entries=0;
+ PSHELL_HOOK_WINDOW Current;
+ HWND* list;
+
+ /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ entries++;
+
+ if (!entries) return NULL;
+
+ list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
+ if (list)
+ {
+ HWND* cursor = list;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ *cursor++ = Current->hWnd;
+
+ *cursor = NULL; /* nullterm list */
+ }
+
+ return list;
+}
+
+/*
+ * Send the Message to the windows registered for ShellHook
+ * notifications. The lParam contents depend on the Message. See
+ * MSDN for more details (RegisterShellHookWindow)
+ */
+VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
+{
+ PDESKTOP Desktop = IntGetActiveDesktop();
+ HWND* HwndList;
+
+ static UINT MsgType = 0;
+
+ if (!MsgType)
+ {
+
+ /* Too bad, this doesn't work.*/
+#if 0
+ UNICODE_STRING Str;
+ RtlInitUnicodeString(&Str, L"SHELLHOOK");
+ MsgType = UserRegisterWindowMessage(&Str);
+#endif
+
+ MsgType = IntAddAtom(L"SHELLHOOK");
+
+ DPRINT("MsgType = %x\n", MsgType);
+ if (!MsgType)
+ DPRINT1("LastError: %x\n", GetLastNtError());
+ }
+
+ if (!Desktop)
+ {
+ DPRINT("IntShellHookNotify: No desktop!\n");
+ return;
+ }
+
+ HwndList = UserBuildShellHookHwndList(Desktop);
+ if (HwndList)
+ {
+ HWND* cursor = HwndList;
+
+ for (; *cursor; cursor++)
+ {
+ DPRINT("Sending notify\n");
+ co_IntPostOrSendMessage(*cursor,
+ MsgType,
+ Message,
+ lParam);
+ }
+
+ ExFreePool(HwndList);
+ }
+
+}
+
+/*
+ * Add the window to the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ *
+ * TODO: Validate the window? I'm not sure if sending these messages to
+ * an unsuspecting application that is not your own is a nice thing to do.
+ */
+BOOL IntRegisterShellHookWindow(HWND hWnd)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP Desktop = pti->rpdesk;
+ PSHELL_HOOK_WINDOW Entry;
+
+ DPRINT("IntRegisterShellHookWindow\n");
+
+ /* First deregister the window, so we can be sure it's never twice in the
+ * list.
+ */
+ IntDeRegisterShellHookWindow(hWnd);
+
+ Entry = ExAllocatePoolWithTag(PagedPool,
+ sizeof(SHELL_HOOK_WINDOW),
+ TAG_WINSTA);
+
+ if (!Entry)
+ return FALSE;
+
+ Entry->hWnd = hWnd;
+
+ InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
+
+ return TRUE;
+}
+
+/*
+ * Remove the window from the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ */
+BOOL IntDeRegisterShellHookWindow(HWND hWnd)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP Desktop = pti->rpdesk;
+ PSHELL_HOOK_WINDOW Current;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ {
+ if (Current->hWnd == hWnd)
+ {
+ RemoveEntryList(&Current->ListEntry);
+ ExFreePool(Current);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static VOID
+IntFreeDesktopHeap(IN OUT PDESKTOP Desktop)
+{
+ if (Desktop->hsectionDesktop != NULL)
+ {
+ ObDereferenceObject(Desktop->hsectionDesktop);
+ Desktop->hsectionDesktop = NULL;
+ }
+}
+/* SYSCALLS *******************************************************************/
+
+/*
+ * NtUserCreateDesktop
+ *
+ * Creates a new desktop.
+ *
+ * Parameters
+ * poaAttribs
+ * Object Attributes.
+ *
+ * lpszDesktopDevice
+ * Name of the device.
+ *
+ * pDeviceMode
+ * Device Mode.
+ *
+ * dwFlags
+ * Interaction flags.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ *
+ * Return Value
+ * If the function succeeds, the return value is a handle to the newly
+ * created desktop. If the specified desktop already exists, the function
+ * succeeds and returns a handle to the existing desktop. When you are
+ * finished using the handle, call the CloseDesktop function to close it.
+ * If the function fails, the return value is NULL.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserCreateDesktop(
+ POBJECT_ATTRIBUTES poa,
+ PUNICODE_STRING lpszDesktopDevice,
+ LPDEVMODEW lpdmw,
+ DWORD dwFlags,
+ ACCESS_MASK dwDesiredAccess)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PTHREADINFO W32Thread;
+ PWINSTATION_OBJECT WinStaObject;
+ PDESKTOP DesktopObject;
+ UNICODE_STRING DesktopName;
+ NTSTATUS Status = STATUS_SUCCESS;
+ HDESK Desktop;
+ CSR_API_MESSAGE Request;
+ PVOID DesktopHeapSystemBase = NULL;
+ SIZE_T DesktopInfoSize;
+ UNICODE_STRING SafeDesktopName;
+ ULONG DummyContext;
+ ULONG_PTR HeapSize = 4 * 1024 * 1024; /* FIXME */
+ HWINSTA hWindowStation = NULL ;
+ PUNICODE_STRING lpszDesktopName = NULL;
- // init desktop area
- DesktopObject->WorkArea.left = 0;
- DesktopObject->WorkArea.top = 0;
- DesktopObject->WorkArea.right = -1;
- DesktopObject->WorkArea.bottom = -1;
- IntGetDesktopWorkArea(DesktopObject, NULL);
-
++ UNICODE_STRING ClassName, MenuName;
++ LARGE_STRING WindowName;
+ PWND pWnd = NULL;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
+
+ _SEH2_TRY
+ {
+ ProbeForRead( poa,
+ sizeof(OBJECT_ATTRIBUTES),
+ 1);
+
+ hWindowStation = poa->RootDirectory;
+ lpszDesktopName = poa->ObjectName;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status =_SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed reading Object Attributes from user space.\n");
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Status = IntValidateWindowStationHandle(
+ hWindowStation,
+ KernelMode,
+ 0, /* FIXME - WINSTA_CREATEDESKTOP */
+ &WinStaObject);
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
+ hWindowStation, lpszDesktopName);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ if(lpszDesktopName != NULL)
+ {
+ Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&SafeDesktopName, NULL);
+ }
+
+ if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+ &SafeDesktopName))
+ {
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ ObDereferenceObject(WinStaObject);
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ RETURN( NULL);
+ }
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ ObDereferenceObject(WinStaObject);
+
+ /*
+ * Try to open already existing desktop
+ */
+
+ DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
+
+ /* Initialize ObjectAttributes for the desktop object */
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DesktopName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ dwDesiredAccess,
+ (PVOID)&DummyContext,
+ (HANDLE*)&Desktop);
+ if (!NT_SUCCESS(Status)) RETURN(NULL);
+ if (Status == STATUS_OBJECT_NAME_EXISTS)
+ {
+ ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
+ RETURN( Desktop);
+ }
+
+ /* Reference the desktop */
+ Status = ObReferenceObjectByHandle(Desktop,
+ 0,
+ ExDesktopObjectType,
+ KernelMode,
+ (PVOID)&DesktopObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) RETURN(NULL);
+
+ DesktopObject->hsectionDesktop = NULL;
+ DesktopObject->pheapDesktop = UserCreateHeap(&DesktopObject->hsectionDesktop,
+ &DesktopHeapSystemBase,
+ HeapSize);
+ if (DesktopObject->pheapDesktop == NULL)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Failed to create desktop heap!\n");
+ RETURN(NULL);
+ }
+
+ DesktopInfoSize = FIELD_OFFSET(DESKTOPINFO,
+ szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);
+
+ DesktopObject->pDeskInfo = RtlAllocateHeap(DesktopObject->pheapDesktop,
+ HEAP_NO_SERIALIZE,
+ DesktopInfoSize);
+
+ if (DesktopObject->pDeskInfo == NULL)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Failed to create the DESKTOP structure!\n");
+ RETURN(NULL);
+ }
+
+ RtlZeroMemory(DesktopObject->pDeskInfo,
+ DesktopInfoSize);
+
+ DesktopObject->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
+ DesktopObject->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
+ RtlCopyMemory(DesktopObject->pDeskInfo->szDesktopName,
+ lpszDesktopName->Buffer,
+ lpszDesktopName->Length);
+
+ /* Initialize some local (to win32k) desktop state. */
+ InitializeListHead(&DesktopObject->PtiList);
+ DesktopObject->ActiveMessageQueue = NULL;
+ ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create desktop handle\n");
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ /*
+ * Create a handle for CSRSS and notify CSRSS for Creating Desktop Window.
+ *
+ * Honestly, I believe this is a cleverly written hack that allowed ReactOS
+ * to function at the beginning of the project by ramroding the GUI into
+ * operation and making the desktop window work from user space.
+ * (jt)
+ */
+ Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
+ Status = CsrInsertObject(Desktop,
+ GENERIC_ALL,
+ (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create desktop handle for CSRSS\n");
+ ZwClose(Desktop);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Status = co_CsrNotify(&Request);
+ if (! NT_SUCCESS(Status))
+ {
+ CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
+ DPRINT1("Failed to notify CSRSS about new desktop\n");
+ ZwClose(Desktop);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ W32Thread = PsGetCurrentThreadWin32Thread();
+
+ if (!W32Thread->rpdesk) IntSetThreadDesktop(DesktopObject,FALSE);
+
+ /*
+ Based on wine/server/window.c in get_desktop_window.
+ */
+
+ ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE])));
+ ClassName.Length = 0;
+ RtlZeroMemory(&MenuName, sizeof(MenuName));
+ RtlZeroMemory(&WindowName, sizeof(WindowName));
+
+ pWnd = co_IntCreateWindowEx( 0,
+ &ClassName,
+ &WindowName,
+ (WS_POPUP|WS_CLIPCHILDREN),
+ 0,
+ 0,
+ 100,
+ 100,
+ NULL,
+ NULL,
+ hModClient,
+ NULL,
+ 0,
+ TRUE);
+ if (!pWnd)
+ {
+ DPRINT1("Failed to create Message window handle\n");
+ }
+ else
+ {
+ DesktopObject->spwndMessage = pWnd;
+ }
+
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserOpenDesktop
+ *
+ * Opens an existing desktop.
+ *
+ * Parameters
+ * lpszDesktopName
+ * Name of the existing desktop.
+ *
+ * dwFlags
+ * Interaction flags.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ * Return Value
+ * Handle to the desktop or zero on failure.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserOpenDesktop(
+ PUNICODE_STRING lpszDesktopName,
+ DWORD dwFlags,
+ ACCESS_MASK dwDesiredAccess)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HWINSTA WinSta;
+ PWINSTATION_OBJECT WinStaObject;
+ UNICODE_STRING DesktopName;
+ UNICODE_STRING SafeDesktopName;
+ NTSTATUS Status;
+ HDESK Desktop;
+ BOOL Result;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
+
+ /*
+ * Validate the window station handle and compose the fully
+ * qualified desktop name
+ */
+
+ WinSta = UserGetProcessWindowStation();
+ Status = IntValidateWindowStationHandle(
+ WinSta,
+ KernelMode,
+ 0,
+ &WinStaObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta);
+ SetLastNtError(Status);
+ RETURN( 0);
+ }
+
+ if(lpszDesktopName != NULL)
+ {
+ Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&SafeDesktopName, NULL);
+ }
+
+ Result = IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+ &SafeDesktopName);
+
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ ObDereferenceObject(WinStaObject);
+
+
+ if (!Result)
+ {
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ RETURN( 0);
+ }
+
+
+ DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
+
+ /* Initialize ObjectAttributes for the desktop object */
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DesktopName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (HANDLE*)&Desktop);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ ExFreePool(DesktopName.Buffer);
+ RETURN( 0);
+ }
+
+ DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
+ ExFreePool(DesktopName.Buffer);
+
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserOpenInputDesktop
+ *
+ * Opens the input (interactive) desktop.
+ *
+ * Parameters
+ * dwFlags
+ * Interaction flags.
+ *
+ * fInherit
+ * Inheritance option.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ * Return Value
+ * Handle to the input desktop or zero on failure.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserOpenInputDesktop(
+ DWORD dwFlags,
+ BOOL fInherit,
+ ACCESS_MASK dwDesiredAccess)
+{
+ PDESKTOP Object;
+ NTSTATUS Status;
+ HDESK Desktop;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenInputDesktop\n");
+ UserEnterExclusive();
+
+ DPRINT("About to open input desktop\n");
+
+ /* Get a pointer to the desktop object */
+
+ Status = IntValidateDesktopHandle(
+ InputDesktopHandle,
+ UserMode,
+ 0,
+ &Object);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
+ RETURN((HDESK)0);
+ }
+
+ /* Create a new handle to the object */
+
+ Status = ObOpenObjectByPointer(
+ Object,
+ 0,
+ NULL,
+ dwDesiredAccess,
+ ExDesktopObjectType,
+ UserMode,
+ (HANDLE*)&Desktop);
+
+ ObDereferenceObject(Object);
+
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("Successfully opened input desktop\n");
+ RETURN((HDESK)Desktop);
+ }
+
+ SetLastNtError(Status);
+ RETURN((HDESK)0);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserCloseDesktop
+ *
+ * Closes a desktop handle.
+ *
+ * Parameters
+ * hDesktop
+ * Handle to the desktop.
+ *
+ * Return Value
+ * Status
+ *
+ * Remarks
+ * The desktop handle can be created with NtUserCreateDesktop or
+ * NtUserOpenDesktop. This function will fail if any thread in the calling
+ * process is using the specified desktop handle or if the handle refers
+ * to the initial desktop of the calling process.
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserCloseDesktop(HDESK hDesktop)
+{
+ PDESKTOP Object;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCloseDesktop\n");
+ UserEnterExclusive();
+
+ DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
+
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &Object);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ ObDereferenceObject(Object);
+
+ DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
+
+ Status = ZwClose(hDesktop);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+
+
+/*
+ * NtUserPaintDesktop
+ *
+ * The NtUserPaintDesktop function fills the clipping region in the
+ * specified device context with the desktop pattern or wallpaper. The
+ * function is provided primarily for shell desktops.
+ *
+ * Parameters
+ * hDC
+ * Handle to the device context.
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserPaintDesktop(HDC hDC)
+{
+ RECTL Rect;
+ HBRUSH DesktopBrush, PreviousBrush;
+ HWND hWndDesktop;
+ BOOL doPatBlt = TRUE;
+ PWINDOW_OBJECT WndDesktop;
+ int len;
+ COLORREF color_old;
+ UINT align_old;
+ int mode_old;
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PWINSTATION_OBJECT WinSta = pti->rpdesk->rpwinstaParent;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserPaintDesktop\n");
+
+ GdiGetClipBox(hDC, &Rect);
+
+ hWndDesktop = IntGetDesktopWindow();
+
+ WndDesktop = UserGetWindowObject(hWndDesktop);
+ if (!WndDesktop)
+ {
+ RETURN(FALSE);
+ }
+
+ DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Wnd->pcls, GCL_HBRBACKGROUND, FALSE);
+
+
+ /*
+ * Paint desktop background
+ */
+
+ if (WinSta->hbmWallpaper != NULL)
+ {
+ PWINDOW_OBJECT DeskWin;
+
+ DeskWin = UserGetWindowObject(hWndDesktop);
+
+ if (DeskWin)
+ {
+ SIZE sz;
+ int x, y;
+ HDC hWallpaperDC;
+
+ sz.cx = DeskWin->Wnd->rcWindow.right - DeskWin->Wnd->rcWindow.left;
+ sz.cy = DeskWin->Wnd->rcWindow.bottom - DeskWin->Wnd->rcWindow.top;
+
+ if (WinSta->WallpaperMode == wmStretch ||
+ WinSta->WallpaperMode == wmTile)
+ {
+ x = 0;
+ y = 0;
+ }
+ else
+ {
+ /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */
+ x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
+ y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
+ }
+
+ hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
+ if(hWallpaperDC != NULL)
+ {
+ HBITMAP hOldBitmap;
+
+ /* fill in the area that the bitmap is not going to cover */
+ if (x > 0 || y > 0)
+ {
+ /* FIXME - clip out the bitmap
+ can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);"
+ once we support DSTINVERT */
+ PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectBrush(hDC, PreviousBrush);
+ }
+
+ /*Do not fill the background after it is painted no matter the size of the picture */
+ doPatBlt = FALSE;
+
+ hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, WinSta->hbmWallpaper);
+
+ if (WinSta->WallpaperMode == wmStretch)
+ {
+ if(Rect.right && Rect.bottom)
+ NtGdiStretchBlt(hDC,
+ x,
+ y,
+ sz.cx,
+ sz.cy,
+ hWallpaperDC,
+ 0,
+ 0,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ SRCCOPY,
+ 0);
+
+ }
+ else if (WinSta->WallpaperMode == wmTile)
+ {
+ /* paint the bitmap across the screen then down */
+ for(y = 0; y < Rect.bottom; y += WinSta->cyWallpaper)
+ {
+ for(x = 0; x < Rect.right; x += WinSta->cxWallpaper)
+ {
+ NtGdiBitBlt(hDC,
+ x,
+ y,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ hWallpaperDC,
+ 0,
+ 0,
+ SRCCOPY,
+ 0,
+ 0);
+ }
+ }
+ }
+ else
+ {
+ NtGdiBitBlt(hDC,
+ x,
+ y,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ hWallpaperDC,
+ 0,
+ 0,
+ SRCCOPY,
+ 0,
+ 0);
+ }
+ NtGdiSelectBitmap(hWallpaperDC, hOldBitmap);
+ NtGdiDeleteObjectApp(hWallpaperDC);
+ }
+ }
+ }
+
+ /* Back ground is set to none, clear the screen */
+ if (doPatBlt)
+ {
+ PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectBrush(hDC, PreviousBrush);
+ }
+
+ /*
+ * Display system version on the desktop background
+ */
+
+ if (g_PaintDesktopVersion)
+ {
+ static WCHAR s_wszVersion[256] = {0};
+ RECTL rect;
+
+ if (*s_wszVersion)
+ {
+ len = wcslen(s_wszVersion);
+ }
+ else
+ {
+ len = GetSystemVersionString(s_wszVersion);
+ }
+
+ if (len)
+ {
+ if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
+ {
+ rect.right = UserGetSystemMetrics(SM_CXSCREEN);
+ rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+ }
+
+ color_old = IntGdiSetTextColor(hDC, RGB(255,255,255));
+ align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
+ mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
+
+ GreExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0);
+
+ IntGdiSetBkMode(hDC, mode_old);
+ IntGdiSetTextAlign(hDC, align_old);
+ IntGdiSetTextColor(hDC, color_old);
+ }
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * NtUserSwitchDesktop
+ *
+ * Sets the current input (interactive) desktop.
+ *
+ * Parameters
+ * hDesktop
+ * Handle to desktop.
+ *
+ * Return Value
+ * Status
+ *
+ * Status
+ * @unimplemented
+ */
+
+BOOL APIENTRY
+NtUserSwitchDesktop(HDESK hDesktop)
+{
+ PDESKTOP DesktopObject;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSwitchDesktop\n");
+
+ DPRINT("About to switch desktop (0x%X)\n", hDesktop);
+
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /*
+ * Don't allow applications switch the desktop if it's locked, unless the caller
+ * is the logon application itself
+ */
+ if((DesktopObject->rpwinstaParent->Flags & WSS_LOCKED) &&
+ LogonProcess != NULL && LogonProcess != PsGetCurrentProcessWin32Process())
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ if(DesktopObject->rpwinstaParent != InputWindowStation)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Switching desktop 0x%x denied because desktop doesn't belong to the interactive winsta!\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /* FIXME: Fail if the process is associated with a secured
+ desktop such as Winlogon or Screen-Saver */
+ /* FIXME: Connect to input device */
+
+ /* Set the active desktop in the desktop's window station. */
+ InputWindowStation->ActiveDesktop = DesktopObject;
+
+ /* Set the global state. */
+ InputDesktop = DesktopObject;
+ InputDesktopHandle = hDesktop;
+
+ ObDereferenceObject(DesktopObject);
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserResolveDesktopForWOW
+ *
+ * Status
+ * @unimplemented
+ */
+
+DWORD APIENTRY
+NtUserResolveDesktopForWOW(DWORD Unknown0)
+{
+ UNIMPLEMENTED
+ return 0;
+}
+
+/*
+ * NtUserGetThreadDesktop
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
+{
+ NTSTATUS Status;
+ PETHREAD Thread;
+ PDESKTOP DesktopObject;
+ HDESK Ret, hThreadDesktop;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+ DECLARE_RETURN(HDESK);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserGetThreadDesktop\n");
+
+ if(!dwThreadId)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ if(Thread->ThreadsProcess == PsGetCurrentProcess())
+ {
+ /* just return the handle, we queried the desktop handle of a thread running
+ in the same context */
+ Ret = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk;
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+ }
+
+ /* get the desktop handle and the desktop of the thread */
+ if(!(hThreadDesktop = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk) ||
+ !(DesktopObject = ((PTHREADINFO)Thread->Tcb.Win32Thread)->rpdesk))
+ {
+ ObDereferenceObject(Thread);
+ DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
+ RETURN(NULL);
+ }
+
+ /* we could just use DesktopObject instead of looking up the handle, but latter
+ may be a bit safer (e.g. when the desktop is being destroyed */
+ /* switch into the context of the thread we're trying to get the desktop from,
+ so we can use the handle */
+ KeAttachProcess(&Thread->ThreadsProcess->Pcb);
+ Status = ObReferenceObjectByHandle(hThreadDesktop,
+ GENERIC_ALL,
+ ExDesktopObjectType,
+ UserMode,
+ (PVOID*)&DesktopObject,
+ &HandleInformation);
+ KeDetachProcess();
+
+ /* the handle couldn't be found, there's nothing to get... */
+ if(!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Thread);
+ RETURN(NULL);
+ }
+
+ /* lookup our handle table if we can find a handle to the desktop object,
+ if not, create one */
+ Ret = IntGetDesktopObjectHandle(DesktopObject);
+
+ /* all done, we got a valid handle to the desktop */
+ ObDereferenceObject(DesktopObject);
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+static NTSTATUS
+IntUnmapDesktopView(IN PDESKTOP DesktopObject)
+{
+ PTHREADINFO ti;
+ PPROCESSINFO CurrentWin32Process;
+ PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("DO %p\n");
+
+ CurrentWin32Process = PsGetCurrentProcessWin32Process();
+ PrevLink = &CurrentWin32Process->HeapMappings.Next;
+
+ /* unmap if we're the last thread using the desktop */
+ HeapMapping = *PrevLink;
+ while (HeapMapping != NULL)
+ {
+ if (HeapMapping->KernelMapping == (PVOID)DesktopObject->pheapDesktop)
+ {
+ if (--HeapMapping->Count == 0)
+ {
+ *PrevLink = HeapMapping->Next;
+
+ Status = MmUnmapViewOfSection(PsGetCurrentProcess(),
+ HeapMapping->UserMapping);
+
+ ObDereferenceObject(DesktopObject);
+
+ UserHeapFree(HeapMapping);
+ break;
+ }
+ }
+
+ PrevLink = &HeapMapping->Next;
+ HeapMapping = HeapMapping->Next;
+ }
+
+ ti = GetW32ThreadInfo();
+ if (ti != NULL)
+ {
+ GetWin32ClientInfo()->pDeskInfo = NULL;
+ }
+ GetWin32ClientInfo()->ulClientDelta = 0;
+
+ return Status;
+}
+
+static NTSTATUS
+IntMapDesktopView(IN PDESKTOP DesktopObject)
+{
+ PTHREADINFO ti;
+ PPROCESSINFO CurrentWin32Process;
+ PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
+ PVOID UserBase = NULL;
+ SIZE_T ViewSize = 0;
+ LARGE_INTEGER Offset;
+ NTSTATUS Status;
+
+ CurrentWin32Process = PsGetCurrentProcessWin32Process();
+ PrevLink = &CurrentWin32Process->HeapMappings.Next;
+
+ /* find out if another thread already mapped the desktop heap */
+ HeapMapping = *PrevLink;
+ while (HeapMapping != NULL)
+ {
+ if (HeapMapping->KernelMapping == (PVOID)DesktopObject->pheapDesktop)
+ {
+ HeapMapping->Count++;
+ return STATUS_SUCCESS;
+ }
+
+ PrevLink = &HeapMapping->Next;
+ HeapMapping = HeapMapping->Next;
+ }
+
+ /* we're the first, map the heap */
+ DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject->pheapDesktop);
+ Offset.QuadPart = 0;
+ Status = MmMapViewOfSection(DesktopObject->hsectionDesktop,
+ PsGetCurrentProcess(),
+ &UserBase,
+ 0,
+ 0,
+ &Offset,
+ &ViewSize,
+ ViewUnmap,
+ SEC_NO_CHANGE,
+ PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to map desktop\n");
+ return Status;
+ }
+
+ /* add the mapping */
+ HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING));
+ if (HeapMapping == NULL)
+ {
+ MmUnmapViewOfSection(PsGetCurrentProcess(),
+ UserBase);
+ DPRINT1("UserHeapAlloc() failed!\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ HeapMapping->Next = NULL;
+ HeapMapping->KernelMapping = (PVOID)DesktopObject->pheapDesktop;
+ HeapMapping->UserMapping = UserBase;
+ HeapMapping->Limit = ViewSize;
+ HeapMapping->Count = 1;
+ *PrevLink = HeapMapping;
+
+ ObReferenceObject(DesktopObject);
+
+ /* create a W32THREADINFO structure if not already done, or update it */
+ ti = GetW32ThreadInfo();
+ GetWin32ClientInfo()->ulClientDelta = DesktopHeapGetUserDelta();
+ if (ti != NULL)
+ {
+ if (GetWin32ClientInfo()->pDeskInfo == NULL)
+ {
+ GetWin32ClientInfo()->pDeskInfo =
+ (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo -
+ GetWin32ClientInfo()->ulClientDelta);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+BOOL
+IntSetThreadDesktop(IN PDESKTOP DesktopObject,
+ IN BOOL FreeOnFailure)
+{
+ PDESKTOP OldDesktop;
+ PTHREADINFO W32Thread;
+ NTSTATUS Status;
+ BOOL MapHeap;
+
+ DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject, FreeOnFailure);
+ MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
+ W32Thread = PsGetCurrentThreadWin32Thread();
+
+ if (W32Thread->rpdesk != DesktopObject)
+ {
+ OldDesktop = W32Thread->rpdesk;
+
+ if (!IsListEmpty(&W32Thread->WindowListHead))
+ {
+ DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
+ SetLastWin32Error(ERROR_BUSY);
+ return FALSE;
+ }
+
+ W32Thread->rpdesk = DesktopObject;
+
+ if (MapHeap && DesktopObject != NULL)
+ {
+ Status = IntMapDesktopView(DesktopObject);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+ }
+
+ /* Hack for system threads */
+ if (NtCurrentTeb())
+ {
+ PCLIENTINFO pci = GetWin32ClientInfo();
+ pci->ulClientDelta = DesktopHeapGetUserDelta();
+ if (DesktopObject)
+ {
+ pci->pDeskInfo = (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo - pci->ulClientDelta);
+ }
+ }
+
+ if (OldDesktop != NULL &&
+ !IntCheckProcessDesktopClasses(OldDesktop,
+ FreeOnFailure))
+ {
+ DPRINT1("Failed to move process classes to shared heap!\n");
+
+ /* failed to move desktop classes to the shared heap,
+ unmap the view and return the error */
+ if (MapHeap && DesktopObject != NULL)
+ IntUnmapDesktopView(DesktopObject);
+
+ return FALSE;
+ }
+
+ /* Remove the thread from the old desktop's list */
+ RemoveEntryList(&W32Thread->PtiLink);
+
+ if (DesktopObject != NULL)
+ {
+ ObReferenceObject(DesktopObject);
+ /* Insert into new desktop's list */
+ InsertTailList(&DesktopObject->PtiList, &W32Thread->PtiLink);
+ }
+
+ if (OldDesktop != NULL)
+ {
+ if (MapHeap)
+ {
+ IntUnmapDesktopView(OldDesktop);
+ }
+
+ ObDereferenceObject(OldDesktop);
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * NtUserSetThreadDesktop
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserSetThreadDesktop(HDESK hDesktop)
+{
+ PDESKTOP DesktopObject;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSetThreadDesktop\n");
+
+ /* Validate the new desktop. */
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /* FIXME: Should check here to see if the thread has any windows. */
+
+ if (!IntSetThreadDesktop(DesktopObject,
+ FALSE))
+ {
+ RETURN(FALSE);
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/* EOF */
--- /dev/null
- /* Restore mouse pointer */
- UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y);
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Video initialization and display settings
+ * FILE: subsystems/win32/win32k/ntuser/display.c
+ * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+#include <win32k.h>
+
+#include <intrin.h>
+
+#define NDEBUG
+#include <debug.h>
+
+PDEVOBJ *gpdevPrimary;
+
+const PWCHAR KEY_ROOT = L"";
+const PWCHAR KEY_VIDEO = L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
+
+NTSTATUS
+NTAPI
+UserEnumDisplayDevices(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ PDISPLAY_DEVICEW pdispdev,
+ DWORD dwFlags);
+
+VOID
+RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
+{
+ UNICODE_STRING ustrValue;
+ UNICODE_STRING ustrData;
+
+ RtlInitUnicodeString(&ustrValue, pwszValue);
+ RtlInitUnicodeString(&ustrData, pwszData);
+ ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
+}
+
+VOID
+RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
+{
+ UNICODE_STRING ustrValue;
+
+ RtlInitUnicodeString(&ustrValue, pwszValue);
+ ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
+}
+
+
+BOOL
+RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
+{
+ NTSTATUS Status;
+ ULONG cbSize = sizeof(DWORD);
+ Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
+ return NT_SUCCESS(Status);
+}
+
+VOID
+RegWriteDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+{
+ RegWriteDWORD(hkey, L"DefaultSettings.BitsPerPel", pdm->dmBitsPerPel);
+ RegWriteDWORD(hkey, L"DefaultSettings.XResolution", pdm->dmPelsWidth);
+ RegWriteDWORD(hkey, L"DefaultSettings.YResolution", pdm->dmPelsHeight);
+ RegWriteDWORD(hkey, L"DefaultSettings.Flags", pdm->dmDisplayFlags);
+ RegWriteDWORD(hkey, L"DefaultSettings.VRefresh", pdm->dmDisplayFrequency);
+ RegWriteDWORD(hkey, L"DefaultSettings.XPanning", pdm->dmPanningWidth);
+ RegWriteDWORD(hkey, L"DefaultSettings.YPanning", pdm->dmPanningHeight);
+ RegWriteDWORD(hkey, L"DefaultSettings.Orientation", pdm->dmDisplayOrientation);
+ RegWriteDWORD(hkey, L"DefaultSettings.FixedOutput", pdm->dmDisplayFixedOutput);
+ RegWriteDWORD(hkey, L"Attach.RelativeX", pdm->dmPosition.x);
+ RegWriteDWORD(hkey, L"Attach.RelativeY", pdm->dmPosition.y);
+// RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
+}
+
+VOID
+RegReadDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+{
+ DWORD dwValue;
+
+ /* Zero out the structure */
+ RtlZeroMemory(pdm, sizeof(DEVMODEW));
+
+/* Helper macro */
+#define READ(field, str, flag) \
+ if (RegReadDWORD(hkey, L##str, &dwValue)) \
+ { \
+ pdm->field = dwValue; \
+ pdm->dmFields |= flag; \
+ }
+
+ /* Read all present settings */
+ READ(dmBitsPerPel, "DefaultSettings.BitsPerPel", DM_BITSPERPEL);
+ READ(dmPelsWidth, "DefaultSettings.XResolution", DM_YRESOLUTION); // DM_XRESOLUTION?
+ READ(dmPelsHeight, "DefaultSettings.YResolution", DM_YRESOLUTION);
+ READ(dmDisplayFlags, "DefaultSettings.Flags", DM_DISPLAYFLAGS);
+ READ(dmDisplayFrequency, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY);
+ READ(dmPanningWidth, "DefaultSettings.XPanning", DM_PANNINGWIDTH);
+ READ(dmPanningHeight, "DefaultSettings.YPanning", DM_PANNINGHEIGHT);
+ READ(dmDisplayOrientation, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION);
+ READ(dmDisplayFixedOutput, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT);
+ READ(dmPosition.x, "Attach.RelativeX", DM_POSITION);
+ READ(dmPosition.y, "Attach.RelativeY", DM_POSITION);
+}
+
+
+enum
+{
+ VF_USEVGA = 0x1,
+};
+
+BOOL
+InitDisplayDriver(
+ PUNICODE_STRING pustrRegPath,
+ FLONG flags)
+{
+// PWSTR pwszDriverName;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ /* Setup QueryTable for direct registry query */
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED|RTL_QUERY_REGISTRY_DIRECT;
+
+
+ /* Check if vga mode is requested */
+ if (flags & VF_USEVGA)
+ {
+ DWORD dwVgaCompatible;
+
+ /* */
+ QueryTable[0].Name = L"VgaCompatible";
+ QueryTable[0].EntryContext = &dwVgaCompatible;
+
+ /* Check if the driver is vga */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ pustrRegPath->Buffer,
+ QueryTable,
+ NULL,
+ NULL);
+
+ if (!dwVgaCompatible)
+ {
+ /* This driver is not a vga driver */
+ return FALSE;
+ }
+ }
+
+#if 0
+
+ /* Query the adapter's registry path */
+ swprintf(awcBuffer, L"\\Device\\Video%lu", iDevNum);
+ QueryTable[0].Name = pGraphicsDevice->szNtDeviceName;
+
+ /* Set string for the registry key */
+ ustrRegistryPath.Buffer = pdispdev->DeviceKey;
+ ustrRegistryPath.Length = 128;
+ ustrRegistryPath.MaximumLength = 128;
+ QueryTable[0].EntryContext = &ustrRegistryPath;
+
+ /* Query the registry */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
+ L"VIDEO",
+ QueryTable,
+ NULL,
+ NULL);
+
+ RegQueryValue(KEY_VIDEO, awcBuffer, REG_SZ, pdispdev->DeviceKey, 256);
+
+ {
+ HANDLE hmod;
+
+ hmod = EngLoadImage(pwszDriverName);
+
+ /* Jump to next name */
+ pwszDriverName += wcslen(pwszDriverName) + 1;
+ }
+ while (pwszDriverName < 0);
+#endif
+
+ return 0;
+}
+
+
+NTSTATUS
+NTAPI
+DisplayDriverQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ PWSTR pwszRegKey = ValueData;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ UNICODE_STRING ustrDeviceName, ustrDisplayDrivers, ustrDescription;
+ NTSTATUS Status;
+ WCHAR awcBuffer[128];
+ ULONG cbSize;
+ HKEY hkey;
+ DEVMODEW dmDefault;
+
+ UNREFERENCED_PARAMETER(ValueLength);
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(EntryContext);
+
+ DPRINT1("DisplayDriverQueryRoutine(%S, %S);\n",
+ ValueName, pwszRegKey);
+
+ /* Check if we have a correct entry */
+ if (ValueType != REG_SZ || ValueName[0] != '\\')
+ {
+ /* Something else, just skip it */
+ return STATUS_SUCCESS;
+ }
+
+ /* Open the driver's registry key */
+ Status = RegOpenKey(pwszRegKey, &hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to open registry key\n");
+ return STATUS_SUCCESS;
+ }
+
+// HACK: only use 1st adapter
+//if (ValueName[13] != '0')
+// return STATUS_SUCCESS;
+
+ /* Query the diplay drivers */
+ cbSize = sizeof(awcBuffer) - 10;
+ Status = RegQueryValue(hkey,
+ L"InstalledDisplayDrivers",
+ REG_MULTI_SZ,
+ awcBuffer,
+ &cbSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status);
+ ZwClose(hkey);
+ return STATUS_SUCCESS;
+ }
+
+ /* Initialize the UNICODE_STRING */
+ ustrDisplayDrivers.Buffer = awcBuffer;
+ ustrDisplayDrivers.MaximumLength = cbSize;
+ ustrDisplayDrivers.Length = cbSize;
+
+ /* Set Buffer for description and size of remaining buffer */
+ ustrDescription.Buffer = awcBuffer + (cbSize / sizeof(WCHAR));
+ cbSize = sizeof(awcBuffer) - cbSize;
+
+ /* Query the device string */
+ Status = RegQueryValue(hkey,
+ L"Device Description",
+ REG_SZ,
+ ustrDescription.Buffer,
+ &cbSize);
+ if (NT_SUCCESS(Status))
+ {
+ ustrDescription.MaximumLength = cbSize;
+ ustrDescription.Length = cbSize;
+ }
+ else
+ {
+ RtlInitUnicodeString(&ustrDescription, L"<unknown>");
+ }
+
+ /* Query the default settings */
+ RegReadDisplaySettings(hkey, &dmDefault);
+
+ /* Close the registry key */
+ ZwClose(hkey);
+
+ /* Register the device with GDI */
+ RtlInitUnicodeString(&ustrDeviceName, ValueName);
+ pGraphicsDevice = EngpRegisterGraphicsDevice(&ustrDeviceName,
+ &ustrDisplayDrivers,
+ &ustrDescription,
+ &dmDefault);
+
+ // FIXME: what to do with pGraphicsDevice?
+
+ return STATUS_SUCCESS;
+}
+
+BOOL InitSysParams();
+
+BOOL
+InitVideo(FLONG flags)
+{
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ DPRINT1("----------------------------- InitVideo() -------------------------------\n");
+
+ /* Setup QueryTable for registry query */
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = DisplayDriverQueryRoutine;
+
+ /* Query the registry */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
+ L"VIDEO",
+ QueryTable,
+ NULL,
+ NULL);
+
+ InitSysParams();
+
+ return 0;
+}
+
+
+NTSTATUS
+NTAPI
+UserEnumDisplayDevices(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ PDISPLAY_DEVICEW pdispdev,
+ DWORD dwFlags)
+{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG cbSize;
+ HKEY hkey;
+ NTSTATUS Status;
+
+ /* Ask gdi for the GRAPHICS_DEVICE */
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, iDevNum, 0);
+ if (!pGraphicsDevice)
+ {
+ /* No device found */
+ DPRINT1("No GRAPHICS_DEVICE found\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Open thhe device map registry key */
+ Status = RegOpenKey(KEY_VIDEO, &hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ /* No device found */
+ DPRINT1("Could not open reg key\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Query the registry path */
+ cbSize = sizeof(pdispdev->DeviceKey);
+ RegQueryValue(hkey,
+ pGraphicsDevice->szNtDeviceName,
+ REG_SZ,
+ pdispdev->DeviceKey,
+ &cbSize);
+
+ /* Close registry key */
+ ZwClose(hkey);
+
+ /* Copy device name, device string and StateFlags */
+ wcsncpy(pdispdev->DeviceName, pGraphicsDevice->szWinDeviceName, 32);
+ wcsncpy(pdispdev->DeviceString, pGraphicsDevice->pwszDescription, 128);
+ pdispdev->StateFlags = pGraphicsDevice->StateFlags;
+
+ // FIXME: fill in DEVICE ID
+
+ return STATUS_SUCCESS;
+}
+
+//NTSTATUS
+BOOL
+NTAPI
+NtUserEnumDisplayDevices(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ PDISPLAY_DEVICEW pDisplayDevice,
+ DWORD dwFlags)
+{
+ UNICODE_STRING ustrDevice;
+ WCHAR awcDevice[CCHDEVICENAME];
+ DISPLAY_DEVICEW dispdev;
+ NTSTATUS Status;
+
+ DPRINT1("Enter NtUserEnumDisplayDevices(%p, %ls, %ld)\n",
+ pustrDevice, pustrDevice ? pustrDevice->Buffer : 0, iDevNum);
+
+ // FIXME: HACK, desk.cpl passes broken crap
+ if (pustrDevice && iDevNum != 0)
+ return FALSE;
+
+ dispdev.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (pustrDevice)
+ {
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
+ _SEH2_TRY
+ {
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+// _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
+ }
+ _SEH2_END
+
+ if (ustrDevice.Length > 0)
+ pustrDevice = &ustrDevice;
+ else
+ pustrDevice = NULL;
+ }
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
+ /* Call the internal function */
+ Status = UserEnumDisplayDevices(pustrDevice, iDevNum, &dispdev, dwFlags);
+
+ /* Release lock */
+ UserLeave();
+
+ /* On success copy data to caller */
+ if (NT_SUCCESS(Status))
+ {
+ /* Enter SEH */
+ _SEH2_TRY
+ {
+ /* First probe the cb field */
+ ProbeForWrite(&pDisplayDevice->cb, sizeof(DWORD), 1);
+
+ /* Check the buffer size */
+ if (pDisplayDevice->cb)
+ {
+ /* Probe the output buffer */
+ pDisplayDevice->cb = min(pDisplayDevice->cb, sizeof(dispdev));
+ ProbeForWrite(pDisplayDevice, pDisplayDevice->cb, 1);
+
+ /* Copy as much as the given buffer allows */
+ RtlCopyMemory(pDisplayDevice, &dispdev, pDisplayDevice->cb);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ }
+
+ DPRINT1("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status);
+ /* Return the result */
+// return Status;
+ return NT_SUCCESS(Status); // FIXME
+}
+
+NTSTATUS
+NTAPI
+UserEnumCurrentDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ PDEVMODEW *ppdm)
+{
+ PPDEVOBJ ppdev;
+
+ /* Get the PDEV for the device */
+ ppdev = EngpGetPDEV(pustrDevice);
+ if (!ppdev)
+ {
+ /* No device found */
+ DPRINT1("No PDEV found!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ *ppdm = ppdev->pdmwDev;
+ PDEVOBJ_vRelease(ppdev);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+UserEnumDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ DWORD iModeNum,
+ LPDEVMODEW *ppdm,
+ DWORD dwFlags)
+{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVMODEENTRY pdmentry;
+ ULONG i, iFoundMode;
+
+ DPRINT1("Enter UserEnumDisplaySettings('%ls', %ld)\n",
+ pustrDevice ? pustrDevice->Buffer : NULL, iModeNum);
+
+ /* Ask gdi for the GRAPHICS_DEVICE */
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0);
+ if (!pGraphicsDevice)
+ {
+ /* No device found */
+ DPRINT1("No device found!\n");
+ return FALSE;
+ }
+
+ if (iModeNum == 0)
+ {
+ DPRINT1("Should initialize modes somehow\n");
+ // Update DISPLAY_DEVICEs?
+ }
+
+ iFoundMode = 0;
+ for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+ {
+ pdmentry = &pGraphicsDevice->pDevModeList[i];
+
+// if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) || // FIXME!
+// (dwFlags & EDS_RAWMODE))
+ {
+ /* Is this the one we want? */
+ if (iFoundMode == iModeNum)
+ {
+ *ppdm = pdmentry->pdm;
+ return STATUS_SUCCESS;
+ }
+
+ /* Increment number of found modes */
+ iFoundMode++;
+ }
+ }
+
+ /* Nothing was found */
+ return STATUS_INVALID_PARAMETER;
+}
+
+NTSTATUS
+NTAPI
+UserOpenDisplaySettingsKey(
+ OUT PHKEY phkey,
+ IN PUNICODE_STRING pustrDevice,
+ IN BOOL bGlobal)
+{
+ HKEY hkey;
+ DISPLAY_DEVICEW dispdev;
+ NTSTATUS Status;
+
+ /* Get device info */
+ Status = UserEnumDisplayDevices(pustrDevice, 0, &dispdev, 0);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ if (bGlobal)
+ {
+ // FIXME: need to fix the registry key somehow
+ }
+
+ /* Open the registry key */
+ Status = RegOpenKey(dispdev.DeviceKey, &hkey);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ *phkey = hkey;
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+UserEnumRegistryDisplaySettings(
+ IN PUNICODE_STRING pustrDevice,
+ OUT LPDEVMODEW pdm)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS
+APIENTRY
+NtUserEnumDisplaySettings(
+ IN PUNICODE_STRING pustrDevice,
+ IN DWORD iModeNum,
+ OUT LPDEVMODEW lpDevMode,
+ IN DWORD dwFlags)
+{
+ UNICODE_STRING ustrDevice;
+ WCHAR awcDevice[CCHDEVICENAME];
+ NTSTATUS Status;
+ ULONG cbSize, cbExtra;
+ DEVMODEW dmReg, *pdm;
+
+ DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
+ pustrDevice ? pustrDevice->Buffer:0, iModeNum);
+
+ if (pustrDevice)
+ {
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
+ _SEH2_TRY
+ {
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END
+
+ pustrDevice = &ustrDevice;
+ }
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
+ if (iModeNum == ENUM_REGISTRY_SETTINGS)
+ {
+ /* Get the registry settings */
+ Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
+ pdm = &dmReg;
+ }
+ else if (iModeNum == ENUM_CURRENT_SETTINGS)
+ {
+ /* Get the current settings */
+ Status = UserEnumCurrentDisplaySettings(pustrDevice, &pdm);
+ }
+ else
+ {
+ /* Get specified settings */
+ Status = UserEnumDisplaySettings(pustrDevice, iModeNum, &pdm, dwFlags);
+ }
+
+ /* Release lock */
+ UserLeave();
+
+ /* Did we succeed? */
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy some information back */
+ _SEH2_TRY
+ {
+ ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
+ cbSize = lpDevMode->dmSize;
+ cbExtra = lpDevMode->dmDriverExtra;
+
+ ProbeForWrite(lpDevMode, cbSize + cbExtra, 1);
+ lpDevMode->dmPelsWidth = pdm->dmPelsWidth;
+ lpDevMode->dmPelsHeight = pdm->dmPelsHeight;
+ lpDevMode->dmBitsPerPel = pdm->dmBitsPerPel;
+ lpDevMode->dmDisplayFrequency = pdm->dmDisplayFrequency;
+ lpDevMode->dmDisplayFlags = pdm->dmDisplayFlags;
+
+ /* output private/extra driver data */
+ if (cbExtra > 0 && pdm->dmDriverExtra > 0)
+ {
+ RtlCopyMemory((PCHAR)lpDevMode + cbSize,
+ (PCHAR)pdm + pdm->dmSize,
+ min(cbExtra, pdm->dmDriverExtra));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+
+ return Status;
+}
+
+BOOL APIENTRY UserClipCursor(RECTL *prcl);
+VOID APIENTRY UserRedrawDesktop();
+HCURSOR FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange);
+
+LONG
+APIENTRY
+UserChangeDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ LPDEVMODEW pdm,
+ HWND hwnd,
+ DWORD flags,
+ LPVOID lParam)
+{
+ DEVMODEW dmReg;
+ LONG lResult = DISP_CHANGE_SUCCESSFUL;
+ HKEY hkey;
+ NTSTATUS Status;
+ PPDEVOBJ ppdev;
+ PDESKTOP pdesk;
+
+ /* If no DEVMODE is given, use registry settings */
+ if (!pdm)
+ {
+ /* Get the registry settings */
+ Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not load registry settings\n");
+ return DISP_CHANGE_BADPARAM;
+ }
+ pdm = &dmReg;
+ }
+
+ /* Get the PDEV */
+ ppdev = EngpGetPDEV(pustrDevice);
+ if (!ppdev)
+ {
+ DPRINT1("failed to get PDEV\n");
+ return DISP_CHANGE_BADPARAM;
+ }
+
+ /* Look for the requested DEVMODE */
+ pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
+ if (!pdm)
+ {
+ DPRINT1("Could not find a matching DEVMODE\n");
+ lResult = DISP_CHANGE_BADMODE;
+ goto leave;
+ }
+
+ /* Shall we update the registry? */
+ if (flags & CDS_UPDATEREGISTRY)
+ {
+ /* Open the local or global settings key */
+ Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, flags & CDS_GLOBAL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Store the settings */
+ RegWriteDisplaySettings(hkey, pdm);
+
+ /* Close the registry key */
+ ZwClose(hkey);
+ }
+ else
+ {
+ DPRINT1("Could not open registry key\n");
+ lResult = DISP_CHANGE_NOTUPDATED;
+ }
+ }
+
+ /* Check if DEVMODE matches the current mode */
+ if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
+ {
+ DPRINT1("DEVMODE matches, nothing to do\n");
+ goto leave;
+ }
+
+ /* Shall we apply the settings? */
+ if (!(flags & CDS_NORESET))
+ {
+ ULONG ulResult;
+
+ /* Remove mouse pointer */
+ UserSetCursor(NULL, TRUE);
+
+ /* Do the mode switch */
+ ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
+
++ /* Restore mouse pointer, no hooks called */
++ UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+
+ /* Check for failure */
+ if (!ulResult)
+ {
+ DPRINT1("failed to set mode\n");
+ lResult = (lResult == DISP_CHANGE_NOTUPDATED) ?
+ DISP_CHANGE_FAILED : DISP_CHANGE_RESTART;
+
+ goto leave;
+ }
+
+ /* Update the system metrics */
+ InitMetrics();
+
+ //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
+
+ /* Remove all cursor clipping */
+ UserClipCursor(NULL);
+
+ pdesk = IntGetActiveDesktop();
+ //IntHideDesktop(pdesk);
+
+ /* Send WM_DISPLAYCHANGE to all toplevel windows */
+ co_IntSendMessageTimeout(HWND_BROADCAST,
+ WM_DISPLAYCHANGE,
+ (WPARAM)ppdev->gdiinfo.cBitsPixel,
+ (LPARAM)(ppdev->gdiinfo.ulHorzRes + (ppdev->gdiinfo.ulVertRes << 16)),
+ SMTO_NORMAL,
+ 100,
+ &ulResult);
+
+ //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
+
+ UserRedrawDesktop();
+ }
+
+leave:
+ /* Release the PDEV */
+ PDEVOBJ_vRelease(ppdev);
+
+ return lResult;
+}
+
+LONG
+APIENTRY
+NtUserChangeDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ LPDEVMODEW lpDevMode,
+ HWND hwnd,
+ DWORD dwflags,
+ LPVOID lParam)
+{
+ WCHAR awcDevice[CCHDEVICENAME];
+ UNICODE_STRING ustrDevice;
+ DEVMODEW dmLocal;
+ LONG lRet;
+
+ /* Check arguments */
+ if ((dwflags != CDS_VIDEOPARAMETERS && lParam != NULL) ||
+ (hwnd != NULL))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return DISP_CHANGE_BADPARAM;
+ }
+
+ /* Check flags */
+ if ((dwflags & (CDS_GLOBAL|CDS_NORESET)) && !(dwflags & CDS_UPDATEREGISTRY))
+ {
+ return DISP_CHANGE_BADFLAGS;
+ }
+
+ /* Copy the device name */
+ if (pustrDevice)
+ {
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
+ _SEH2_TRY
+ {
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Set and return error */
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
+ }
+ _SEH2_END
+
+ pustrDevice = &ustrDevice;
+ }
+
+ /* Copy devmode */
+ if (lpDevMode)
+ {
+ _SEH2_TRY
+ {
+ /* Probe the size field of the structure */
+ ProbeForRead(lpDevMode, sizeof(dmLocal.dmSize), 1);
+
+ /* Calculate usable size */
+ dmLocal.dmSize = min(sizeof(dmLocal), lpDevMode->dmSize);
+
+ /* Probe and copy the full DEVMODE */
+ ProbeForRead(lpDevMode, dmLocal.dmSize, 1);
+ RtlCopyMemory(&dmLocal, lpDevMode, dmLocal.dmSize);
+ dmLocal.dmSize = sizeof(dmLocal);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Set and return error */
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
+ }
+ _SEH2_END
+
+ /* Check for extra parameters */
+ if (dmLocal.dmDriverExtra > 0)
+ {
+ /* FIXME: TODO */
+ DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
+ dmLocal.dmDriverExtra = 0;
+ }
+
+ /* Use the local structure */
+ lpDevMode = &dmLocal;
+ }
+
+ // FIXME: Copy videoparameters
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
+ /* Call internal function */
+ lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, hwnd, dwflags, NULL);
+
+ /* Release lock */
+ UserLeave();
+
+ return lRet;
+}
+
--- /dev/null
- PUNICODE_STRING WindowName;
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Messages
+ * FILE: subsys/win32k/ntuser/message.c
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISION HISTORY:
+ * 06-06-2001 CSH Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
+
+typedef struct
+{
+ UINT uFlags;
+ UINT uTimeout;
+ ULONG_PTR Result;
+}
+DOSENDMESSAGE, *PDOSENDMESSAGE;
+
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS FASTCALL
+IntInitMessageImpl(VOID)
+{
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS FASTCALL
+IntCleanupMessageImpl(VOID)
+{
+ return STATUS_SUCCESS;
+}
+
+#define MMS_SIZE_WPARAM -1
+#define MMS_SIZE_WPARAMWCHAR -2
+#define MMS_SIZE_LPARAMSZ -3
+#define MMS_SIZE_SPECIAL -4
+#define MMS_FLAG_READ 0x01
+#define MMS_FLAG_WRITE 0x02
+#define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
+typedef struct tagMSGMEMORY
+{
+ UINT Message;
+ UINT Size;
+ INT Flags;
+}
+MSGMEMORY, *PMSGMEMORY;
+
+static MSGMEMORY MsgMemory[] =
+ {
+ { WM_CREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_DDE_ACK, sizeof(KMDDELPARAM), MMS_FLAG_READ },
+ { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ },
+ { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
+ { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
+ { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_NCCREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
+ { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
+ { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
+ { WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
+ { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
+ { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
+ };
+
+static PMSGMEMORY FASTCALL
+FindMsgMemory(UINT Msg)
+{
+ PMSGMEMORY MsgMemoryEntry;
+
+ /* See if this message type is present in the table */
+ for (MsgMemoryEntry = MsgMemory;
+ MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY);
+ MsgMemoryEntry++)
+ {
+ if (Msg == MsgMemoryEntry->Message)
+ {
+ return MsgMemoryEntry;
+ }
+ }
+
+ return NULL;
+}
+
+static UINT FASTCALL
+MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
+{
+ CREATESTRUCTW *Cs;
+ PUNICODE_STRING WindowName;
+ PUNICODE_STRING ClassName;
+ UINT Size = 0;
+
+ _SEH2_TRY
+ {
+ if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
+ {
+ Size = (UINT)wParam;
+ }
+ else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
+ {
+ Size = (UINT) (wParam * sizeof(WCHAR));
+ }
+ else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
+ {
+ Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
+ }
+ else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
+ {
+ switch(MsgMemoryEntry->Message)
+ {
+ case WM_CREATE:
+ case WM_NCCREATE:
+ Cs = (CREATESTRUCTW *) lParam;
+ WindowName = (PUNICODE_STRING) Cs->lpszName;
+ ClassName = (PUNICODE_STRING) Cs->lpszClass;
+ Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ Size += sizeof(WCHAR) + sizeof(ATOM);
+ }
+ else
+ {
+ Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+ }
+ break;
+
+ case WM_NCCALCSIZE:
+ Size = wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
+ break;
+
+ case WM_COPYDATA:
+ Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
+ break;
+
+ case WM_COPYGLOBALDATA:
+ Size = wParam;
+ break;
+
+ default:
+ assert(FALSE);
+ Size = 0;
+ break;
+ }
+ }
+ else
+ {
+ Size = MsgMemoryEntry->Size;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
+ Size = 0;
+ }
+ _SEH2_END;
+ return Size;
+}
+
+static NTSTATUS
+PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded)
+{
+ NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
+ NCCALCSIZE_PARAMS *PackedNcCalcsize;
+ CREATESTRUCTW *UnpackedCs;
+ CREATESTRUCTW *PackedCs;
- WindowName = (PUNICODE_STRING) UnpackedCs->lpszName;
++ PLARGE_STRING WindowName;
+ PUNICODE_STRING ClassName;
+ POOL_TYPE PoolType;
+ UINT Size;
+ PCHAR CsData;
+
+ *lParamPacked = lParam;
+
+ if (NonPagedPoolNeeded)
+ PoolType = NonPagedPool;
+ else
+ PoolType = PagedPool;
+
+ if (WM_NCCALCSIZE == Msg && wParam)
+ {
+
+ UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
+ PackedNcCalcsize = ExAllocatePoolWithTag(PoolType,
+ sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
+ TAG_MSG);
+
+ if (NULL == PackedNcCalcsize)
+ {
+ DPRINT1("Not enough memory to pack lParam\n");
+ return STATUS_NO_MEMORY;
+ }
+ RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS));
+ PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1);
+ RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS));
+ *lParamPacked = (LPARAM) PackedNcCalcsize;
+ }
+ else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+ {
+ UnpackedCs = (CREATESTRUCTW *) lParam;
++ WindowName = (PLARGE_STRING) UnpackedCs->lpszName;
+ ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
+ Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ Size += sizeof(WCHAR) + sizeof(ATOM);
+ }
+ else
+ {
+ Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+ }
+ PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG);
+ if (NULL == PackedCs)
+ {
+ DPRINT1("Not enough memory to pack lParam\n");
+ return STATUS_NO_MEMORY;
+ }
+ RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW));
+ CsData = (PCHAR) (PackedCs + 1);
+ PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+ RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length);
+ CsData += WindowName->Length;
+ *((WCHAR *) CsData) = L'\0';
+ CsData += sizeof(WCHAR);
+ PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ *((WCHAR *) CsData) = L'A';
+ CsData += sizeof(WCHAR);
+ *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer;
+ CsData += sizeof(ATOM);
+ }
+ else
+ {
+ *((WCHAR *) CsData) = L'S';
+ CsData += sizeof(WCHAR);
+ RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length);
+ CsData += ClassName->Length;
+ *((WCHAR *) CsData) = L'\0';
+ CsData += sizeof(WCHAR);
+ }
+ ASSERT(CsData == (PCHAR) PackedCs + Size);
+ *lParamPacked = (LPARAM) PackedCs;
+ }
+
+ else if (PoolType == NonPagedPool)
+ {
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID PackedData;
+
+ MsgMemoryEntry = FindMsgMemory(Msg);
+
+ if ((!MsgMemoryEntry) || (MsgMemoryEntry->Size < 0))
+ {
+ /* Keep previous behavior */
+ return STATUS_SUCCESS;
+ }
+ PackedData = ExAllocatePoolWithTag(NonPagedPool, MsgMemorySize(MsgMemoryEntry, wParam, lParam), TAG_MSG);
+ RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam));
+ *lParamPacked = (LPARAM)PackedData;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed)
+{
+ NCCALCSIZE_PARAMS *UnpackedParams;
+ NCCALCSIZE_PARAMS *PackedParams;
+ PWINDOWPOS UnpackedWindowPos;
+
+ if (lParamPacked == lParam)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ if (WM_NCCALCSIZE == Msg && wParam)
+ {
+ PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
+ UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
+ UnpackedWindowPos = UnpackedParams->lppos;
+ RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
+ UnpackedParams->lppos = UnpackedWindowPos;
+ RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
+ ExFreePool((PVOID) lParamPacked);
+
+ return STATUS_SUCCESS;
+ }
+ else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+ {
+ ExFreePool((PVOID) lParamPacked);
+
+ return STATUS_SUCCESS;
+ }
+ else if (NonPagedPoolUsed)
+ {
+ PMSGMEMORY MsgMemoryEntry;
+ MsgMemoryEntry = FindMsgMemory(Msg);
+ if (MsgMemoryEntry->Size < 0)
+ {
+ /* Keep previous behavior */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (MsgMemory->Flags == MMS_FLAG_READWRITE)
+ {
+ //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
+ }
+ ExFreePool((PVOID) lParamPacked);
+ return STATUS_SUCCESS;
+ }
+
+ ASSERT(FALSE);
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+static
+VOID
+FASTCALL
+IntCallWndProc
+( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL SameThread = FALSE;
+
+ if (Window->pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
+ SameThread = TRUE;
+
+ if ((!SameThread && (Window->pti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROC))) ||
+ (SameThread && ISITHOOKED(WH_CALLWNDPROC)) )
+ {
+ CWPSTRUCT CWP;
+ CWP.hwnd = hWnd;
+ CWP.message = Msg;
+ CWP.wParam = wParam;
+ CWP.lParam = lParam;
+ co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP );
+ }
+}
+
+static
+VOID
+FASTCALL
+IntCallWndProcRet
+( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult)
+{
+ BOOL SameThread = FALSE;
+
+ if (Window->pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
+ SameThread = TRUE;
+
+ if ((!SameThread && (Window->pti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROCRET))) ||
+ (SameThread && ISITHOOKED(WH_CALLWNDPROCRET)) )
+ {
+ CWPRETSTRUCT CWPR;
+ CWPR.hwnd = hWnd;
+ CWPR.message = Msg;
+ CWPR.wParam = wParam;
+ CWPR.lParam = lParam;
+ CWPR.lResult = *uResult;
+ co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
+ }
+}
+
+LRESULT
+FASTCALL
+IntDispatchMessage(PMSG pMsg)
+{
+ LARGE_INTEGER TickCount;
+ LONG Time;
+ LRESULT retval;
+ PMSGMEMORY MsgMemoryEntry;
+ INT lParamBufferSize;
+ LPARAM lParamPacked;
+ PWINDOW_OBJECT Window = NULL;
+
+ if (pMsg->hwnd)
+ {
+ Window = UserGetWindowObject(pMsg->hwnd);
+ if (!Window || !Window->Wnd) return 0;
+ }
+
+ if (((pMsg->message == WM_SYSTIMER) ||
+ (pMsg->message == WM_TIMER)) &&
+ (pMsg->lParam) )
+ {
+ if (pMsg->message == WM_TIMER)
+ {
+ if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window,pMsg->wParam,pMsg->lParam))
+ {
+ KeQueryTickCount(&TickCount);
+ Time = MsqCalculateMessageTime(&TickCount);
+ return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+ TRUE,
+ pMsg->hwnd,
+ WM_TIMER,
+ pMsg->wParam,
+ (LPARAM)Time,
+ sizeof(LPARAM));
+ }
+ return 0;
+ }
+ else
+ {
+ PTIMER pTimer = FindSystemTimer(pMsg);
+ if (pTimer && pTimer->pfn)
+ {
+ KeQueryTickCount(&TickCount);
+ Time = MsqCalculateMessageTime(&TickCount);
+ pTimer->pfn(pMsg->hwnd, WM_SYSTIMER, (UINT)pMsg->wParam, Time);
+ }
+ return 0;
+ }
+ }
+ // Need a window!
+ if ( !Window || !Window->Wnd ) return 0;
+
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(pMsg->message);
+ if ( !MsgMemoryEntry )
+ {
+ lParamBufferSize = -1;
+ }
+ else
+ {
+ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, pMsg->wParam, pMsg->lParam);
+ }
+
+ if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
+ {
+ DPRINT1("Failed to pack message parameters\n");
+ return 0;
+ }
+
+ retval = co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
+ !Window->Wnd->Unicode,
+ pMsg->hwnd,
+ pMsg->message,
+ pMsg->wParam,
+ lParamPacked,
+ lParamBufferSize);
+
+ if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
+ {
+ DPRINT1("Failed to unpack message parameters\n");
+ }
+
+ if (pMsg->message == WM_PAINT)
+ {
+ /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
+ HRGN hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
+ co_UserGetUpdateRgn( Window, hrgn, TRUE );
+ REGION_FreeRgnByHandle( hrgn );
+ }
+ return retval;
+}
+
+VOID FASTCALL
+co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
+{
+ if(!Msg->hwnd || ThreadQueue->CaptureWindow)
+ {
+ return;
+ }
+
+ switch(Msg->message)
+ {
+ case WM_MOUSEMOVE:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
+ break;
+ }
+ case WM_NCMOUSEMOVE:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_XBUTTONDBLCLK:
+ {
+ WPARAM wParam;
+ PSYSTEM_CURSORINFO CurInfo;
+ CurInfo = IntGetSysCursorInfo();
+
+ wParam = (WPARAM)(CurInfo->ButtonsDown);
+
+ co_IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam);
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
+ break;
+ }
+ case WM_NCLBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCXBUTTONDOWN:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCXBUTTONDBLCLK:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam);
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
+ break;
+ }
+ }
+}
+
+BOOL FASTCALL
+co_IntActivateWindowMouse(
+ PUSER_MESSAGE_QUEUE ThreadQueue,
+ LPMSG Msg,
+ PWINDOW_OBJECT MsgWindow,
+ USHORT *HitTest)
+{
+ ULONG Result;
+ PWINDOW_OBJECT Parent;
+
+ ASSERT_REFS_CO(MsgWindow);
+
+ if(*HitTest == (USHORT)HTTRANSPARENT)
+ {
+ /* eat the message, search again! */
+ return TRUE;
+ }
+
+ Parent = IntGetParent(MsgWindow);//fixme: deref retval?
+
+ /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
+ Result = co_IntSendMessage(MsgWindow->hSelf,
+ WM_MOUSEACTIVATE,
+ (WPARAM) (Parent ? Parent->hSelf : MsgWindow->hSelf),
+ (LPARAM)MAKELONG(*HitTest, Msg->message)
+ );
+
+ switch (Result)
+ {
+ case MA_NOACTIVATEANDEAT:
+ return TRUE;
+ case MA_NOACTIVATE:
+ break;
+ case MA_ACTIVATEANDEAT:
+ co_IntMouseActivateWindow(MsgWindow);
+ return TRUE;
+ default:
+ /* MA_ACTIVATE */
+ co_IntMouseActivateWindow(MsgWindow);
+ break;
+ }
+
+ return FALSE;
+}
+
+BOOL FASTCALL
+co_IntTranslateMouseMessage(
+ PUSER_MESSAGE_QUEUE ThreadQueue,
+ LPMSG Msg,
+ USHORT *HitTest,
+ BOOL Remove)
+{
+ PWINDOW_OBJECT Window;
+ USER_REFERENCE_ENTRY Ref, DesktopRef;
+
+ if(!(Window = UserGetWindowObject(Msg->hwnd)))
+ {
+ /* let's just eat the message?! */
+ return TRUE;
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ if ( ThreadQueue == Window->pti->MessageQueue &&
+ ThreadQueue->CaptureWindow != Window->hSelf)
+ {
+ /* only send WM_NCHITTEST messages if we're not capturing the window! */
+ *HitTest = co_IntSendMessage(Window->hSelf, WM_NCHITTEST, 0,
+ MAKELONG(Msg->pt.x, Msg->pt.y));
+
+ if (*HitTest == (USHORT)HTTRANSPARENT)
+ {
+ PWINDOW_OBJECT DesktopWindow;
+ HWND hDesktop = IntGetDesktopWindow();
+
+ if ((DesktopWindow = UserGetWindowObject(hDesktop)))
+ {
+ PWINDOW_OBJECT Wnd;
+
+ UserRefObjectCo(DesktopWindow, &DesktopRef);
+
+ co_WinPosWindowFromPoint(DesktopWindow, Window->pti->MessageQueue, &Msg->pt, &Wnd);
+ if (Wnd)
+ {
+ if (Wnd != Window)
+ {
+ /* post the message to the other window */
+ Msg->hwnd = Wnd->hSelf;
+ if(!(Wnd->state & WINDOWSTATUS_DESTROYING))
+ {
+ MsqPostMessage(Wnd->pti->MessageQueue, Msg, FALSE,
+ Msg->message == WM_MOUSEMOVE ? QS_MOUSEMOVE :
+ QS_MOUSEBUTTON);
+ }
+
+ /* eat the message */
+ UserDereferenceObject(Wnd);
+ UserDerefObjectCo(DesktopWindow);
+ UserDerefObjectCo(Window);
+ return TRUE;
+ }
+ UserDereferenceObject(Wnd);
+ }
+
+ UserDerefObjectCo(DesktopWindow);
+ }
+ }
+ }
+ else
+ {
+ *HitTest = HTCLIENT;
+ }
+
+ if ( gspv.bMouseClickLock &&
+ ( (Msg->message == WM_LBUTTONUP) ||
+ (Msg->message == WM_LBUTTONDOWN) ) )
+ {
+ if (MsqIsClkLck(Msg, Remove))
+ {
+ // FIXME: drop the message, hack: use WM_NULL
+ Msg->message = WM_NULL;
+ }
+ }
+
+ if (IS_BTN_MESSAGE(Msg->message, DOWN))
+ {
+ /* generate double click messages, if necessary */
+ if ((((*HitTest) != HTCLIENT) ||
+ (Window->Wnd->pcls->style & CS_DBLCLKS)) &&
+ MsqIsDblClk(Msg, Remove))
+ {
+ Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
+ }
+ }
+
+ if(Msg->message != WM_MOUSEWHEEL)
+ {
+
+ if ((*HitTest) != HTCLIENT)
+ {
+ Msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
+ if ( (Msg->message == WM_NCRBUTTONUP) &&
+ (((*HitTest) == HTCAPTION) || ((*HitTest) == HTSYSMENU)) )
+ {
+ Msg->message = WM_CONTEXTMENU;
+ Msg->wParam = (WPARAM)Window->hSelf;
+ }
+ else
+ {
+ Msg->wParam = *HitTest;
+ }
+ Msg->lParam = MAKELONG(Msg->pt.x, Msg->pt.y);
+ }
+ else if ( ThreadQueue->MoveSize == NULL &&
+ ThreadQueue->MenuOwner == NULL )
+ {
+ /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
+ Msg->lParam = MAKELONG(
+ Msg->pt.x - (WORD)Window->Wnd->rcClient.left,
+ Msg->pt.y - (WORD)Window->Wnd->rcClient.top);
+ }
+ }
+
+ UserDerefObjectCo(Window);
+ return FALSE;
+}
+
+BOOL ProcessMouseMessage(MSG* Msg, USHORT HitTest, UINT RemoveMsg)
+{
+ MOUSEHOOKSTRUCT MHook;
+ EVENTMSG Event;
+
+ Event.message = Msg->message;
+ Event.time = Msg->time;
+ Event.hwnd = Msg->hwnd;
+ Event.paramL = Msg->pt.x;
+ Event.paramH = Msg->pt.y;
+ co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
+
+
+ MHook.pt = Msg->pt;
+ MHook.hwnd = Msg->hwnd;
+ MHook.wHitTestCode = HitTest;
+ MHook.dwExtraInfo = 0;
+ if (co_HOOK_CallHooks( WH_MOUSE,
+ RemoveMsg ? HC_ACTION : HC_NOREMOVE,
+ Msg->message,
+ (LPARAM)&MHook ))
+ {
+ if (ISITHOOKED(WH_CBT))
+ {
+ MHook.pt = Msg->pt;
+ MHook.hwnd = Msg->hwnd;
+ MHook.wHitTestCode = HitTest;
+ MHook.dwExtraInfo = 0;
+ co_HOOK_CallHooks( WH_CBT,
+ HCBT_CLICKSKIPPED,
+ Msg->message,
+ (LPARAM)&MHook);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL ProcessKeyboardMessage(MSG* Msg, UINT RemoveMsg)
+{
+ EVENTMSG Event;
+
+ Event.message = Msg->message;
+ Event.hwnd = Msg->hwnd;
+ Event.time = Msg->time;
+ Event.paramL = (Msg->wParam & 0xFF) | (HIWORD(Msg->lParam) << 8);
+ Event.paramH = Msg->lParam & 0x7FFF;
+ if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000;
+ co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
+
+ if (co_HOOK_CallHooks( WH_KEYBOARD,
+ RemoveMsg ? HC_ACTION : HC_NOREMOVE,
+ LOWORD(Msg->wParam),
+ Msg->lParam))
+ {
+ if (ISITHOOKED(WH_CBT))
+ {
+ /* skip this message */
+ co_HOOK_CallHooks( WH_CBT,
+ HCBT_KEYSKIPPED,
+ LOWORD(Msg->wParam),
+ Msg->lParam );
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+/*
+ * Internal version of PeekMessage() doing all the work
+ */
+BOOL FASTCALL
+co_IntPeekMessage( PUSER_MESSAGE Msg,
+ PWINDOW_OBJECT Window,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg )
+{
+ PTHREADINFO pti;
+ LARGE_INTEGER LargeTickCount;
+ PUSER_MESSAGE_QUEUE ThreadQueue;
+ PUSER_MESSAGE Message;
+ BOOL Present, RemoveMessages;
+ USER_REFERENCE_ENTRY Ref;
+ USHORT HitTest;
+
+ /* The queues and order in which they are checked are documented in the MSDN
+ article on GetMessage() */
+
+ pti = PsGetCurrentThreadWin32Thread();
+ ThreadQueue = pti->MessageQueue;
+
+ /* Inspect RemoveMsg flags */
+ /* Note:
+ The only flag we process is PM_REMOVE.
+ Processing (High word) PM_QS_Xx Is needed. This and MsgFilterXxx can result
+ with QS_Xx flags to be used to isolate which message check to test for.
+ ATM, we look at all messages and the filters are sent to co_MsqFindMessage
+ and there, it is cross checked.
+ Example: Wine server/queue.c is_keyboard_msg, check_msg_filter and
+ filter_contains_hw_range.
+ */
+ RemoveMessages = RemoveMsg & PM_REMOVE;
+
+/*
+ If no filter is specified, messages are processed in the following order:
+
+ * Sent messages
+ * Posted messages
+ * Input (hardware) messages and system internal events
+ * Sent messages (again)
+ * WM_PAINT messages
+ * WM_TIMER messages
+ */
+CheckMessages:
+
+ Present = FALSE;
+
+ KeQueryTickCount(&LargeTickCount);
+ ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+
+ /* Dispatch sent messages here. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
+
+ /* Now look for a quit message. */
+
+ if (ThreadQueue->QuitPosted)
+ {
+ /* According to the PSDK, WM_QUIT messages are always returned, regardless
+ of the filter specified */
+ Msg->Msg.hwnd = NULL;
+ Msg->Msg.message = WM_QUIT;
+ Msg->Msg.wParam = ThreadQueue->QuitExitCode;
+ Msg->Msg.lParam = 0;
+ Msg->FreeLParam = FALSE;
+ if (RemoveMessages)
+ {
+ ThreadQueue->QuitPosted = FALSE;
+ }
+ goto MsgExit;
+ }
+
+ /* Now check for normal messages. */
+ Present = co_MsqFindMessage( ThreadQueue,
+ FALSE,
+ RemoveMessages,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
+ &Message );
+ if (Present)
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+ if (RemoveMessages)
+ {
+ MsqDestroyMessage(Message);
+ }
+ goto MessageFound;
+ }
+
+ /* Check for hardware events. */
+ Present = co_MsqFindMessage( ThreadQueue,
+ TRUE,
+ RemoveMessages,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
+ &Message );
+ if (Present)
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+ if (RemoveMessages)
+ {
+ MsqDestroyMessage(Message);
+ }
+ goto MessageFound;
+ }
+
+ /* Check for sent messages again. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
+
+ /* Check for paint messages. */
+ if ( IntGetPaintMessage( Window,
+ MsgFilterMin,
+ MsgFilterMax,
+ pti,
+ &Msg->Msg,
+ RemoveMessages))
+ {
+ Msg->FreeLParam = FALSE;
+ goto MsgExit;
+ }
+
+ if (PostTimerMessages(Window))
+ goto CheckMessages;
+
+ if(Present)
+ {
+MessageFound:
+
+ if(RemoveMessages)
+ {
+ PWINDOW_OBJECT MsgWindow = NULL;
+
+ /* Mouse message process */
+
+ if( Msg->Msg.hwnd &&
+ ( MsgWindow = UserGetWindowObject(Msg->Msg.hwnd) ) &&
+ Msg->Msg.message >= WM_MOUSEFIRST &&
+ Msg->Msg.message <= WM_MOUSELAST )
+ {
+ USHORT HitTest;
+
+ UserRefObjectCo(MsgWindow, &Ref);
+
+ if ( co_IntTranslateMouseMessage( ThreadQueue,
+ &Msg->Msg,
+ &HitTest,
+ TRUE))
+ /* FIXME - check message filter again, if the message doesn't match anymore,
+ search again */
+ {
+ UserDerefObjectCo(MsgWindow);
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
+
+ if(ThreadQueue->CaptureWindow == NULL)
+ {
+ co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
+
+ if ( ( Msg->Msg.message != WM_MOUSEMOVE &&
+ Msg->Msg.message != WM_NCMOUSEMOVE ) &&
+ IS_BTN_MESSAGE(Msg->Msg.message, DOWN) &&
+ co_IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest) )
+ {
+ UserDerefObjectCo(MsgWindow);
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
+ }
+
+ UserDerefObjectCo(MsgWindow);
+ }
+ else
+ {
+ co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
+ }
+
+// if(MsgWindow)
+// {
+// UserDereferenceObject(MsgWindow);
+// }
+
+ goto MsgExit;
+ }
+
+ if ( ( Msg->Msg.hwnd &&
+ Msg->Msg.message >= WM_MOUSEFIRST &&
+ Msg->Msg.message <= WM_MOUSELAST ) &&
+ co_IntTranslateMouseMessage( ThreadQueue,
+ &Msg->Msg,
+ &HitTest,
+ FALSE) )
+ /* FIXME - check message filter again, if the message doesn't match anymore,
+ search again */
+ {
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
+
+MsgExit:
+ if ( ISITHOOKED(WH_MOUSE) && IS_MOUSE_MESSAGE(Msg->Msg.message))
+ {
+ if(!ProcessMouseMessage(&Msg->Msg, HitTest, RemoveMsg))
+ {
+ return FALSE;
+ }
+ }
+
+ if ( ISITHOOKED(WH_KEYBOARD) && IS_KBD_MESSAGE(Msg->Msg.message))
+ {
+ if(!ProcessKeyboardMessage(&Msg->Msg, RemoveMsg))
+ {
+ return FALSE;
+ }
+ }
+ // The WH_GETMESSAGE hook enables an application to monitor messages about to
+ // be returned by the GetMessage or PeekMessage function.
+ if (ISITHOOKED(WH_GETMESSAGE))
+ {
+ //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
+ co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
+ }
+ return TRUE;
+ }
+
+ return Present;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
+{
+ NTSTATUS Status;
+
+ PVOID KernelMem;
+ UINT Size;
+
+ *KernelModeMsg = *UserModeMsg;
+
+ /* See if this message type is present in the table */
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ return STATUS_SUCCESS;
+ }
+
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+ if (0 != Size)
+ {
+ /* Allocate kernel mem */
+ KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
+ if (NULL == KernelMem)
+ {
+ DPRINT1("Not enough memory to copy message to kernel mem\n");
+ return STATUS_NO_MEMORY;
+ }
+ KernelModeMsg->lParam = (LPARAM) KernelMem;
+
+ /* Copy data if required */
+ if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
+ {
+ Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
+ ExFreePoolWithTag(KernelMem, TAG_MSG);
+ return Status;
+ }
+ }
+ else
+ {
+ /* Make sure we don't pass any secrets to usermode */
+ RtlZeroMemory(KernelMem, Size);
+ }
+ }
+ else
+ {
+ KernelModeMsg->lParam = 0;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
+{
+ NTSTATUS Status;
+ PMSGMEMORY MsgMemoryEntry;
+ UINT Size;
+
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ return STATUS_SUCCESS;
+ }
+
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+ if (0 != Size)
+ {
+ /* Copy data if required */
+ if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
+ {
+ Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
+ ExFreePool((PVOID) KernelModeMsg->lParam);
+ return Status;
+ }
+ }
+
+ ExFreePool((PVOID) KernelModeMsg->lParam);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static BOOL FASTCALL
+co_IntWaitMessage( PWINDOW_OBJECT Window,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax )
+{
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE ThreadQueue;
+ NTSTATUS Status = STATUS_SUCCESS;
+ USER_MESSAGE Msg;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ ThreadQueue = pti->MessageQueue;
+
+ do
+ {
+ if ( co_IntPeekMessage( &Msg,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
+ PM_NOREMOVE))
+ {
+ return TRUE;
+ }
+ /* Nothing found. Wait for new messages. */
+ Status = co_MsqWaitForNewMessages( ThreadQueue,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax);
+ }
+ while ( (STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) ||
+ STATUS_TIMEOUT == Status );
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ DPRINT1("Exit co_IntWaitMessage on error!\n");
+ }
+
+ return FALSE;
+}
+
+BOOL FASTCALL
+co_IntGetPeekMessage( PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg,
+ BOOL bGMSG )
+{
+ BOOL Present;
+ PWINDOW_OBJECT Window;
+ USER_MESSAGE Msg;
+
+ if ( hWnd == HWND_TOPMOST ||
+ hWnd == HWND_BROADCAST )
+ hWnd = HWND_BOTTOM;
+
+ /* Validate input */
+ if (hWnd && hWnd != HWND_BOTTOM)
+ {
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ if (bGMSG)
+ return -1;
+ else
+ return FALSE;
+ }
+ }
+ else
+ {
+ Window = (PWINDOW_OBJECT)hWnd;
+ }
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
+ MsgFilterMin = 0;
+ MsgFilterMax = 0;
+ }
+
+ do
+ {
+ Present = co_IntPeekMessage( &Msg,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
+ RemoveMsg );
+ if (Present)
+ {
+ RtlCopyMemory( pMsg, &Msg.Msg, sizeof(MSG));
+
+ if (bGMSG)
+ return (WM_QUIT != pMsg->message);
+ else
+ return TRUE;
+ }
+
+ if ( bGMSG && !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
+ {
+ return -1;
+ }
+ else
+ {
+ if (!(RemoveMsg & PM_NOYIELD))
+ {
+ // Yield this thread!
+ UserLeave();
+ ZwYieldExecution();
+ UserEnterExclusive();
+ // Fall through to fail.
+ }
+ }
+ }
+ while( bGMSG && !Present );
+
+ return FALSE;
+}
+
+BOOL FASTCALL
+UserPostThreadMessage( DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ MSG Message;
+ PETHREAD peThread;
+ PTHREADINFO pThread;
+ LARGE_INTEGER LargeTickCount;
+ NTSTATUS Status;
+
+ DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam,lParam);
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
+
+ if( Status == STATUS_SUCCESS )
+ {
+ pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
+ if( !pThread ||
+ !pThread->MessageQueue ||
+ (pThread->TIF_flags & TIF_INCLEANUP))
+ {
+ ObDereferenceObject( peThread );
+ return FALSE;
+ }
+
+ Message.hwnd = NULL;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ Message.pt = gpsi->ptCursor;
+
+ KeQueryTickCount(&LargeTickCount);
+ pThread->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+ ObDereferenceObject( peThread );
+ return TRUE;
+ }
+ else
+ {
+ SetLastNtError( Status );
+ }
+ return FALSE;
+}
+
+BOOL FASTCALL
+UserPostMessage( HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ PTHREADINFO pti;
+ MSG Message;
+ LARGE_INTEGER LargeTickCount;
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ if (!Wnd)
+ return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
+ Msg,
+ wParam,
+ lParam);
+
+ if (Wnd == HWND_BROADCAST)
+ {
+ HWND *List;
+ PWINDOW_OBJECT DesktopWindow;
+ ULONG i;
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+
+ if (List != NULL)
+ {
+ UserPostMessage(DesktopWindow->hSelf, Msg, wParam, lParam);
+ for (i = 0; List[i]; i++)
+ UserPostMessage(List[i], Msg, wParam, lParam);
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ PWINDOW_OBJECT Window;
+
+ Window = UserGetWindowObject(Wnd);
+ if ( !Window || !Window->Wnd )
+ {
+ return FALSE;
+ }
+
+ pti = Window->Wnd->head.pti;
+ if ( pti->TIF_flags & TIF_INCLEANUP )
+ {
+ DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd);
+ return FALSE;
+ }
+
+ if ( Window->state & WINDOWSTATUS_DESTROYING )
+ {
+ DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
+ /* FIXME - last error code? */
+ return FALSE;
+ }
+
+ if (WM_QUIT == Msg)
+ {
+ MsqPostQuitMessage(Window->pti->MessageQueue, wParam);
+ }
+ else
+ {
+ Message.hwnd = Wnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ Message.pt = gpsi->ptCursor;
+ KeQueryTickCount(&LargeTickCount);
+ pti->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(Window->pti->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+ }
+ }
+ return TRUE;
+}
+
+
+LRESULT FASTCALL
+co_IntSendMessage( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ ULONG_PTR Result = 0;
+ if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+ {
+ return (LRESULT)Result;
+ }
+ return 0;
+}
+
+static
+LRESULT FASTCALL
+co_IntSendMessageTimeoutSingle( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult )
+{
+ ULONG_PTR Result;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ INT lParamBufferSize;
+ LPARAM lParamPacked;
+ PTHREADINFO Win32Thread;
+ DECLARE_RETURN(LRESULT);
+ USER_REFERENCE_ENTRY Ref;
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN( FALSE);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ Win32Thread = PsGetCurrentThreadWin32Thread();
+
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+ if ( NULL != Win32Thread &&
+ Window->pti->MessageQueue == Win32Thread->MessageQueue)
+ {
+ if (Win32Thread->TIF_flags & TIF_INCLEANUP)
+ {
+ /* Never send messages to exiting threads */
+ RETURN( FALSE);
+ }
+
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Msg);
+ if (NULL == MsgMemoryEntry)
+ {
+ lParamBufferSize = -1;
+ }
+ else
+ {
+ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+ }
+
+ if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE)))
+ {
+ DPRINT1("Failed to pack message parameters\n");
+ RETURN( FALSE);
+ }
+
+ Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
+ !Window->Wnd->Unicode,
+ hWnd,
+ Msg,
+ wParam,
+ lParamPacked,
+ lParamBufferSize );
+ if(uResult)
+ {
+ *uResult = Result;
+ }
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+ if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
+ {
+ DPRINT1("Failed to unpack message parameters\n");
+ RETURN( TRUE);
+ }
+
+ RETURN( TRUE);
+ }
+
+ if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->pti->MessageQueue))
+ {
+ /* FIXME - Set a LastError? */
+ RETURN( FALSE);
+ }
+
+ if (Window->state & WINDOWSTATUS_DESTROYING)
+ {
+ /* FIXME - last error? */
+ DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+ RETURN( FALSE);
+ }
+
+ do
+ {
+ Status = co_MsqSendMessage( Window->pti->MessageQueue,
+ hWnd,
+ Msg,
+ wParam,
+ lParam,
+ uTimeout,
+ (uFlags & SMTO_BLOCK),
+ MSQ_NORMAL,
+ uResult );
+ }
+ while ((STATUS_TIMEOUT == Status) &&
+ (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
+ !MsqIsHung(Window->pti->MessageQueue));
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+ if (STATUS_TIMEOUT == Status)
+ {
+/*
+ MSDN says:
+ Microsoft Windows 2000: If GetLastError returns zero, then the function
+ timed out.
+ XP+ : If the function fails or times out, the return value is zero.
+ To get extended error information, call GetLastError. If GetLastError
+ returns ERROR_TIMEOUT, then the function timed out.
+ */
+ SetLastWin32Error(ERROR_TIMEOUT);
+ RETURN( FALSE);
+ }
+ else if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( FALSE);
+ }
+
+ RETURN( TRUE);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+ END_CLEANUP;
+}
+
+LRESULT FASTCALL
+co_IntSendMessageTimeout( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult )
+{
+ PWINDOW_OBJECT DesktopWindow;
+ HWND *Children;
+ HWND *Child;
+
+ if (HWND_BROADCAST != hWnd)
+ {
+ return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+ }
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ if (NULL == DesktopWindow)
+ {
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Send message to the desktop window too! */
+ co_IntSendMessageTimeoutSingle(DesktopWindow->hSelf, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+
+ Children = IntWinListChildren(DesktopWindow);
+ if (NULL == Children)
+ {
+ return 0;
+ }
+
+ for (Child = Children; NULL != *Child; Child++)
+ {
+ co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+ }
+
+ ExFreePool(Children);
+
+ return (LRESULT) TRUE;
+}
+
+LRESULT FASTCALL co_IntSendMessageNoWait(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ ULONG_PTR Result = 0;
+ co_IntSendMessageWithCallBack(hWnd,
+ Msg,
+ wParam,
+ lParam,
+ NULL,
+ 0,
+ &Result);
+ return Result;
+}
+
+LRESULT FASTCALL
+co_IntSendMessageWithCallBack( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ SENDASYNCPROC CompletionCallback,
+ ULONG_PTR CompletionCallbackContext,
+ ULONG_PTR *uResult)
+{
+ ULONG_PTR Result;
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ INT lParamBufferSize;
+ LPARAM lParamPacked;
+ PTHREADINFO Win32Thread;
+ DECLARE_RETURN(LRESULT);
+ USER_REFERENCE_ENTRY Ref;
+ PUSER_SENT_MESSAGE Message;
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(FALSE);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ if (Window->state & WINDOWSTATUS_DESTROYING)
+ {
+ /* FIXME - last error? */
+ DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+ RETURN(FALSE);
+ }
+
+ Win32Thread = PsGetCurrentThreadWin32Thread();
+
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+ if (Win32Thread == NULL)
+ {
+ ASSERT(FALSE);
+ RETURN(FALSE);
+ }
+
+ if (Win32Thread->TIF_flags & TIF_INCLEANUP)
+ {
+ /* Never send messages to exiting threads */
+ RETURN(FALSE);
+ }
+
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Msg);
+ if (NULL == MsgMemoryEntry)
+ {
+ lParamBufferSize = -1;
+ }
+ else
+ {
+ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+ }
+
+ if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->pti->MessageQueue != Win32Thread->MessageQueue)))
+ {
+ DPRINT1("Failed to pack message parameters\n");
+ RETURN( FALSE);
+ }
+
+ /* If this is not a callback and it can be sent now, then send it. */
+ if ((Window->pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
+ {
+
+ Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
+ !Window->Wnd->Unicode,
+ hWnd,
+ Msg,
+ wParam,
+ lParamPacked,
+ lParamBufferSize );
+ if(uResult)
+ {
+ *uResult = Result;
+ }
+ }
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+ if (Window->pti->MessageQueue == Win32Thread->MessageQueue)
+ {
+ if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
+ {
+ DPRINT1("Failed to unpack message parameters\n");
+ RETURN(TRUE);
+ }
+ RETURN(TRUE);
+ }
+
+ if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+ {
+ DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Message->Msg.hwnd = hWnd;
+ Message->Msg.message = Msg;
+ Message->Msg.wParam = wParam;
+ Message->Msg.lParam = lParamPacked;
+ Message->CompletionEvent = NULL;
+ Message->Result = 0;
+ Message->SenderQueue = Win32Thread->MessageQueue;
+ IntReferenceMessageQueue(Message->SenderQueue);
+ IntReferenceMessageQueue(Window->pti->MessageQueue);
+ Message->CompletionCallback = CompletionCallback;
+ Message->CompletionCallbackContext = CompletionCallbackContext;
+ Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT;
+ Message->HasPackedLParam = (lParamBufferSize > 0);
+
+ InsertTailList(&Window->pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
+ InsertTailList(&Win32Thread->MessageQueue->DispatchingMessagesHead, &Message->DispatchingListEntry);
+ IntDereferenceMessageQueue(Window->pti->MessageQueue);
+ IntDereferenceMessageQueue(Message->SenderQueue);
+
+ RETURN(TRUE);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+ END_CLEANUP;
+}
+
+/* This function posts a message if the destination's message queue belongs to
+ another thread, otherwise it sends the message. It does not support broadcast
+ messages! */
+LRESULT FASTCALL
+co_IntPostOrSendMessage( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ ULONG_PTR Result;
+ PTHREADINFO pti;
+ PWINDOW_OBJECT Window;
+
+ if ( hWnd == HWND_BROADCAST )
+ {
+ return 0;
+ }
+
+ if(!(Window = UserGetWindowObject(hWnd)))
+ {
+ return 0;
+ }
+
+ pti = PsGetCurrentThreadWin32Thread();
+
+ if ( Window->pti->MessageQueue != pti->MessageQueue &&
+ FindMsgMemory(Msg) == 0 )
+ {
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ {
+ if ( !co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result) )
+ {
+ Result = 0;
+ }
+ }
+
+ return (LRESULT)Result;
+}
+
+LRESULT FASTCALL
+co_IntDoSendMessage( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ PDOSENDMESSAGE dsm,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo )
+{
+ PTHREADINFO pti;
+ LRESULT Result = TRUE;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ NTUSERSENDMESSAGEINFO Info;
+ MSG UserModeMsg;
+ MSG KernelModeMsg;
+ PMSGMEMORY MsgMemoryEntry;
+
+ RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));
+
+ /* FIXME: Call hooks. */
+ if (HWND_BROADCAST != hWnd)
+ {
+ Window = UserGetWindowObject(hWnd);
+ if ( !Window || !Window->Wnd )
+ {
+ /* Tell usermode to not touch this one */
+ Info.HandledByKernel = TRUE;
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ return 0;
+ }
+ }
+
+ /* Check for an exiting window. */
+ if (Window && Window->state & WINDOWSTATUS_DESTROYING)
+ {
+ DPRINT1("co_IntDoSendMessage Window Exiting!\n");
+ }
+
+ /* See if the current thread can handle the message */
+ pti = PsGetCurrentThreadWin32Thread();
+
+ // This is checked in user mode!!!!!!!
+ if ( HWND_BROADCAST != hWnd &&
+ NULL != pti &&
+ Window->pti->MessageQueue == pti->MessageQueue &&
+ !ISITHOOKED(WH_CALLWNDPROC) &&
+ !ISITHOOKED(WH_CALLWNDPROCRET) &&
+ ( Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST ) )
+ {
+ /* Gather the information usermode needs to call the window proc directly */
+ Info.HandledByKernel = FALSE;
+
+ Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
+ sizeof(BOOL));
+ if (! NT_SUCCESS(Status))
+ {
+ Info.Ansi = ! Window->Wnd->Unicode;
+ }
+
+ Info.Ansi = !Window->Wnd->Unicode;
+ Info.Proc = Window->Wnd->lpfnWndProc;
+ }
+ else
+ {
+ /* Must be handled by other thread */
+// if (HWND_BROADCAST != hWnd)
+// {
+// UserDereferenceObject(Window);
+// }
+ Info.HandledByKernel = TRUE;
+ UserModeMsg.hwnd = hWnd;
+ UserModeMsg.message = Msg;
+ UserModeMsg.wParam = wParam;
+ UserModeMsg.lParam = lParam;
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+
+ Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+ if (! NT_SUCCESS(Status))
+ {
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return (dsm ? 0 : -1);
+ }
+
+ if(!dsm)
+ {
+ Result = co_IntSendMessage( KernelModeMsg.hwnd,
+ KernelModeMsg.message,
+ KernelModeMsg.wParam,
+ KernelModeMsg.lParam );
+ }
+ else
+ {
+ Result = co_IntSendMessageTimeout( KernelModeMsg.hwnd,
+ KernelModeMsg.message,
+ KernelModeMsg.wParam,
+ KernelModeMsg.lParam,
+ dsm->uFlags,
+ dsm->uTimeout,
+ &dsm->Result );
+ }
+
+ Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
+ if (! NT_SUCCESS(Status))
+ {
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return(dsm ? 0 : -1);
+ }
+ }
+
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ }
+
+ return (LRESULT)Result;
+}
+
+
+BOOL FASTCALL
+UserSendNotifyMessage( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ BOOL Result = TRUE;
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ // Basicly the same as IntPostOrSendMessage
+ if (hWnd == HWND_BROADCAST) //Handle Broadcast
+ {
+ HWND *List;
+ PWINDOW_OBJECT DesktopWindow;
+ ULONG i;
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+
+ if (List != NULL)
+ {
+ UserSendNotifyMessage(DesktopWindow->hSelf, Msg, wParam, lParam);
+ for (i = 0; List[i]; i++)
+ {
+ UserSendNotifyMessage(List[i], Msg, wParam, lParam);
+ }
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ ULONG_PTR PResult;
+ PTHREADINFO pti;
+ PWINDOW_OBJECT Window;
+ MSG Message;
+
+ if ( !(Window = UserGetWindowObject(hWnd)) ) return FALSE;
+
+ pti = PsGetCurrentThreadWin32Thread();
+
+ if (Window->pti->MessageQueue != pti->MessageQueue)
+ { // Send message w/o waiting for it.
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ { // Handle message and callback.
+ Message.hwnd = hWnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+
+ Result = co_IntSendMessageTimeoutSingle( hWnd,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_NORMAL,
+ 0,
+ &PResult );
+ }
+ }
+ return Result;
+}
+
+
+DWORD APIENTRY
+IntGetQueueStatus(BOOL ClearChanges)
+{
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE Queue;
+ DWORD Result;
+ DECLARE_RETURN(DWORD);
+
+ DPRINT("Enter IntGetQueueStatus\n");
+
+ pti = PsGetCurrentThreadWin32Thread();
+ Queue = pti->MessageQueue;
+
+ Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
+ if (ClearChanges)
+ {
+ Queue->ChangedBits = 0;
+ }
+
+ RETURN(Result);
+
+CLEANUP:
+ DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_);
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+IntInitMessagePumpHook()
+{
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL APIENTRY
+IntUninitMessagePumpHook()
+{
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <= 0)
+ {
+ return FALSE;
+ }
+ ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/** Functions ******************************************************************/
+
+BOOL APIENTRY
+NtUserPostMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPostMessage\n");
+ UserEnterExclusive();
+
+ RETURN( UserPostMessage(hWnd, Msg, wParam, lParam));
+
+CLEANUP:
+ DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+NtUserPostThreadMessage(DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPostThreadMessage\n");
+ UserEnterExclusive();
+
+ RETURN( UserPostThreadMessage( idThread,
+ Msg,
+ wParam,
+ lParam));
+
+CLEANUP:
+ DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+DWORD APIENTRY
+NtUserQuerySendMessage(DWORD Unknown0)
+{
+ UNIMPLEMENTED;
+
+ return 0;
+}
+
+
+////////// API on the way out!
+LRESULT APIENTRY
+NtUserSendMessageTimeout( HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo )
+{
+ DOSENDMESSAGE dsm;
+ LRESULT Result;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSendMessageTimeout\n");
+ UserEnterExclusive();
+
+ dsm.uFlags = uFlags;
+ dsm.uTimeout = uTimeout;
+ Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
+ if(uResult != NULL && Result != 0)
+ {
+ NTSTATUS Status;
+
+ Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( FALSE);
+ }
+ }
+ RETURN( Result);
+
+CLEANUP:
+ DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+LRESULT APIENTRY
+NtUserSendMessage( HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo )
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSendMessage\n");
+ UserEnterExclusive();
+
+ RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo));
+
+CLEANUP:
+ DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+//////////
+
+BOOL APIENTRY
+NtUserWaitMessage(VOID)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("EnterNtUserWaitMessage\n");
+ UserEnterExclusive();
+
+ RETURN(co_IntWaitMessage(NULL, 0, 0));
+
+CLEANUP:
+ DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+BOOL APIENTRY
+NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax )
+/*
+ * FUNCTION: Get a message from the calling thread's message queue.
+ * ARGUMENTS:
+ * UnsafeMsg - Pointer to the structure which receives the returned message.
+ * Wnd - Window whose messages are to be retrieved.
+ * MsgFilterMin - Integer value of the lowest message value to be
+ * retrieved.
+ * MsgFilterMax - Integer value of the highest message value to be
+ * retrieved.
+ */
+{
+ BOOL GotMessage;
+ NTUSERGETMESSAGEINFO Info;
+ NTSTATUS Status;
+ /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID UserMem;
+ UINT Size;
+ USER_MESSAGE Msg;
+ DECLARE_RETURN(BOOL);
+// USER_REFERENCE_ENTRY Ref;
+
+ DPRINT("Enter NtUserGetMessage\n");
+ UserEnterExclusive();
+
+ /* Validate input */
+ if (hWnd && !(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(-1);
+ }
+
+// if (Window) UserRefObjectCo(Window, &Ref);
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
+ MsgFilterMin = 0;
+ MsgFilterMax = 0;
+ }
+
+ do
+ {
+ GotMessage = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, PM_REMOVE);
+ if (GotMessage)
+ {
+ Info.Msg = Msg.Msg;
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ Info.LParamSize = 0;
+ }
+ else
+ {
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+ Info.Msg.lParam);
+ /* Allocate required amount of user-mode memory */
+ Info.LParamSize = Size;
+ UserMem = NULL;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+ &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ /* Transfer lParam data to user-mode mem */
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+ &Info.LParamSize, MEM_DECOMMIT);
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ Info.Msg.lParam = (LPARAM) UserMem;
+ }
+ if (Msg.FreeLParam && 0 != Msg.Msg.lParam)
+ {
+ ExFreePool((void *) Msg.Msg.lParam);
+ }
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ }
+ else if (! co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax))
+ {
+ RETURN( (BOOL) -1);
+ }
+ }
+ while (! GotMessage);
+
+ RETURN( WM_QUIT != Info.Msg.message);
+
+CLEANUP:
+// if (Window) UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserGetMessage\n");
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+BOOL
+APIENTRY
+NtUserGetMessageX(
+ PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax)
+{
+ MSG Msg;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetMessage\n");
+ UserEnterExclusive();
+
+ if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( Ret);
+ }
+
+ RtlZeroMemory(&Msg, sizeof(MSG));
+
+ Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE);
+
+ if (Ret)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(pMsg, sizeof(MSG), 1);
+ RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Ret = FALSE;
+ }
+ _SEH2_END;
+ }
+ RETURN( Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetMessage\n");
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg)
+{
+ NTSTATUS Status;
+ BOOL Present;
+ NTUSERGETMESSAGEINFO Info;
+ PWINDOW_OBJECT Window;
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID UserMem;
+ UINT Size;
+ USER_MESSAGE Msg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPeekMessage\n");
+ UserEnterExclusive();
+
+ if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
+ hWnd = (HWND)1;
+
+ /* Validate input */
+ if (hWnd && hWnd != (HWND)1)
+ {
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(-1);
+ }
+ }
+ else
+ {
+ Window = (PWINDOW_OBJECT)hWnd;
+ }
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
+ MsgFilterMin = 0;
+ MsgFilterMax = 0;
+ }
+
+ Present = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg);
+ if (Present)
+ {
+
+ Info.Msg = Msg.Msg;
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ Info.LParamSize = 0;
+ }
+ else
+ {
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+ Info.Msg.lParam);
+ /* Allocate required amount of user-mode memory */
+ Info.LParamSize = Size;
+ UserMem = NULL;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+ &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ /* Transfer lParam data to user-mode mem */
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+ &Info.LParamSize, MEM_RELEASE);
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ Info.Msg.lParam = (LPARAM) UserMem;
+ }
+ if (RemoveMsg && Msg.FreeLParam && 0 != Msg.Msg.lParam)
+ {
+ ExFreePool((void *) Msg.Msg.lParam);
+ }
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ }
+
+ RETURN( Present);
+
+CLEANUP:
+ DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL
+APIENTRY
+NtUserPeekMessageX(
+ PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg)
+{
+ MSG Msg;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPeekMessage\n");
+ UserEnterExclusive();
+
+ if ( RemoveMsg & PM_BADMSGFLAGS )
+ {
+ SetLastWin32Error(ERROR_INVALID_FLAGS);
+ RETURN( Ret);
+ }
+
+ RtlZeroMemory(&Msg, sizeof(MSG));
+
+ Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE);
+
+ if (Ret)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(pMsg, sizeof(MSG), 1);
+ RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Ret = FALSE;
+ }
+ _SEH2_END;
+ }
+ RETURN( Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL
+APIENTRY
+NtUserCallMsgFilter(
+ LPMSG lpmsg,
+ INT code)
+{
+ BOOL BadChk = FALSE, Ret = FALSE;
+ MSG Msg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCallMsgFilter\n");
+ UserEnterExclusive();
+ if (lpmsg)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory( &Msg,
+ (PVOID)lpmsg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ }
+ else
+ RETURN( FALSE);
+
+ if (BadChk) RETURN( FALSE);
+
+ if ( ISITHOOKED(WH_SYSMSGFILTER) &&
+ co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
+ {
+ Ret = TRUE;
+ }
+ else
+ {
+ if ( ISITHOOKED(WH_MSGFILTER) )
+ {
+ Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
+ }
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory((PVOID)lpmsg,
+ &Msg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk) RETURN( FALSE);
+ RETURN( Ret)
+
+CLEANUP:
+ DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+LRESULT APIENTRY
+NtUserDispatchMessage(PMSG UnsafeMsgInfo)
+{
+ LRESULT Res = 0;
+ BOOL Hit = FALSE;
+ MSG SafeMsg;
+
+ UserEnterExclusive();
+ _SEH2_TRY
+ {
+ ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
+ RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Hit = TRUE;
+ }
+ _SEH2_END;
+
+ if (!Hit) Res = IntDispatchMessage(&SafeMsg);
+
+ UserLeave();
+ return Res;
+}
+
+
+BOOL APIENTRY
+NtUserTranslateMessage(LPMSG lpMsg,
+ UINT flags)
+{
+ NTSTATUS Status;
+ MSG SafeMsg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserTranslateMessage\n");
+ UserEnterExclusive();
+
+ Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( FALSE);
+ }
+
+ RETURN( IntTranslateKbdMessage(&SafeMsg, flags));
+
+CLEANUP:
+ DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+NtUserMessageCall(
+ HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ ULONG_PTR ResultInfo,
+ DWORD dwType, // fnID?
+ BOOL Ansi)
+{
+ LRESULT lResult = 0;
+ BOOL Ret = FALSE;
+ BOOL BadChk = FALSE;
+ PWINDOW_OBJECT Window = NULL;
+ USER_REFERENCE_ENTRY Ref;
+
+ UserEnterExclusive();
+
+ /* Validate input */
+ if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
+ {
+ UserLeave();
+ return FALSE;
+ }
+ switch(dwType)
+ {
+ case FNID_DEFWINDOWPROC:
+ UserRefObjectCo(Window, &Ref);
+ lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi);
+ Ret = TRUE;
+ UserDerefObjectCo(Window);
+ break;
+ case FNID_SENDNOTIFYMESSAGE:
+ Ret = UserSendNotifyMessage(hWnd, Msg, wParam, lParam);
+ break;
+ case FNID_BROADCASTSYSTEMMESSAGE:
+ {
+ BROADCASTPARM parm;
+ DWORD_PTR RetVal = 0;
+
+ if (ResultInfo)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)ResultInfo,
+ sizeof(BROADCASTPARM),
+ 1);
+ RtlCopyMemory(&parm, (PVOID)ResultInfo, sizeof(BROADCASTPARM));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk) break;
+ }
+ else
+ break;
+
+ if ( parm.recipients & BSM_ALLDESKTOPS ||
+ parm.recipients == BSM_ALLCOMPONENTS )
+ {
+ }
+ else if (parm.recipients & BSM_APPLICATIONS)
+ {
+ if (parm.flags & BSF_QUERY)
+ {
+ if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG)
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_ABORTIFHUNG,
+ 2000,
+ &RetVal);
+ }
+ else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG)
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_NOTIMEOUTIFNOTHUNG,
+ 2000,
+ &RetVal);
+ }
+ else
+ {
+ co_IntSendMessageTimeout( HWND_BROADCAST,
+ Msg,
+ wParam,
+ lParam,
+ SMTO_NORMAL,
+ 2000,
+ &RetVal);
+ }
+ }
+ else if (parm.flags & BSF_POSTMESSAGE)
+ {
+ Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
+ }
+ else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+ {
+ Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
+ }
+ }
+ }
+ break;
+ case FNID_SENDMESSAGECALLBACK:
+ break;
+ // CallNextHook bypass.
+ case FNID_CALLWNDPROC:
+ case FNID_CALLWNDPROCRET:
+ {
+ PCLIENTINFO ClientInfo = GetWin32ClientInfo();
+ PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+
+ if (!ClientInfo || !Hook) break;
+
+ UserReferenceObject(Hook);
+
+ if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
+ {
+ UserDereferenceObject(Hook);
+ break;
+ }
+
+ NextObj = IntGetNextHook(Hook);
+ ClientInfo->phkCurrent = NextObj;
+
+ if ( Hook->HookId == WH_CALLWNDPROC)
+ {
+ CWPSTRUCT CWP;
+ CWP.hwnd = hWnd;
+ CWP.message = Msg;
+ CWP.wParam = wParam;
+ CWP.lParam = lParam;
+ DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook, NextObj );
+
+ lResult = co_IntCallHookProc( Hook->HookId,
+ HC_ACTION,
+ ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+ (LPARAM)&CWP,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ }
+ else
+ {
+ CWPRETSTRUCT CWPR;
+ CWPR.hwnd = hWnd;
+ CWPR.message = Msg;
+ CWPR.wParam = wParam;
+ CWPR.lParam = lParam;
+ CWPR.lResult = ClientInfo->dwHookData;
+
+ lResult = co_IntCallHookProc( Hook->HookId,
+ HC_ACTION,
+ ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+ (LPARAM)&CWPR,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ }
+ UserDereferenceObject(Hook);
+ lResult = (LRESULT) NextObj;
+ }
+ break;
+ }
+
+ switch(dwType)
+ {
+ case FNID_DEFWINDOWPROC:
+ case FNID_CALLWNDPROC:
+ case FNID_CALLWNDPROCRET:
+ if (ResultInfo)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)ResultInfo, sizeof(LRESULT), 1);
+ RtlCopyMemory((PVOID)ResultInfo, &lResult, sizeof(LRESULT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ }
+ break;
+ default:
+ break;
+ }
+
+ UserLeave();
+
+ return BadChk ? FALSE : Ret;
+}
+
+#define INFINITE 0xFFFFFFFF
+#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
+
+DWORD
+APIENTRY
+NtUserWaitForInputIdle(
+ IN HANDLE hProcess,
+ IN DWORD dwMilliseconds,
+ IN BOOL Unknown2)
+{
+ PEPROCESS Process;
+ PPROCESSINFO W32Process;
+ NTSTATUS Status;
+ HANDLE Handles[2];
+ LARGE_INTEGER Timeout;
+ ULONGLONG StartTime, Run, Elapsed = 0;
+
+ UserEnterExclusive();
+
+ Status = ObReferenceObjectByHandle(hProcess,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ UserMode,
+ (PVOID*)&Process,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ UserLeave();
+ SetLastNtError(Status);
+ return WAIT_FAILED;
+ }
+
+ W32Process = (PPROCESSINFO)Process->Win32Process;
+ if (!W32Process)
+ {
+ ObDereferenceObject(Process);
+ UserLeave();
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return WAIT_FAILED;
+ }
+
+ EngCreateEvent((PEVENT *)&W32Process->InputIdleEvent);
+
+ Handles[0] = Process;
+ Handles[1] = W32Process->InputIdleEvent;
+
+ if (!Handles[1])
+ {
+ ObDereferenceObject(Process);
+ UserLeave();
+ return STATUS_SUCCESS; /* no event to wait on */
+ }
+
+ StartTime = EngGetTickCount();
+
+ Run = dwMilliseconds;
+
+ DPRINT("WFII: waiting for %p\n", Handles[1] );
+ do
+ {
+ Timeout.QuadPart = Run - Elapsed;
+ UserLeave();
+ Status = KeWaitForMultipleObjects( 2,
+ Handles,
+ WaitAny,
+ UserRequest,
+ UserMode,
+ FALSE,
+ dwMilliseconds == INFINITE ? NULL : &Timeout,
+ NULL);
+ UserEnterExclusive();
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ Status = WAIT_FAILED;
+ goto WaitExit;
+ }
+
+ switch (Status)
+ {
+ case STATUS_WAIT_0:
+ Status = WAIT_FAILED;
+ goto WaitExit;
+
+ case STATUS_WAIT_2:
+ {
+ USER_MESSAGE Msg;
+ co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
+ break;
+ }
+
+ case STATUS_USER_APC:
+ case STATUS_ALERTED:
+ case STATUS_TIMEOUT:
+ DPRINT1("WFII: timeout\n");
+ Status = STATUS_TIMEOUT;
+ goto WaitExit;
+
+ default:
+ DPRINT1("WFII: finished\n");
+ Status = STATUS_SUCCESS;
+ goto WaitExit;
+ }
+
+ if (dwMilliseconds != INFINITE)
+ {
+ Elapsed = EngGetTickCount() - StartTime;
+
+ if (Elapsed > Run)
+ Status = STATUS_TIMEOUT;
+ break;
+ }
+ }
+ while (1);
+
+WaitExit:
+ if (W32Process->InputIdleEvent)
+ {
+ EngFreeMem((PVOID)W32Process->InputIdleEvent);
+ W32Process->InputIdleEvent = NULL;
+ }
+ ObDereferenceObject(Process);
+ UserLeave();
+ return Status;
+}
+
+/* EOF */
--- /dev/null
- MonitorRect.left = 0; /* FIXME: get origin */
- MonitorRect.top = 0; /* FIXME: get origin */
- MonitorRect.right = MonitorRect.left + Monitor->GdiDevice->gdiinfo.ulHorzRes;
- MonitorRect.bottom = MonitorRect.top + Monitor->GdiDevice->gdiinfo.ulVertRes;
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Monitor support
+ * FILE: subsys/win32k/ntuser/monitor.c
+ * PROGRAMER: Anich Gregor (blight@blight.eu.org)
+ * REVISION HISTORY:
+ * 26-02-2004 Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+/* FIXME: find include file for these */
+#define MONITORINFOF_PRIMARY 1
+#define MONITOR_DEFAULTTONULL 0
+#define MONITOR_DEFAULTTOPRIMARY 1
+#define MONITOR_DEFAULTTONEAREST 2
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+/* list of monitors */
+static PMONITOR gMonitorList = NULL;
+
+/* INITALIZATION FUNCTIONS ****************************************************/
+
+NTSTATUS
+InitMonitorImpl()
+{
+ DPRINT("Initializing monitor implementation...\n");
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CleanupMonitorImpl()
+{
+ DPRINT("Cleaning up monitor implementation...\n");
+ /* FIXME: Destroy monitor objects? */
+
+ return STATUS_SUCCESS;
+}
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef ABS
+# define ABS(a) ((a) < (0) ? (-(a)) : (a))
+#endif
+
+/* IntCreateMonitorObject
+ *
+ * Creates a MONITOR
+ *
+ * Return value
+ * If the function succeeds a pointer to a MONITOR is returned. On failure
+ * NULL is returned.
+ */
+static
+PMONITOR
+IntCreateMonitorObject()
+{
+ HANDLE Handle;
+ PMONITOR Monitor;
+
+ Monitor = UserCreateObject(gHandleTable, NULL, &Handle, otMonitor, sizeof (MONITOR));
+ if (Monitor == NULL)
+ {
+ return NULL;
+ }
+
+ ExInitializeFastMutex(&Monitor->Lock);
+
+ return Monitor;
+}
+
+/* IntDestroyMonitorObject
+ *
+ * Destroys a MONITOR
+ * You have to be the owner of the monitors lock to safely destroy it.
+ *
+ * Arguments
+ *
+ * pMonitor
+ * Pointer to the MONITOR which shall be deleted
+ */
+static
+void
+IntDestroyMonitorObject(IN PMONITOR pMonitor)
+{
+ RtlFreeUnicodeString(&pMonitor->DeviceName);
+ UserDereferenceObject(pMonitor);
+}
+
+
+PMONITOR FASTCALL
+UserGetMonitorObject(IN HMONITOR hMonitor)
+{
+ PMONITOR Monitor;
+
+ if (!hMonitor)
+ {
+ SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);
+ return NULL;
+ }
+
+
+ Monitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor);
+ if (!Monitor)
+ {
+ SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);
+ return NULL;
+ }
+
+ ASSERT(Monitor->head.cLockObj >= 0);
+
+ return Monitor;
+}
+
+
+/* IntAttachMonitor
+ *
+ * Creates a new MONITOR and appends it to the list of monitors.
+ *
+ * Arguments
+ *
+ * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
+ * DisplayNumber Display Number (starting with 0)
+ *
+ * Return value
+ * Returns a NTSTATUS
+ */
+NTSTATUS
+IntAttachMonitor(IN PDEVOBJ *pGdiDevice,
+ IN ULONG DisplayNumber)
+{
+ PMONITOR Monitor;
+ WCHAR Buffer[CCHDEVICENAME];
+
+ DPRINT("Attaching monitor...\n");
+
+ /* create new monitor object */
+ Monitor = IntCreateMonitorObject();
+ if (Monitor == NULL)
+ {
+ DPRINT("Couldnt create monitor object\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ _snwprintf(Buffer, CCHDEVICENAME, L"\\\\.\\DISPLAY%d", DisplayNumber + 1);
+ if (!RtlCreateUnicodeString(&Monitor->DeviceName, Buffer))
+ {
+ DPRINT("Couldn't duplicate monitor name!\n");
+ UserDereferenceObject(Monitor);
+ UserDeleteObject(UserHMGetHandle(Monitor), otMonitor);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Monitor->GdiDevice = pGdiDevice;
+ Monitor->rcMonitor.left = 0;
+ Monitor->rcMonitor.top = 0;
+ Monitor->rcMonitor.right = Monitor->rcMonitor.left + pGdiDevice->gdiinfo.ulHorzRes;
+ Monitor->rcMonitor.bottom = Monitor->rcMonitor.top + pGdiDevice->gdiinfo.ulVertRes;
+ Monitor->rcWork = Monitor->rcMonitor;
+ Monitor->cWndStack = 0;
+
+ Monitor->hrgnMonitor = IntSysCreateRectRgnIndirect( &Monitor->rcMonitor );
+
+ IntGdiSetRegionOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);
+
+ if (gMonitorList == NULL)
+ {
+ DPRINT("Primary monitor is beeing attached\n");
+ Monitor->IsPrimary = TRUE;
+ gMonitorList = Monitor;
+ }
+ else
+ {
+ PMONITOR p;
+ DPRINT("Additional monitor is beeing attached\n");
+ for (p = gMonitorList; p->Next != NULL; p = p->Next)
+ {
+ p->Next = Monitor;
+ }
+ Monitor->Prev = p;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* IntDetachMonitor
+ *
+ * Deletes a MONITOR and removes it from the list of monitors.
+ *
+ * Arguments
+ *
+ * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
+ *
+ * Return value
+ * Returns a NTSTATUS
+ */
+NTSTATUS
+IntDetachMonitor(IN PDEVOBJ *pGdiDevice)
+{
+ PMONITOR Monitor;
+
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ if (Monitor->GdiDevice == pGdiDevice)
+ break;
+ }
+
+ if (Monitor == NULL)
+ {
+ /* no monitor for given device found */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (Monitor->IsPrimary && (Monitor->Next != NULL || Monitor->Prev != NULL))
+ {
+ PMONITOR NewPrimaryMonitor = (Monitor->Prev != NULL) ? (Monitor->Prev) : (Monitor->Next);
+
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor->Lock);
+ NewPrimaryMonitor->IsPrimary = TRUE;
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor->Lock);
+ }
+
+ if (gMonitorList == Monitor)
+ {
+ gMonitorList = Monitor->Next;
+ if (Monitor->Next != NULL)
+ Monitor->Next->Prev = NULL;
+ }
+ else
+ {
+ Monitor->Prev->Next = Monitor->Next;
+ if (Monitor->Next != NULL)
+ Monitor->Next->Prev = Monitor->Prev;
+ }
+
+ if (Monitor->hrgnMonitor)
+ REGION_FreeRgnByHandle(Monitor->hrgnMonitor);
+
+ IntDestroyMonitorObject(Monitor);
+
+ return STATUS_SUCCESS;
+}
+
+/* IntGetPrimaryMonitor
+ *
+ * Returns a PMONITOR for the primary monitor
+ *
+ * Return value
+ * PMONITOR
+ */
+PMONITOR
+FASTCALL
+IntGetPrimaryMonitor()
+{
+ PMONITOR Monitor;
+
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ /* FIXME: I guess locking the monitor is not neccessary to read 1 int */
+ if (Monitor->IsPrimary)
+ break;
+ }
+
+ return Monitor;
+}
+
+/* IntGetMonitorsFromRect
+ *
+ * Returns a list of monitor handles/rectangles. The rectangles in the list are
+ * the areas of intersection with the monitors.
+ *
+ * Arguments
+ *
+ * pRect
+ * Rectangle in desktop coordinates. If this is NULL all monitors are
+ * returned and the rect list is filled with the sizes of the monitors.
+ *
+ * hMonitorList
+ * Pointer to an array of HMONITOR which is filled with monitor handles.
+ * Can be NULL
+ *
+ * monitorRectList
+ * Pointer to an array of RECT which is filled with intersection rects in
+ * desktop coordinates.
+ * Can be NULL, will be ignored if no intersecting monitor is found and
+ * flags is MONITOR_DEFAULTTONEAREST
+ *
+ * listSize
+ * Size of the hMonitorList and monitorRectList arguments. If this is zero
+ * hMonitorList and monitorRectList are ignored.
+ *
+ * flags
+ * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
+ *
+ * Returns
+ * The number of monitors which intersect the specified region.
+ */
+static
+UINT
+IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
+ OPTIONAL OUT HMONITOR *hMonitorList,
+ OPTIONAL OUT PRECTL monitorRectList,
+ OPTIONAL IN DWORD listSize,
+ OPTIONAL IN DWORD flags)
+{
+ PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL;
+ UINT iCount = 0;
+ LONG iNearestDistanceX = 0x7fffffff, iNearestDistanceY = 0x7fffffff;
+
+ /* find monitors which intersect the rectangle */
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ RECTL MonitorRect, IntersectionRect;
+
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock);
- MonitorInfo.rcMonitor.left = 0; /* FIXME: get origin */
- MonitorInfo.rcMonitor.top = 0; /* FIXME: get origin */
- MonitorInfo.rcMonitor.right = MonitorInfo.rcMonitor.left + Monitor->GdiDevice->gdiinfo.ulHorzRes;
- MonitorInfo.rcMonitor.bottom = MonitorInfo.rcMonitor.top + Monitor->GdiDevice->gdiinfo.ulVertRes;
- MonitorInfo.rcWork = MonitorInfo.rcMonitor; /* FIXME: use DEVMODE panning to calculate work area? */
++ MonitorRect = Monitor->rcMonitor;
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock);
+
+ DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
+ MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);
+
+ if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary)
+ {
+ PrimaryMonitor = Monitor;
+ }
+
+ if (pRect != NULL)
+ {
+ BOOL intersects = TRUE;
+
+ /* check if the rect intersects the monitor */
+ if ((pRect->right < MonitorRect.left) || (pRect->left > MonitorRect.right) ||
+ (pRect->bottom < MonitorRect.top) || (pRect->top > MonitorRect.bottom))
+ {
+ intersects = FALSE;
+ }
+
+ if (flags == MONITOR_DEFAULTTONEAREST && !intersects)
+ {
+ INT distanceX, distanceY;
+
+ distanceX = MIN(ABS(MonitorRect.left - pRect->right),
+ ABS(pRect->left - MonitorRect.right));
+ distanceY = MIN(ABS(MonitorRect.top - pRect->bottom),
+ ABS(pRect->top - MonitorRect.bottom));
+
+ if (((distanceX < iNearestDistanceX) && (distanceY <= iNearestDistanceY)) ||
+ ((distanceX <= iNearestDistanceX) && (distanceY < iNearestDistanceY)))
+ {
+ iNearestDistanceX = distanceX;
+ iNearestDistanceY = distanceY;
+ NearestMonitor = Monitor;
+ }
+ }
+
+ if (!intersects)
+ continue;
+
+ /* calculate intersection */
+ IntersectionRect.left = MAX(MonitorRect.left, pRect->left);
+ IntersectionRect.top = MAX(MonitorRect.top, pRect->top);
+ IntersectionRect.right = MIN(MonitorRect.right, pRect->right);
+ IntersectionRect.bottom = MIN(MonitorRect.bottom, pRect->bottom);
+ }
+ else
+ {
+ IntersectionRect = MonitorRect;
+ }
+
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(Monitor);
+ if (monitorRectList != NULL)
+ monitorRectList[iCount] = IntersectionRect;
+ }
+ iCount++;
+ }
+
+ if (iCount == 0 && flags == MONITOR_DEFAULTTONEAREST)
+ {
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(NearestMonitor);
+ }
+ iCount++;
+ }
+ else if (iCount == 0 && flags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor);
+ }
+ iCount++;
+ }
+ return iCount;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/* NtUserEnumDisplayMonitors
+ *
+ * Enumerates display monitors which intersect the given HDC/cliprect
+ *
+ * Arguments
+ *
+ * hDC
+ * Handle to a DC for which to enum intersecting monitors. If this is NULL
+ * it returns all monitors which are part of the current virtual screen.
+ *
+ * pRect
+ * Clipping rectangle with coordinate system origin at the DCs origin if the
+ * given HDC is not NULL or in virtual screen coordinated if it is NULL.
+ * Can be NULL
+ *
+ * hMonitorList
+ * Pointer to an array of HMONITOR which is filled with monitor handles.
+ * Can be NULL
+ *
+ * monitorRectList
+ * Pointer to an array of RECT which is filled with intersection rectangles.
+ * Can be NULL
+ *
+ * listSize
+ * Size of the hMonitorList and monitorRectList arguments. If this is zero
+ * hMonitorList and monitorRectList are ignored.
+ *
+ * Returns
+ * The number of monitors which intersect the specified region or -1 on failure.
+ */
+INT
+APIENTRY
+NtUserEnumDisplayMonitors(
+ OPTIONAL IN HDC hDC,
+ OPTIONAL IN LPCRECTL pRect,
+ OPTIONAL OUT HMONITOR *hMonitorList,
+ OPTIONAL OUT PRECTL monitorRectList,
+ OPTIONAL IN DWORD listSize)
+{
+ INT numMonitors, i;
+ HMONITOR *safeHMonitorList = NULL;
+ PRECTL safeRectList = NULL;
+ RECTL rect, *myRect;
+ RECTL dcRect;
+ NTSTATUS status;
+
+ /* get rect */
+ if (pRect != NULL)
+ {
+ status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
+ if (!NT_SUCCESS(status))
+ {
+ DPRINT("MmCopyFromCaller() failed!\n");
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+
+ if (hDC != NULL)
+ {
+ PDC dc;
+ HRGN dcVisRgn;
+ INT regionType;
+
+ /* get visible region bounding rect */
+ dc = DC_LockDc(hDC);
+ if (dc == NULL)
+ {
+ DPRINT("DC_LockDc() failed!\n");
+ /* FIXME: setlasterror? */
+ return -1;
+ }
+ dcVisRgn = dc->prgnVis->BaseObject.hHmgr;
+ DC_UnlockDc(dc);
+
+ regionType = NtGdiGetRgnBox(dcVisRgn, &dcRect);
+ if (regionType == 0)
+ {
+ DPRINT("NtGdiGetRgnBox() failed!\n");
+ return -1;
+ }
+ if (regionType == NULLREGION)
+ return 0;
+ if (regionType == COMPLEXREGION)
+ { /* TODO: warning */
+ }
+
+ /* if hDC and pRect are given the area of interest is pRect with
+ coordinate origin at the DC position */
+ if (pRect != NULL)
+ {
+ rect.left += dcRect.left;
+ rect.right += dcRect.left;
+ rect.top += dcRect.top;
+ rect.bottom += dcRect.top;
+ }
+ /* if hDC is given and pRect is not the area of interest is the
+ bounding rect of hDC */
+ else
+ {
+ rect = dcRect;
+ }
+ }
+
+ if (hDC == NULL && pRect == NULL)
+ myRect = NULL;
+ else
+ myRect = ▭
+
+ /* find intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(myRect, NULL, NULL, 0, 0);
+ if (numMonitors == 0 || listSize == 0 ||
+ (hMonitorList == NULL && monitorRectList == NULL))
+ {
+ DPRINT("numMonitors = %d\n", numMonitors);
+ return numMonitors;
+ }
+
+ if (hMonitorList != NULL && listSize != 0)
+ {
+ safeHMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * listSize);
+ if (safeHMonitorList == NULL)
+ {
+ /* FIXME: SetLastWin32Error? */
+ return -1;
+ }
+ }
+ if (monitorRectList != NULL && listSize != 0)
+ {
+ safeRectList = ExAllocatePool(PagedPool, sizeof (RECT) * listSize);
+ if (safeRectList == NULL)
+ {
+ ExFreePool(safeHMonitorList);
+ /* FIXME: SetLastWin32Error? */
+ return -1;
+ }
+ }
+
+ /* get intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(myRect, safeHMonitorList, safeRectList,
+ listSize, 0 );
+
+ if (hDC != NULL && pRect != NULL && safeRectList != NULL)
+ for (i = 0; i < numMonitors; i++)
+ {
+ safeRectList[i].left -= dcRect.left;
+ safeRectList[i].right -= dcRect.left;
+ safeRectList[i].top -= dcRect.top;
+ safeRectList[i].bottom -= dcRect.top;
+ }
+
+ /* output result */
+ if (hMonitorList != NULL && listSize != 0)
+ {
+ status = MmCopyToCaller(hMonitorList, safeHMonitorList, sizeof (HMONITOR) * listSize);
+ ExFreePool(safeHMonitorList);
+ if (!NT_SUCCESS(status))
+ {
+ ExFreePool(safeRectList);
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+ if (monitorRectList != NULL && listSize != 0)
+ {
+ status = MmCopyToCaller(monitorRectList, safeRectList, sizeof (RECT) * listSize);
+ ExFreePool(safeRectList);
+ if (!NT_SUCCESS(status))
+ {
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+
+ return numMonitors;
+}
+
+/* NtUserGetMonitorInfo
+ *
+ * Retrieves information about a given monitor
+ *
+ * Arguments
+ *
+ * hMonitor
+ * Handle to a monitor for which to get information
+ *
+ * pMonitorInfo
+ * Pointer to a MONITORINFO struct which is filled with the information.
+ * The cbSize member must be set to sizeof(MONITORINFO) or
+ * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
+ * from MONITORINFO will be filled.
+ *
+ * pDevice
+ * Pointer to a UNICODE_STRING which will recieve the device's name. The
+ * length should be CCHDEVICENAME
+ * Can be NULL
+ *
+ * Return value
+ * TRUE on success; FALSE on failure (calls SetLastNtError())
+ *
+ */
+BOOL
+APIENTRY
+NtUserGetMonitorInfo(
+ IN HMONITOR hMonitor,
+ OUT LPMONITORINFO pMonitorInfo)
+{
+ PMONITOR Monitor;
+ MONITORINFOEXW MonitorInfo;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetMonitorInfo\n");
+ UserEnterShared();
+
+ /* get monitor object */
+ if (!(Monitor = UserGetMonitorObject(hMonitor)))
+ {
+ DPRINT("Couldnt find monitor 0x%lx\n", hMonitor);
+ RETURN(FALSE);
+ }
+
+ if(pMonitorInfo == NULL)
+ {
+ SetLastNtError(STATUS_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+
+ /* get size of pMonitorInfo */
+ Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfo->cbSize, sizeof (MonitorInfo.cbSize));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+ if ((MonitorInfo.cbSize != sizeof (MONITORINFO)) &&
+ (MonitorInfo.cbSize != sizeof (MONITORINFOEXW)))
+ {
+ SetLastNtError(STATUS_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+
+ /* fill monitor info */
++ MonitorInfo.rcMonitor = Monitor->rcMonitor;
++ MonitorInfo.rcWork = Monitor->rcWork;
+ MonitorInfo.dwFlags = 0;
+
+ if (Monitor->IsPrimary)
+ MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
+
+ /* fill device name */
+ if (MonitorInfo.cbSize == sizeof (MONITORINFOEXW))
+ {
+ WCHAR nul = L'\0';
+ INT len = Monitor->DeviceName.Length;
+ if (len >= CCHDEVICENAME * sizeof (WCHAR))
+ len = (CCHDEVICENAME - 1) * sizeof (WCHAR);
+
+ memcpy(MonitorInfo.szDevice, Monitor->DeviceName.Buffer, len);
+ memcpy(MonitorInfo.szDevice + (len / sizeof (WCHAR)), &nul, sizeof (WCHAR));
+ }
+
+ /* output data */
+ Status = MmCopyToCaller(pMonitorInfo, &MonitorInfo, MonitorInfo.cbSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ DPRINT("GetMonitorInfo: success\n");
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/* NtUserMonitorFromPoint
+ *
+ * Returns a handle to the monitor containing the given point.
+ *
+ * Arguments
+ *
+ * point
+ * Point for which to find monitor
+ *
+ * dwFlags
+ * Specifies the behaviour if the point isn't on any of the monitors.
+ *
+ * Return value
+ * If the point is found a handle to the monitor is returned; if not the
+ * return value depends on dwFlags
+ */
+HMONITOR
+APIENTRY
+NtUserMonitorFromPoint(
+ IN POINT point,
+ IN DWORD dwFlags)
+{
+ INT NumMonitors;
+ RECTL InRect;
+ HMONITOR hMonitor = NULL;
+
+ /* fill inRect */
+ InRect.left = InRect.right = point.x;
+ InRect.top = InRect.bottom = point.y;
+
+ /* find intersecting monitor */
+ NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, 0);
+ if (NumMonitors < 0)
+ {
+ return (HMONITOR)NULL;
+ }
+
+ if (hMonitor == NULL)
+ {
+ if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ PMONITOR MonitorObj = IntGetPrimaryMonitor();
+ if (MonitorObj)
+ hMonitor = UserHMGetHandle(MonitorObj);
+ }
+ else if (dwFlags == MONITOR_DEFAULTTONEAREST)
+ {
+ NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL,
+ 1, MONITOR_DEFAULTTONEAREST);
+ /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
+ }
+ /* else flag is DEFAULTTONULL */
+ }
+
+ return hMonitor;
+}
+
+/* NtUserMonitorFromRect
+ *
+ * Returns a handle to the monitor having the largest intersection with a
+ * given rectangle
+ *
+ * Arguments
+ *
+ * pRect
+ * Pointer to a RECT for which to find monitor
+ *
+ * dwFlags
+ * Specifies the behaviour if no monitor intersects the given rect
+ *
+ * Return value
+ * If a monitor intersects the rect a handle to it is returned; if not the
+ * return value depends on dwFlags
+ */
+HMONITOR
+APIENTRY
+NtUserMonitorFromRect(
+ IN LPCRECTL pRect,
+ IN DWORD dwFlags)
+{
+ INT numMonitors, iLargestArea = -1, i;
+ PRECTL rectList;
+ HMONITOR *hMonitorList;
+ HMONITOR hMonitor = NULL;
+ RECTL rect;
+ NTSTATUS status;
+
+ /* get rect */
+ status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
+ if (!NT_SUCCESS(status))
+ {
+ SetLastNtError(status);
+ return (HMONITOR)NULL;
+ }
+
+ /* find intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(&rect, NULL, NULL, 0, 0);
+ if (numMonitors < 0)
+ {
+ return (HMONITOR)NULL;
+ }
+
+ if (numMonitors == 0)
+ {
+ if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ PMONITOR monitorObj = IntGetPrimaryMonitor();
+ if (monitorObj)
+ return UserHMGetHandle(monitorObj);
+ }
+ else if (dwFlags == MONITOR_DEFAULTTONEAREST)
+ {
+ numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL,
+ 1, MONITOR_DEFAULTTONEAREST);
+ if (numMonitors <= 0)
+ {
+ /* error? */
+ return (HMONITOR)NULL;
+ }
+
+ if (numMonitors > 0)
+ return hMonitor;
+ }
+ /* else flag is DEFAULTTONULL */
+ return (HMONITOR)NULL;
+ }
+
+ hMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * numMonitors);
+ if (hMonitorList == NULL)
+ {
+ /* FIXME: SetLastWin32Error? */
+ return (HMONITOR)NULL;
+ }
+ rectList = ExAllocatePool(PagedPool, sizeof (RECT) * numMonitors);
+ if (rectList == NULL)
+ {
+ ExFreePool(hMonitorList);
+ /* FIXME: SetLastWin32Error? */
+ return (HMONITOR)NULL;
+ }
+
+ /* get intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList,
+ numMonitors, 0);
+ if (numMonitors <= 0)
+ {
+ ExFreePool(hMonitorList);
+ ExFreePool(rectList);
+ return (HMONITOR)NULL;
+ }
+
+ /* find largest intersection */
+ for (i = 0; i < numMonitors; i++)
+ {
+ INT area = (rectList[i].right - rectList[i].left) *
+ (rectList[i].bottom - rectList[i].top);
+ if (area > iLargestArea)
+ {
+ hMonitor = hMonitorList[i];
+ }
+ }
+
+ ExFreePool(hMonitorList);
+ ExFreePool(rectList);
+
+ return hMonitor;
+}
+
+
+HMONITOR
+APIENTRY
+NtUserMonitorFromWindow(
+ IN HWND hWnd,
+ IN DWORD dwFlags)
+{
+ PWINDOW_OBJECT Window;
+ HMONITOR hMonitor = NULL;
+ RECTL Rect;
+ DECLARE_RETURN(HMONITOR);
+
+ DPRINT("Enter NtUserMonitorFromWindow\n");
+ UserEnterShared();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ if (dwFlags == MONITOR_DEFAULTTONULL)
+ {
+ RETURN(hMonitor);
+ }
+ IntGetMonitorsFromRect(NULL, &hMonitor, NULL, 1, dwFlags);
+ RETURN(hMonitor);
+ }
+
+ if (!Window->Wnd)
+ RETURN(hMonitor);
+
+ Rect.left = Rect.right = Window->Wnd->rcWindow.left;
+ Rect.top = Rect.bottom = Window->Wnd->rcWindow.bottom;
+
+ IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
+
+ RETURN(hMonitor);
+
+CLEANUP:
+ DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
--- /dev/null
- UserDrawCaptionText(hMemDc, &pWnd->Wnd->strName, &r, uFlags);
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Window painting function
+ * FILE: subsys/win32k/ntuser/painting.c
+ * PROGRAMER: Filip Navara (xnavara@volny.cz)
+ * REVISION HISTORY:
+ * 06/06/2001 Created (?)
+ * 18/11/2003 Complete rewrite
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+/**
+ * @name IntIntersectWithParents
+ *
+ * Intersect window rectangle with all parent client rectangles.
+ *
+ * @param Child
+ * Pointer to child window to start intersecting from.
+ * @param WindowRect
+ * Pointer to rectangle that we want to intersect in screen
+ * coordinates on input and intersected rectangle on output (if TRUE
+ * is returned).
+ *
+ * @return
+ * If any parent is minimized or invisible or the resulting rectangle
+ * is empty then FALSE is returned. Otherwise TRUE is returned.
+ */
+
+BOOL FASTCALL
+IntIntersectWithParents(PWINDOW_OBJECT Child, RECTL *WindowRect)
+{
+ PWINDOW_OBJECT ParentWindow;
+ PWND ParentWnd;
+
+ ParentWindow = Child->spwndParent;
+ while (ParentWindow != NULL)
+ {
+ ParentWnd = ParentWindow->Wnd;
+ if (!(ParentWnd->style & WS_VISIBLE) ||
+ (ParentWnd->style & WS_MINIMIZE))
+ {
+ return FALSE;
+ }
+
+ if (!RECTL_bIntersectRect(WindowRect, WindowRect, &ParentWnd->rcClient))
+ {
+ return FALSE;
+ }
+
+ /* FIXME: Layered windows. */
+
+ ParentWindow = ParentWindow->spwndParent;
+ }
+
+ return TRUE;
+}
+
+BOOL FASTCALL
+IntValidateParent(PWINDOW_OBJECT Child, HRGN hValidateRgn, BOOL Recurse)
+{
+ PWINDOW_OBJECT ParentWindow = Child->spwndParent;
+ PWND ParentWnd;
+
+ while (ParentWindow)
+ {
+ ParentWnd = ParentWindow->Wnd;
+ if (ParentWnd->style & WS_CLIPCHILDREN)
+ break;
+
+ if (ParentWindow->hrgnUpdate != 0)
+ {
+ if (Recurse)
+ return FALSE;
+
+ IntInvalidateWindows( ParentWindow,
+ hValidateRgn,
+ RDW_VALIDATE | RDW_NOCHILDREN);
+ }
+
+ ParentWindow = ParentWindow->spwndParent;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @name IntCalcWindowRgn
+ *
+ * Get a window or client region.
+ */
+
+HRGN FASTCALL
+IntCalcWindowRgn(PWINDOW_OBJECT Window, BOOL Client)
+{
+ PWND Wnd;
+ HRGN hRgnWindow;
+ UINT RgnType;
+
+ Wnd = Window->Wnd;
+ if (Client)
+ hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
+ else
+ hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
+
+ if (Window->hrgnClip != NULL && !(Wnd->style & WS_MINIMIZE))
+ {
+ NtGdiOffsetRgn(hRgnWindow,
+ -Wnd->rcWindow.left,
+ -Wnd->rcWindow.top);
+ RgnType = NtGdiCombineRgn(hRgnWindow, hRgnWindow, Window->hrgnClip, RGN_AND);
+ NtGdiOffsetRgn(hRgnWindow,
+ Wnd->rcWindow.left,
+ Wnd->rcWindow.top);
+ }
+
+ return hRgnWindow;
+}
+
+/**
+ * @name IntGetNCUpdateRgn
+ *
+ * Get non-client update region of a window and optionally validate it.
+ *
+ * @param Window
+ * Pointer to window to get the NC update region from.
+ * @param Validate
+ * Set to TRUE to force validating the NC update region.
+ *
+ * @return
+ * Handle to NC update region. The caller is responsible for deleting
+ * it.
+ */
+
+HRGN FASTCALL
+IntGetNCUpdateRgn(PWINDOW_OBJECT Window, BOOL Validate)
+{
+ HRGN hRgnNonClient;
+ HRGN hRgnWindow;
+ UINT RgnType;
+
+ if (Window->hrgnUpdate != NULL &&
+ Window->hrgnUpdate != (HRGN)1)
+ {
+ hRgnNonClient = IntCalcWindowRgn(Window, FALSE);
+
+ /*
+ * If region creation fails it's safe to fallback to whole
+ * window region.
+ */
+ if (hRgnNonClient == NULL)
+ {
+ return (HRGN)1;
+ }
+
+ hRgnWindow = IntCalcWindowRgn(Window, TRUE);
+ if (hRgnWindow == NULL)
+ {
+ REGION_FreeRgnByHandle(hRgnNonClient);
+ return (HRGN)1;
+ }
+
+ RgnType = NtGdiCombineRgn(hRgnNonClient, hRgnNonClient,
+ hRgnWindow, RGN_DIFF);
+ if (RgnType == ERROR)
+ {
+ REGION_FreeRgnByHandle(hRgnWindow);
+ REGION_FreeRgnByHandle(hRgnNonClient);
+ return (HRGN)1;
+ }
+ else if (RgnType == NULLREGION)
+ {
+ REGION_FreeRgnByHandle(hRgnWindow);
+ REGION_FreeRgnByHandle(hRgnNonClient);
+ return NULL;
+ }
+
+ /*
+ * Remove the nonclient region from the standard update region if
+ * we were asked for it.
+ */
+
+ if (Validate)
+ {
+ if (NtGdiCombineRgn(Window->hrgnUpdate, Window->hrgnUpdate,
+ hRgnWindow, RGN_AND) == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ REGION_FreeRgnByHandle(Window->hrgnUpdate);
+ Window->hrgnUpdate = NULL;
+ if (!(Window->Wnd->state & WNDS_INTERNALPAINT))
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ }
+ }
+
+ REGION_FreeRgnByHandle(hRgnWindow);
+
+ return hRgnNonClient;
+ }
+ else
+ {
+ return Window->hrgnUpdate;
+ }
+}
+
+/*
+ * IntPaintWindows
+ *
+ * Internal function used by IntRedrawWindow.
+ */
+
+VOID FASTCALL
+co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags, BOOL Recurse)
+{
+ HDC hDC;
+ HWND hWnd = Window->hSelf;
+ HRGN TempRegion;
+ PWND Wnd;
+
+ Wnd = Window->Wnd;
+
+ if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
+ {
+ if (Window->hrgnUpdate)
+ {
+ if (!IntValidateParent(Window, Window->hrgnUpdate, Recurse))
+ return;
+ }
+
+ if (Flags & RDW_UPDATENOW)
+ {
+ if (Window->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT)
+ {
+ co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
+ }
+ }
+ else
+ {
+ if (Window->state & WINDOWOBJECT_NEED_NCPAINT)
+ {
+ TempRegion = IntGetNCUpdateRgn(Window, TRUE);
+ Window->state &= ~WINDOWOBJECT_NEED_NCPAINT;
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
+
+ if ( (HANDLE) 1 != TempRegion &&
+ NULL != TempRegion)
+ {
+ /* NOTE: The region can already be deleted! */
+ GDIOBJ_FreeObjByHandle(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
+ }
+ }
+
+ if (Window->state & WINDOWOBJECT_NEED_ERASEBKGND)
+ {
+ if (Window->hrgnUpdate)
+ {
+ hDC = UserGetDCEx( Window,
+ Window->hrgnUpdate,
+ DCX_CACHE|DCX_USESTYLE|DCX_INTERSECTRGN|DCX_KEEPCLIPRGN);
+
+ if (co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
+ {
+ Window->state &= ~WINDOWOBJECT_NEED_ERASEBKGND;
+ }
+ UserReleaseDC(Window, hDC, FALSE);
+ }
+ }
+ }
+ }
+
+ /*
+ * Check that the window is still valid at this point
+ */
+ if (!IntIsWindow(hWnd))
+ {
+ return;
+ }
+
+ /*
+ * Paint child windows.
+ */
+ if (!(Flags & RDW_NOCHILDREN) &&
+ !(Wnd->style & WS_MINIMIZE) &&
+ ((Flags & RDW_ALLCHILDREN) || !(Wnd->style & WS_CLIPCHILDREN)) )
+ {
+ HWND *List, *phWnd;
+
+ if ((List = IntWinListChildren(Window)))
+ {
+ /* FIXME: Handle WS_EX_TRANSPARENT */
+ for (phWnd = List; *phWnd; ++phWnd)
+ {
+ Window = UserGetWindowObject(*phWnd);
+ Wnd = Window->Wnd;
+ if (Window && (Wnd->style & WS_VISIBLE))
+ {
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
+ co_IntPaintWindows(Window, Flags, TRUE);
+ UserDerefObjectCo(Window);
+ }
+ }
+ ExFreePool(List);
+ }
+ }
+}
+
+/*
+ * IntInvalidateWindows
+ *
+ * Internal function used by IntRedrawWindow.
+ */
+
+VOID FASTCALL
+IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
+{
+ INT RgnType;
+ PWND Wnd;
+ BOOL HadPaintMessage, HadNCPaintMessage;
+ BOOL HasPaintMessage, HasNCPaintMessage;
+
+ Wnd = Window->Wnd;
+ DPRINT("IntInvalidateWindows start\n");
+ /*
+ * If the nonclient is not to be redrawn, clip the region to the client
+ * rect
+ */
+ if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME))
+ {
+ HRGN hRgnClient;
+
+ hRgnClient = IntSysCreateRectRgnIndirect(&Window->Wnd->rcClient);
+ RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnClient, RGN_AND);
+ REGION_FreeRgnByHandle(hRgnClient);
+ }
+
+ /*
+ * Clip the given region with window rectangle (or region)
+ */
+
+ if (!Window->hrgnClip || (Wnd->style & WS_MINIMIZE))
+ {
+ HRGN hRgnWindow;
+
+ hRgnWindow = IntSysCreateRectRgnIndirect(&Window->Wnd->rcWindow);
+ RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
+ REGION_FreeRgnByHandle(hRgnWindow);
+ }
+ else
+ {
+ NtGdiOffsetRgn( hRgn,
+ -Wnd->rcWindow.left,
+ -Wnd->rcWindow.top);
+ RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->hrgnClip, RGN_AND);
+ NtGdiOffsetRgn( hRgn,
+ Wnd->rcWindow.left,
+ Wnd->rcWindow.top);
+ }
+
+ /*
+ * Save current state of pending updates
+ */
+
+ HadPaintMessage = Window->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT;
+ HadNCPaintMessage = Window->state & WINDOWOBJECT_NEED_NCPAINT;
+
+ /*
+ * Update the region and flags
+ */
+
+ if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
+ {
+ if (Window->hrgnUpdate == NULL)
+ {
+ Window->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0);
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+ }
+
+ if (NtGdiCombineRgn(Window->hrgnUpdate, Window->hrgnUpdate,
+ hRgn, RGN_OR) == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ REGION_FreeRgnByHandle(Window->hrgnUpdate);
+ Window->hrgnUpdate = NULL;
+ }
+
+ if (Flags & RDW_FRAME)
+ Window->state |= WINDOWOBJECT_NEED_NCPAINT;
+ if (Flags & RDW_ERASE)
+ Window->state |= WINDOWOBJECT_NEED_ERASEBKGND;
+
+ Flags |= RDW_FRAME;
+ }
+
+ if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
+ {
+ if (Window->hrgnUpdate != NULL)
+ {
+ if (NtGdiCombineRgn(Window->hrgnUpdate, Window->hrgnUpdate,
+ hRgn, RGN_DIFF) == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ REGION_FreeRgnByHandle(Window->hrgnUpdate);
+ Window->hrgnUpdate = NULL;
+ }
+ }
+
+ if (Window->hrgnUpdate == NULL)
+ Window->state &= ~WINDOWOBJECT_NEED_ERASEBKGND;
+ if (Flags & RDW_NOFRAME)
+ Window->state &= ~WINDOWOBJECT_NEED_NCPAINT;
+ if (Flags & RDW_NOERASE)
+ Window->state &= ~WINDOWOBJECT_NEED_ERASEBKGND;
+ }
+
+ if (Flags & RDW_INTERNALPAINT)
+ {
+ Wnd->state |= WNDS_INTERNALPAINT;
+ }
+
+ if (Flags & RDW_NOINTERNALPAINT)
+ {
+ Wnd->state &= ~WNDS_INTERNALPAINT;
+ }
+
+ /*
+ * Process children if needed
+ */
+
+ if (!(Flags & RDW_NOCHILDREN) && !(Wnd->style & WS_MINIMIZE) &&
+ ((Flags & RDW_ALLCHILDREN) || !(Wnd->style & WS_CLIPCHILDREN)))
+ {
+ PWINDOW_OBJECT Child;
+
+ for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+ {
+ if (Child->Wnd->style & WS_VISIBLE)
+ {
+ /*
+ * Recursive call to update children hrgnUpdate
+ */
+ HRGN hRgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
+ NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
+ IntInvalidateWindows(Child, hRgnTemp, Flags);
+ REGION_FreeRgnByHandle(hRgnTemp);
+ }
+
+ }
+ }
+
+ /*
+ * Fake post paint messages to window message queue if needed
+ */
+
+ HasPaintMessage = Window->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT;
+ HasNCPaintMessage = Window->state & WINDOWOBJECT_NEED_NCPAINT;
+
+ if (HasPaintMessage != HadPaintMessage)
+ {
+ if (HadPaintMessage)
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ else
+ MsqIncPaintCountQueue(Window->pti->MessageQueue);
+ }
+
+ if (HasNCPaintMessage != HadNCPaintMessage)
+ {
+ if (HadNCPaintMessage)
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ else
+ MsqIncPaintCountQueue(Window->pti->MessageQueue);
+ }
+ DPRINT("IntInvalidateWindows exit\n");
+}
+
+/*
+ * IntIsWindowDrawable
+ *
+ * Remarks
+ * Window is drawable when it is visible and all parents are not
+ * minimized.
+ */
+
+BOOL FASTCALL
+IntIsWindowDrawable(PWINDOW_OBJECT Window)
+{
+ PWINDOW_OBJECT WndObject;
+ PWND Wnd;
+
+ for (WndObject = Window; WndObject != NULL; WndObject = WndObject->spwndParent)
+ {
+ Wnd = WndObject->Wnd;
+ if ( Window->state & WINDOWSTATUS_DESTROYING || // state2
+ Window->state & WINDOWSTATUS_DESTROYED ||
+ !Wnd ||
+ !(Wnd->style & WS_VISIBLE) ||
+ ((Wnd->style & WS_MINIMIZE) && (WndObject != Window)))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * IntRedrawWindow
+ *
+ * Internal version of NtUserRedrawWindow that takes WINDOW_OBJECT as
+ * first parameter.
+ */
+
+BOOL FASTCALL
+co_UserRedrawWindow(
+ PWINDOW_OBJECT Window,
+ const RECTL* UpdateRect,
+ HRGN UpdateRgn,
+ ULONG Flags)
+{
+ HRGN hRgn = NULL;
+ DPRINT("co_UserRedrawWindow start\n");
+
+ /*
+ * Step 1.
+ * Validation of passed parameters.
+ */
+
+ if (!IntIsWindowDrawable(Window))
+ {
+ return TRUE; // Just do nothing!!!
+ }
+
+ /*
+ * Step 2.
+ * Transform the parameters UpdateRgn and UpdateRect into
+ * a region hRgn specified in screen coordinates.
+ */
+
+ if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY!
+ {
+ if (UpdateRgn != NULL)
+ {
+ hRgn = IntSysCreateRectRgn(0, 0, 0, 0);
+ if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
+ {
+ REGION_FreeRgnByHandle(hRgn);
+ hRgn = NULL;
+ }
+ else
+ NtGdiOffsetRgn(hRgn, Window->Wnd->rcClient.left, Window->Wnd->rcClient.top);
+ }
+ else if (UpdateRect != NULL)
+ {
+ if (!RECTL_bIsEmptyRect(UpdateRect))
+ {
+ hRgn = IntSysCreateRectRgnIndirect((RECTL *)UpdateRect);
+ NtGdiOffsetRgn(hRgn, Window->Wnd->rcClient.left, Window->Wnd->rcClient.top);
+ }
+ }
+ else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
+ (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
+ {
+ if (!RECTL_bIsEmptyRect(&Window->Wnd->rcWindow))
+ hRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcWindow);
+ }
+ else
+ {
+ if (!RECTL_bIsEmptyRect(&Window->Wnd->rcClient))
+ hRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcClient);
+ }
+ }
+
+ /*
+ * Step 3.
+ * Adjust the window update region depending on hRgn and flags.
+ */
+
+ if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
+ hRgn != NULL)
+ {
+ IntInvalidateWindows(Window, hRgn, Flags);
+ }
+
+ /*
+ * Step 4.
+ * Repaint and erase windows if needed.
+ */
+
+ if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
+ {
+ co_IntPaintWindows(Window, Flags, FALSE);
+ }
+
+ /*
+ * Step 5.
+ * Cleanup ;-)
+ */
+
+ if (hRgn != NULL)
+ {
+ REGION_FreeRgnByHandle(hRgn);
+ }
+ DPRINT("co_UserRedrawWindow exit\n");
+
+ return TRUE;
+}
+
+BOOL FASTCALL
+IntIsWindowDirty(PWINDOW_OBJECT Window)
+{
+ PWND Wnd = Window->Wnd;
+ return (Wnd->style & WS_VISIBLE) &&
+ ((Window->hrgnUpdate != NULL) ||
+ (Wnd->state & WNDS_INTERNALPAINT) ||
+ (Window->state & WINDOWOBJECT_NEED_NCPAINT));
+}
+
+HWND FASTCALL
+IntFindWindowToRepaint(PWINDOW_OBJECT Window, PTHREADINFO Thread)
+{
+ HWND hChild;
+ PWINDOW_OBJECT TempWindow;
+ PWND Wnd, TempWnd;
+
+ for (; Window != NULL; Window = Window->spwndNext)
+ {
+ Wnd = Window->Wnd;
+ if (IntWndBelongsToThread(Window, Thread) &&
+ IntIsWindowDirty(Window))
+ {
+ /* Make sure all non-transparent siblings are already drawn. */
+ if (Wnd->ExStyle & WS_EX_TRANSPARENT)
+ {
+ for (TempWindow = Window->spwndNext; TempWindow != NULL;
+ TempWindow = TempWindow->spwndNext)
+ {
+ TempWnd = TempWindow->Wnd;
+ if (!(TempWnd->ExStyle & WS_EX_TRANSPARENT) &&
+ IntWndBelongsToThread(TempWindow, Thread) &&
+ IntIsWindowDirty(TempWindow))
+ {
+ return TempWindow->hSelf;
+ }
+ }
+ }
+
+ return Window->hSelf;
+ }
+
+ if (Window->spwndChild)
+ {
+ hChild = IntFindWindowToRepaint(Window->spwndChild, Thread);
+ if (hChild != NULL)
+ return hChild;
+ }
+ }
+
+ return NULL;
+}
+
+BOOL FASTCALL
+IntGetPaintMessage(
+ PWINDOW_OBJECT Window,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ PTHREADINFO Thread,
+ MSG *Message,
+ BOOL Remove)
+{
+ PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
+
+ if (!MessageQueue->PaintCount)
+ return FALSE;
+
+ if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
+ (MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
+ return FALSE;
+
+ Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetCurrentThreadWin32Thread());
+
+ if (Message->hwnd == NULL)
+ {
+ DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
+ /* Hack to stop spamming the debuglog ! */
+ MessageQueue->PaintCount = 0;
+ return FALSE;
+ }
+
+ if (Window != NULL && Message->hwnd != Window->hSelf)
+ return FALSE;
+
+ Message->message = WM_PAINT;
+ Message->wParam = Message->lParam = 0;
+
+ return TRUE;
+}
+
+static
+HWND FASTCALL
+co_IntFixCaret(PWINDOW_OBJECT Window, RECTL *lprc, UINT flags)
+{
+ PDESKTOP Desktop;
+ PTHRDCARETINFO CaretInfo;
+ HWND hWndCaret;
+ PWINDOW_OBJECT WndCaret;
+
+ ASSERT_REFS_CO(Window);
+
+ Desktop = ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->rpdesk;
+ CaretInfo = ((PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue)->CaretInfo;
+ hWndCaret = CaretInfo->hWnd;
+
+ WndCaret = UserGetWindowObject(hWndCaret);
+
+ //fix: check for WndCaret can be null
+ if (WndCaret == Window ||
+ ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
+ {
+ POINT pt, FromOffset, ToOffset, Offset;
+ RECTL rcCaret;
+
+ pt.x = CaretInfo->Pos.x;
+ pt.y = CaretInfo->Pos.y;
+ IntGetClientOrigin(WndCaret, &FromOffset);
+ IntGetClientOrigin(Window, &ToOffset);
+ Offset.x = FromOffset.x - ToOffset.x;
+ Offset.y = FromOffset.y - ToOffset.y;
+ rcCaret.left = pt.x;
+ rcCaret.top = pt.y;
+ rcCaret.right = pt.x + CaretInfo->Size.cx;
+ rcCaret.bottom = pt.y + CaretInfo->Size.cy;
+ if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
+ {
+ co_UserHideCaret(0);
+ lprc->left = pt.x;
+ lprc->top = pt.y;
+ return hWndCaret;
+ }
+ }
+
+ return 0;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * NtUserBeginPaint
+ *
+ * Status
+ * @implemented
+ */
+
+HDC APIENTRY
+NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
+{
+ PWINDOW_OBJECT Window = NULL;
+ PAINTSTRUCT Ps;
+ NTSTATUS Status;
+ DECLARE_RETURN(HDC);
+ USER_REFERENCE_ENTRY Ref;
+ PWND Wnd;
+
+ DPRINT("Enter NtUserBeginPaint\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN( NULL);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ Wnd = Window->Wnd;
+
+ co_UserHideCaret(Window);
+
+ if (Window->state & WINDOWOBJECT_NEED_NCPAINT)
+ {
+ HRGN hRgn;
+
+ hRgn = IntGetNCUpdateRgn(Window, FALSE);
+ Window->state &= ~WINDOWOBJECT_NEED_NCPAINT;
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
+ if (hRgn != (HANDLE)1 && hRgn != NULL)
+ {
+ /* NOTE: The region can already by deleted! */
+ GDIOBJ_FreeObjByHandle(hRgn, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT);
+ }
+ }
+
+ RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT));
+
+ Ps.hdc = UserGetDCEx( Window,
+ Window->hrgnUpdate,
+ DCX_INTERSECTRGN | DCX_USESTYLE);
+ if (!Ps.hdc)
+ {
+ RETURN(NULL);
+ }
+
+ if (Window->hrgnUpdate != NULL)
+ {
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+ GdiGetClipBox(Ps.hdc, &Ps.rcPaint);
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ /* The region is part of the dc now and belongs to the process! */
+ Window->hrgnUpdate = NULL;
+ }
+ else
+ {
+ if (Wnd->state & WNDS_INTERNALPAINT)
+ MsqDecPaintCountQueue(Window->pti->MessageQueue);
+
+ IntGetClientRect(Window, &Ps.rcPaint);
+ }
+
+ Wnd->state &= ~WNDS_INTERNALPAINT;
+
+ if (Window->state & WINDOWOBJECT_NEED_ERASEBKGND)
+ {
+ Window->state &= ~WINDOWOBJECT_NEED_ERASEBKGND;
+ Ps.fErase = !co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)Ps.hdc, 0);
+ }
+ else
+ {
+ Ps.fErase = FALSE;
+ }
+ if (Window->hrgnUpdate)
+ {
+ if (!(Wnd->style & WS_CLIPCHILDREN))
+ {
+ PWINDOW_OBJECT Child;
+ for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+ {
+ IntInvalidateWindows(Child, Window->hrgnUpdate, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
+ }
+ }
+ }
+
+ Status = MmCopyToCaller(UnsafePs, &Ps, sizeof(PAINTSTRUCT));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(NULL);
+ }
+
+ RETURN(Ps.hdc);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserBeginPaint, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+
+}
+
+/*
+ * NtUserEndPaint
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* pUnsafePs)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PWINDOW_OBJECT Window;
+ DECLARE_RETURN(BOOL);
+ USER_REFERENCE_ENTRY Ref;
+ HDC hdc = NULL;
+
+ DPRINT("Enter NtUserEndPaint\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(FALSE);
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(pUnsafePs, sizeof(*pUnsafePs), 1);
+ hdc = pUnsafePs->hdc;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ if (!NT_SUCCESS(Status))
+ {
+ RETURN(FALSE);
+ }
+
+ UserReleaseDC(Window, hdc, TRUE);
+
+ UserRefObjectCo(Window, &Ref);
+ co_UserShowCaret(Window);
+ UserDerefObjectCo(Window);
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserEndPaint, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+INT FASTCALL
+co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)
+{
+ int RegionType;
+ RECTL Rect;
+
+ ASSERT_REFS_CO(Window);
+
+ if (Window->hrgnUpdate == NULL)
+ {
+ RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
+ }
+ else
+ {
+ Rect = Window->Wnd->rcClient;
+ IntIntersectWithParents(Window, &Rect);
+ NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
+ RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->hrgnUpdate, RGN_AND);
+ NtGdiOffsetRgn(hRgn, -Window->Wnd->rcClient.left, -Window->Wnd->rcClient.top);
+ }
+
+ if (bErase && RegionType != NULLREGION && RegionType != ERROR)
+ {
+ co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
+ }
+
+ return RegionType;
+}
+
+/*
+ * NtUserGetUpdateRgn
+ *
+ * Status
+ * @implemented
+ */
+
+INT APIENTRY
+NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
+{
+ DECLARE_RETURN(INT);
+ PWINDOW_OBJECT Window;
+ INT ret;
+ USER_REFERENCE_ENTRY Ref;
+
+ DPRINT("Enter NtUserGetUpdateRgn\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(ERROR);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+ ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
+ UserDerefObjectCo(Window);
+
+ RETURN(ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserGetUpdateRect
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserGetUpdateRect(HWND hWnd, LPRECT UnsafeRect, BOOL bErase)
+{
+ PWINDOW_OBJECT Window;
+ RECTL Rect;
+ INT RegionType;
+ PROSRGNDATA RgnData;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetUpdateRect\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(FALSE);
+ }
+
+ if (Window->hrgnUpdate == NULL)
+ {
+ Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
+ }
+ else
+ {
+ /* Get the update region bounding box. */
+ if (Window->hrgnUpdate == (HRGN)1)
+ {
+ Rect = Window->Wnd->rcClient;
+ }
+ else
+ {
+ RgnData = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
+ ASSERT(RgnData != NULL);
+ RegionType = REGION_GetRgnBox(RgnData, &Rect);
+ RGNOBJAPI_Unlock(RgnData);
+
+ if (RegionType != ERROR && RegionType != NULLREGION)
+ RECTL_bIntersectRect(&Rect, &Rect, &Window->Wnd->rcClient);
+ }
+
+ if (IntIntersectWithParents(Window, &Rect))
+ {
+ RECTL_vOffsetRect(&Rect,
+ -Window->Wnd->rcClient.left,
+ -Window->Wnd->rcClient.top);
+ } else
+ {
+ Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
+ }
+ }
+
+ if (bErase && !RECTL_bIsEmptyRect(&Rect))
+ {
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(Window, &Ref);
+ co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
+ UserDerefObjectCo(Window);
+ }
+
+ if (UnsafeRect != NULL)
+ {
+ Status = MmCopyToCaller(UnsafeRect, &Rect, sizeof(RECTL));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+ }
+
+ RETURN(!RECTL_bIsEmptyRect(&Rect));
+
+CLEANUP:
+ DPRINT("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserRedrawWindow
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserRedrawWindow(
+ HWND hWnd,
+ CONST RECT *lprcUpdate,
+ HRGN hrgnUpdate,
+ UINT flags)
+{
+ RECTL SafeUpdateRect;
+ PWINDOW_OBJECT Wnd;
+ BOOL Ret;
+ USER_REFERENCE_ENTRY Ref;
+ NTSTATUS Status = STATUS_SUCCESS;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserRedrawWindow\n");
+ UserEnterExclusive();
+
+ if (!(Wnd = UserGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
+ {
+ RETURN( FALSE);
+ }
+
+ if (lprcUpdate)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead(lprcUpdate, sizeof(RECTL), 1);
+ RtlCopyMemory(&SafeUpdateRect, lprcUpdate, sizeof(RECTL));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(RtlNtStatusToDosError(Status));
+ RETURN( FALSE);
+ }
+ }
+
+ if ( flags & ~(RDW_ERASE|RDW_FRAME|RDW_INTERNALPAINT|RDW_INVALIDATE|
+ RDW_NOERASE|RDW_NOFRAME|RDW_NOINTERNALPAINT|RDW_VALIDATE|
+ RDW_ERASENOW|RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_NOCHILDREN) )
+ {
+ /* RedrawWindow fails only in case that flags are invalid */
+ SetLastWin32Error(ERROR_INVALID_FLAGS);
+ RETURN( FALSE);
+ }
+
+ UserRefObjectCo(Wnd, &Ref);
+
+ Ret = co_UserRedrawWindow( Wnd,
+ lprcUpdate ? &SafeUpdateRect : NULL,
+ hrgnUpdate,
+ flags);
+
+ UserDerefObjectCo(Wnd);
+
+ RETURN( Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+static
+INT FASTCALL
+UserScrollDC(
+ HDC hDC,
+ INT dx,
+ INT dy,
+ const RECTL *prcScroll,
+ const RECTL *prcClip,
+ HRGN hrgnUpdate,
+ RECTL *prcUpdate)
+{
+ PDC pDC;
+ RECTL rcScroll, rcClip, rcSrc, rcDst;
+ INT Result;
+
+ GdiGetClipBox(hDC, &rcClip);
+ rcScroll = rcClip;
+ if (prcClip)
+ {
+ RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
+ }
+
+ if (prcScroll)
+ {
+ rcScroll = *prcScroll;
+ RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
+ }
+ else
+ {
+ rcSrc = rcClip;
+ }
+
+ rcDst = rcSrc;
+ RECTL_vOffsetRect(&rcDst, dx, dy);
+ RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
+
+ if (!NtGdiBitBlt( hDC,
+ rcDst.left,
+ rcDst.top,
+ rcDst.right - rcDst.left,
+ rcDst.bottom - rcDst.top,
+ hDC,
+ rcDst.left - dx,
+ rcDst.top - dy,
+ SRCCOPY,
+ 0,
+ 0))
+ {
+ return ERROR;
+ }
+
+ /* Calculate the region that was invalidated by moving or
+ could not be copied, because it was not visible */
+ if (hrgnUpdate || prcUpdate)
+ {
+ HRGN hrgnOwn, hrgnVisible, hrgnTmp;
+
+ pDC = DC_LockDc(hDC);
+ if (!pDC)
+ {
+ return FALSE;
+ }
+ hrgnVisible = pDC->prgnVis->BaseObject.hHmgr; // pDC->prgnRao?
+ DC_UnlockDc(pDC);
+
+ /* Begin with the shifted and then clipped scroll rect */
+ rcDst = rcScroll;
+ RECTL_vOffsetRect(&rcDst, dx, dy);
+ RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
+ if (hrgnUpdate)
+ {
+ hrgnOwn = hrgnUpdate;
+ if (!NtGdiSetRectRgn(hrgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom))
+ {
+ return ERROR;
+ }
+ }
+ else
+ {
+ hrgnOwn = IntSysCreateRectRgnIndirect(&rcDst);
+ }
+
+ /* Add the source rect */
+ hrgnTmp = IntSysCreateRectRgnIndirect(&rcSrc);
+ NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_OR);
+
+ /* Substract the part of the dest that was visible in source */
+ NtGdiCombineRgn(hrgnTmp, hrgnTmp, hrgnVisible, RGN_AND);
+ NtGdiOffsetRgn(hrgnTmp, dx, dy);
+ Result = NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_DIFF);
+
+ REGION_FreeRgnByHandle(hrgnTmp);
+
+ if (prcUpdate)
+ {
+ IntGdiGetRgnBox(hrgnOwn, prcUpdate);
+ }
+
+ if (!hrgnUpdate)
+ {
+ REGION_FreeRgnByHandle(hrgnOwn);
+ }
+ }
+ else
+ Result = NULLREGION;
+
+ return Result;
+}
+
+/*
+ * NtUserScrollDC
+ *
+ * Status
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserScrollDC(
+ HDC hDC,
+ INT dx,
+ INT dy,
+ const RECT *prcUnsafeScroll,
+ const RECT *prcUnsafeClip,
+ HRGN hrgnUpdate,
+ LPRECT prcUnsafeUpdate)
+{
+ DECLARE_RETURN(DWORD);
+ RECTL rcScroll, rcClip, rcUpdate;
+ NTSTATUS Status = STATUS_SUCCESS;
+ DWORD Result;
+
+ DPRINT("Enter NtUserScrollDC\n");
+ UserEnterExclusive();
+
+ _SEH2_TRY
+ {
+ if (prcUnsafeScroll)
+ {
+ ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
+ rcScroll = *prcUnsafeScroll;
+ }
+ if (prcUnsafeClip)
+ {
+ ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
+ rcClip = *prcUnsafeClip;
+ }
+ if (prcUnsafeUpdate)
+ {
+ ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ Result = UserScrollDC( hDC,
+ dx,
+ dy,
+ prcUnsafeScroll? &rcScroll : 0,
+ prcUnsafeClip? &rcClip : 0,
+ hrgnUpdate,
+ prcUnsafeUpdate? &rcUpdate : NULL);
+ if(Result == ERROR)
+ {
+ /* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
+ RETURN(FALSE);
+ }
+
+ if (prcUnsafeUpdate)
+ {
+ _SEH2_TRY
+ {
+ *prcUnsafeUpdate = rcUpdate;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: SetLastError? */
+ /* FIXME: correct? We have already scrolled! */
+ RETURN(FALSE);
+ }
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserScrollDC, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserScrollWindowEx
+ *
+ * Status
+ * @implemented
+ */
+
+DWORD APIENTRY
+NtUserScrollWindowEx(
+ HWND hWnd,
+ INT dx,
+ INT dy,
+ const RECT *prcUnsafeScroll,
+ const RECT *prcUnsafeClip,
+ HRGN hrgnUpdate,
+ LPRECT prcUnsafeUpdate,
+ UINT flags)
+{
+ RECTL rcScroll, rcClip, rcCaret, rcUpdate;
+ INT Result;
+ PWINDOW_OBJECT Window = NULL, CaretWnd;
+ HDC hDC;
+ HRGN hrgnOwn = NULL, hrgnTemp;
+ HWND hwndCaret;
+ NTSTATUS Status = STATUS_SUCCESS;
+ DECLARE_RETURN(DWORD);
+ USER_REFERENCE_ENTRY Ref, CaretRef;
+
+ DPRINT("Enter NtUserScrollWindowEx\n");
+ UserEnterExclusive();
+
+ Window = UserGetWindowObject(hWnd);
+ if (!Window || !IntIsWindowDrawable(Window))
+ {
+ Window = NULL; /* prevent deref at cleanup */
+ RETURN( ERROR);
+ }
+ UserRefObjectCo(Window, &Ref);
+
+ IntGetClientRect(Window, &rcClip);
+
+ _SEH2_TRY
+ {
+ if (prcUnsafeScroll)
+ {
+ ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
+ RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
+ }
+ else
+ rcScroll = rcClip;
+
+ if (prcUnsafeClip)
+ {
+ ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
+ RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(ERROR);
+ }
+
+ if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
+ (dx == 0 && dy == 0))
+ {
+ RETURN(NULLREGION);
+ }
+
+ if (hrgnUpdate)
+ hrgnOwn = hrgnUpdate;
+ else
+ hrgnOwn = IntSysCreateRectRgn(0, 0, 0, 0);
+
+ hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE);
+ if (!hDC)
+ {
+ /* FIXME: SetLastError? */
+ RETURN(ERROR);
+ }
+
+ rcCaret = rcScroll;
+ hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
+
+ Result = UserScrollDC( hDC,
+ dx,
+ dy,
+ &rcScroll,
+ &rcClip,
+ hrgnOwn,
+ prcUnsafeUpdate? &rcUpdate : NULL);
+
+ UserReleaseDC(Window, hDC, FALSE);
+
+ /*
+ * Take into account the fact that some damage may have occurred during
+ * the scroll.
+ */
+
+ hrgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
+ if (co_UserGetUpdateRgn(Window, hrgnTemp, FALSE) != NULLREGION)
+ {
+ HRGN hrgnClip = IntSysCreateRectRgnIndirect(&rcClip);
+ NtGdiOffsetRgn(hrgnTemp, dx, dy);
+ NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND);
+ co_UserRedrawWindow(Window, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE);
+ REGION_FreeRgnByHandle(hrgnClip);
+ }
+ REGION_FreeRgnByHandle(hrgnTemp);
+
+ if (flags & SW_SCROLLCHILDREN)
+ {
+ PWINDOW_OBJECT Child;
+ RECTL rcChild;
+ POINT ClientOrigin;
+ USER_REFERENCE_ENTRY WndRef;
+ RECTL rcDummy;
+
+ IntGetClientOrigin(Window, &ClientOrigin);
+ for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+ {
+ rcChild = Child->Wnd->rcWindow;
+ rcChild.left -= ClientOrigin.x;
+ rcChild.top -= ClientOrigin.y;
+ rcChild.right -= ClientOrigin.x;
+ rcChild.bottom -= ClientOrigin.y;
+
+ if (! prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
+ {
+ UserRefObjectCo(Child, &WndRef);
+ co_WinPosSetWindowPos(Child, 0, rcChild.left + dx, rcChild.top + dy, 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
+ SWP_NOREDRAW);
+ UserDerefObjectCo(Child);
+ }
+ }
+ }
+
+ if (flags & (SW_INVALIDATE | SW_ERASE))
+ {
+ co_UserRedrawWindow(Window, NULL, hrgnOwn, RDW_INVALIDATE | RDW_ERASE |
+ ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
+ ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
+ }
+
+ if ((CaretWnd = UserGetWindowObject(hwndCaret)))
+ {
+ UserRefObjectCo(CaretWnd, &CaretRef);
+
+ co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
+ co_UserShowCaret(CaretWnd);
+
+ UserDerefObjectCo(CaretWnd);
+ }
+
+ if (prcUnsafeUpdate)
+ {
+ _SEH2_TRY
+ {
+ /* Probe here, to not fail on invalid pointer before scrolling */
+ ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
+ *prcUnsafeUpdate = rcUpdate;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(ERROR);
+ }
+ }
+
+ RETURN(Result);
+
+CLEANUP:
+ if (hrgnOwn && !hrgnUpdate)
+ {
+ REGION_FreeRgnByHandle(hrgnOwn);
+ }
+
+ if (Window)
+ UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserScrollWindowEx, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+BOOL
+UserDrawSysMenuButton(
+ PWINDOW_OBJECT pWnd,
+ HDC hDc,
+ RECTL *lpRc,
+ BOOL Down)
+{
+ HICON hIcon;
+ PCURICON_OBJECT pIcon;
+
+ ASSERT(pWnd && lpRc);
+
+ /* Get the icon to draw. We don't care about WM_GETICON here. */
+
+ hIcon = pWnd->Wnd->pcls->hIconSm;
+
+ if(!hIcon)
+ {
+ DPRINT("Wnd class has no small icon.\n");
+ hIcon = pWnd->Wnd->pcls->hIcon;
+ }
+
+ if(!hIcon)
+ {
+ DPRINT("Wnd class hasn't any icon.\n");
+ //FIXME: Draw "winlogo" icon.
+ return FALSE;
+ }
+
+ if(!(pIcon = UserGetCurIconObject(hIcon)))
+ {
+ DPRINT1("UserGetCurIconObject() failed!\n");
+ return FALSE;
+ }
+
+ return UserDrawIconEx(hDc, lpRc->left, lpRc->top, pIcon,
+ UserGetSystemMetrics(SM_CXSMICON),
+ UserGetSystemMetrics(SM_CYSMICON),
+ 0, NULL, DI_NORMAL);
+}
+
+BOOL
+UserDrawCaptionText(
+ HDC hDc,
+ const PUNICODE_STRING Text,
+ const RECTL *lpRc,
+ UINT uFlags)
+{
+ HFONT hOldFont = NULL, hFont = NULL;
+ COLORREF OldTextColor;
+ NONCLIENTMETRICSW nclm;
+ NTSTATUS Status;
+ #ifndef NDEBUG
+ INT i;
+ DPRINT("%s:", __FUNCTION__);
+ for(i = 0; i < Text->Length/sizeof(WCHAR); i++)
+ DbgPrint("%C", Text->Buffer[i]);
+ DbgPrint(", %d\n", Text->Length/sizeof(WCHAR));
+ #endif
+
+ nclm.cbSize = sizeof(nclm);
+ if(!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS,
+ sizeof(NONCLIENTMETRICS), &nclm, 0))
+ {
+ DPRINT1("%s: UserSystemParametersInfo() failed!\n", __FUNCTION__);
+ return FALSE;
+ }
+
+ IntGdiSetBkMode(hDc, TRANSPARENT);
+
+ if(uFlags & DC_SMALLCAP)
+ Status = TextIntCreateFontIndirect(&nclm.lfSmCaptionFont, &hFont);
+ else Status = TextIntCreateFontIndirect(&nclm.lfCaptionFont, &hFont);
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("%s: TextIntCreateFontIndirect() failed! Status: 0x%x\n",
+ __FUNCTION__, Status);
+ return FALSE;
+ }
+
+ hOldFont = NtGdiSelectFont(hDc, hFont);
+ if(!hOldFont)
+ {
+ DPRINT1("%s: SelectFont() failed!\n", __FUNCTION__);
+ GreDeleteObject(hFont);
+ return FALSE;
+ }
+
+ if(uFlags & DC_INBUTTON)
+ OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(COLOR_BTNTEXT));
+ else OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(uFlags & DC_ACTIVE
+ ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
+
+ //FIXME: If string doesn't fit to rc, truncate it and add ellipsis.
+
+ GreExtTextOutW(hDc, lpRc->left,
+ lpRc->top, 0, NULL, Text->Buffer,
+ Text->Length/sizeof(WCHAR), NULL, 0);
+
+ IntGdiSetTextColor(hDc, OldTextColor);
+ NtGdiSelectFont(hDc, hOldFont);
+ GreDeleteObject(hFont);
+
+ return TRUE;
+}
+
+BOOL UserDrawCaption(
+ PWINDOW_OBJECT pWnd,
+ HDC hDc,
+ RECTL *lpRc,
+ HFONT hFont,
+ HICON hIcon,
+ const PUNICODE_STRING str,
+ UINT uFlags)
+{
+ BOOL Ret = FALSE;
+ HBITMAP hMemBmp = NULL, hOldBmp = NULL;
+ HBRUSH hOldBrush = NULL;
+ HDC hMemDc = NULL;
+ ULONG Height;
+ UINT VCenter = 0, Padding = 0;
+ RECTL r = *lpRc;
+ LONG ButtonWidth, IconWidth;
+ BOOL HasIcon;
+ PWND Wnd = NULL;
+
+ //ASSERT(pWnd != NULL);
+
+ if (pWnd)
+ Wnd = pWnd->Wnd;
+
+ RECTL_vMakeWellOrdered(lpRc);
+ hMemBmp = NtGdiCreateCompatibleBitmap(hDc,
+ lpRc->right - lpRc->left,
+ lpRc->bottom - lpRc->top);
+
+ if(!hMemBmp)
+ {
+ DPRINT1("%s: NtGdiCreateCompatibleBitmap() failed!\n", __FUNCTION__);
+ return FALSE;
+ }
+
+ hMemDc = NtGdiCreateCompatibleDC(hDc);
+ if(!hMemDc)
+ {
+ DPRINT1("%s: NtGdiCreateCompatibleDC() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ hOldBmp = NtGdiSelectBitmap(hMemDc, hMemBmp);
+ if(!hOldBmp)
+ {
+ DPRINT1("%s: NtGdiSelectBitmap() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ Height = UserGetSystemMetrics(SM_CYCAPTION) - 1;
+ VCenter = (lpRc->bottom - lpRc->top) / 2;
+ Padding = VCenter - (Height / 2);
+
+ if ((!hIcon) && (Wnd != NULL))
+ {
+ HasIcon = (uFlags & DC_ICON) && (Wnd->style & WS_SYSMENU)
+ && !(uFlags & DC_SMALLCAP) && !(Wnd->ExStyle & WS_EX_DLGMODALFRAME)
+ && !(Wnd->ExStyle & WS_EX_TOOLWINDOW);
+ }
+ else
+ HasIcon = (hIcon != 0);
+
+ IconWidth = UserGetSystemMetrics(SM_CXSIZE) + Padding;
+
+ r.left = Padding;
+ r.right = r.left + (lpRc->right - lpRc->left);
+ r.top = Padding;
+ r.bottom = r.top + (Height / 2);
+
+ // Draw the caption background
+ if(uFlags & DC_INBUTTON)
+ {
+ hOldBrush = NtGdiSelectBrush(hMemDc,
+ IntGetSysColorBrush(COLOR_3DFACE));
+
+ if(!hOldBrush)
+ {
+ DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if(!NtGdiPatBlt(hMemDc, 0, 0,
+ lpRc->right - lpRc->left,
+ lpRc->bottom - lpRc->top,
+ PATCOPY))
+ {
+ DPRINT1("%s: NtGdiPatBlt() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if(HasIcon) r.left+=IconWidth;
+ }
+ else
+ {
+ r.right = (lpRc->right - lpRc->left);
+ if(uFlags & DC_SMALLCAP)
+ ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
+ else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
+
+ hOldBrush = NtGdiSelectBrush(hMemDc,
+ IntGetSysColorBrush(uFlags & DC_ACTIVE ?
+ COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
+
+ if(!hOldBrush)
+ {
+ DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if(HasIcon && (uFlags & DC_GRADIENT))
+ {
+ NtGdiPatBlt(hMemDc, 0, 0,
+ IconWidth+1,
+ lpRc->bottom - lpRc->top,
+ PATCOPY);
+ r.left+=IconWidth;
+ }
+ else
+ {
+ NtGdiPatBlt(hMemDc, 0, 0,
+ lpRc->right - lpRc->left,
+ lpRc->bottom - lpRc->top,
+ PATCOPY);
+ }
+
+ if(uFlags & DC_GRADIENT)
+ {
+ static GRADIENT_RECT gcap = {0, 1};
+ TRIVERTEX vert[2];
+ COLORREF Colors[2];
+ PDC pMemDc;
+
+ if (Wnd != NULL)
+ {
+ if(Wnd->style & WS_SYSMENU)
+ {
+ r.right -= 3 + ButtonWidth;
+ if(!(uFlags & DC_SMALLCAP))
+ {
+ if(Wnd->style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
+ r.right -= 2 + 2 * ButtonWidth;
+ else r.right -= 2;
+ r.right -= 2;
+ }
+
+ //Draw buttons background
+ if(!NtGdiSelectBrush(hMemDc,
+ IntGetSysColorBrush(uFlags & DC_ACTIVE ?
+ COLOR_GRADIENTACTIVECAPTION:COLOR_GRADIENTINACTIVECAPTION)))
+ {
+ DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ NtGdiPatBlt(hMemDc,
+ r.right,
+ 0,
+ lpRc->right - lpRc->left - r.right,
+ lpRc->bottom - lpRc->top,
+ PATCOPY);
+ }
+ }
+
+ Colors[0] = IntGetSysColor((uFlags & DC_ACTIVE) ?
+ COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
+
+ Colors[1] = IntGetSysColor((uFlags & DC_ACTIVE) ?
+ COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION);
+
+ vert[0].x = r.left;
+ vert[0].y = 0;
+ vert[0].Red = (WORD)Colors[0]<<8;
+ vert[0].Green = (WORD)Colors[0] & 0xFF00;
+ vert[0].Blue = (WORD)(Colors[0]>>8) & 0xFF00;
+ vert[0].Alpha = 0;
+
+ vert[1].x = r.right;
+ vert[1].y = lpRc->bottom - lpRc->top;
+ vert[1].Red = (WORD)Colors[1]<<8;
+ vert[1].Green = (WORD)Colors[1] & 0xFF00;
+ vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00;
+ vert[1].Alpha = 0;
+
+ pMemDc = DC_LockDc(hMemDc);
+ if(!pMemDc)
+ {
+ DPRINT1("%s: Can't lock dc!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ /* There is no need to call DC_vPrepareDCsForBlit for memory DC */
+ if(!IntGdiGradientFill(pMemDc, vert, 2, &gcap,
+ 1, GRADIENT_FILL_RECT_H))
+ {
+ DPRINT1("%s: IntGdiGradientFill() failed!\n", __FUNCTION__);
+ }
+
+ DC_UnlockDc(pMemDc);
+ } //if(uFlags & DC_GRADIENT)
+ }
+
+ if(HasIcon)
+ {
+ r.top ++;
+ r.left -= --IconWidth;
+ /* FIXME: Draw the Icon when pWnd == NULL but hIcon is valid */
+ if (pWnd != NULL)
+ UserDrawSysMenuButton(pWnd, hMemDc, &r, FALSE);
+
+ r.left += IconWidth;
+ r.top --;
+ }
+
+ r.top ++;
+ r.left += 2;
+
+ r.bottom = r.top + Height;
+
+ if((uFlags & DC_TEXT))
+ {
+ if(!(uFlags & DC_GRADIENT))
+ {
+ r.right = (lpRc->right - lpRc->left);
+
+ if(uFlags & DC_SMALLCAP)
+ ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
+ else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
+
+ if ((Wnd != NULL) && (Wnd->style & WS_SYSMENU))
+ {
+ r.right -= 3 + ButtonWidth;
+ if(! (uFlags & DC_SMALLCAP))
+ {
+ if(Wnd->style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
+ r.right -= 2 + 2 * ButtonWidth;
+ else r.right -= 2;
+ r.right -= 2;
+ }
+ }
+ }
+
+ /* FIXME: hFont isn't handled */
+ if (str)
+ UserDrawCaptionText(hMemDc, str, &r, uFlags);
+ else if (pWnd != NULL)
++ {
++ UNICODE_STRING ustr;
++ ustr.Buffer = pWnd->Wnd->strName.Buffer;
++ ustr.Length = pWnd->Wnd->strName.Length;
++ ustr.MaximumLength = pWnd->Wnd->strName.MaximumLength;
++ UserDrawCaptionText(hMemDc, &ustr, &r, uFlags);
++ }
+ }
+
+ if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top,
+ lpRc->right - lpRc->left, lpRc->bottom - lpRc->top,
+ hMemDc, 0, 0, SRCCOPY, 0, 0))
+ {
+ DPRINT1("%s: NtGdiBitBlt() failed!\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ Ret = TRUE;
+
+cleanup:
+ if (hOldBrush) NtGdiSelectBrush(hMemDc, hOldBrush);
+ if (hOldBmp) NtGdiSelectBitmap(hMemDc, hOldBmp);
+ if (hMemBmp) GreDeleteObject(hMemBmp);
+ if (hMemDc) NtGdiDeleteObjectApp(hMemDc);
+
+ return Ret;
+}
+
+INT
+FASTCALL
+UserRealizePalette(HDC hdc)
+{
+ HWND hWnd;
+ DWORD Ret;
+
+ Ret = IntGdiRealizePalette(hdc);
+ if (Ret) // There was a change.
+ {
+ hWnd = IntWindowFromDC(hdc);
+ if (hWnd) // Send broadcast if dc is associated with a window.
+ { // FYI: Thread locked in CallOneParam.
+ co_IntSendMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hWnd, 0);
+ }
+ }
+ return Ret;
+}
+
+BOOL
+APIENTRY
+NtUserDrawCaptionTemp(
+ HWND hWnd,
+ HDC hDC,
+ LPCRECT lpRc,
+ HFONT hFont,
+ HICON hIcon,
+ const PUNICODE_STRING str,
+ UINT uFlags)
+{
+ PWINDOW_OBJECT pWnd = NULL;
+ UNICODE_STRING SafeStr = {0};
+ NTSTATUS Status = STATUS_SUCCESS;
+ RECTL SafeRect;
+ BOOL Ret;
+
+ UserEnterExclusive();
+
+ if (hWnd != NULL)
+ {
+ if(!(pWnd = UserGetWindowObject(hWnd)))
+ {
+ UserLeave();
+ return FALSE;
+ }
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(lpRc, sizeof(RECTL), sizeof(ULONG));
+ RtlCopyMemory(&SafeRect, lpRc, sizeof(RECTL));
+ if (str != NULL)
+ {
+ SafeStr = ProbeForReadUnicodeString(str);
+ if (SafeStr.Length != 0)
+ {
+ ProbeForRead( SafeStr.Buffer,
+ SafeStr.Length,
+ sizeof(WCHAR));
+ }
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (Status != STATUS_SUCCESS)
+ {
+ SetLastNtError(Status);
+ UserLeave();
+ return FALSE;
+ }
+
+ if (str != NULL)
+ Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, &SafeStr, uFlags);
+ else
+ Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, NULL, uFlags);
+
+ UserLeave();
+ return Ret;
+}
+
+BOOL
+APIENTRY
+NtUserDrawCaption(HWND hWnd,
+ HDC hDC,
+ LPCRECT lpRc,
+ UINT uFlags)
+{
+ return NtUserDrawCaptionTemp(hWnd, hDC, lpRc, 0, 0, NULL, uFlags);
+}
+
+BOOL
+APIENTRY
+NtUserInvalidateRect(
+ HWND hWnd,
+ CONST RECT *lpUnsafeRect,
+ BOOL bErase)
+{
+ return NtUserRedrawWindow(hWnd, lpUnsafeRect, NULL, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
+}
+
+BOOL
+APIENTRY
+NtUserInvalidateRgn(
+ HWND hWnd,
+ HRGN hRgn,
+ BOOL bErase)
+{
+ return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
+}
+
+/* ValidateRect gets redirected to NtUserValidateRect:
+ http://blog.csdn.net/ntdll/archive/2005/10/19/509299.aspx */
+BOOL
+APIENTRY
+NtUserValidateRect(
+ HWND hWnd,
+ const RECT *lpRect)
+{
+ if (hWnd)
+ {
+ return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_VALIDATE );
+ }
+ return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ERASENOW|RDW_ALLCHILDREN);
+}
+
+/* EOF */