--- /dev/null
+; 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\dhcp\dhcp.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\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
+/*
+ * ReactOS Gdi32
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ *
+ *
+ */
+
+#include "precomp.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+
+typedef int (WINAPI *CHOOSEPIXELFMT) (HDC, CONST PIXELFORMATDESCRIPTOR *);
+typedef BOOL (WINAPI *SETPIXELFMT) (HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+typedef BOOL (WINAPI *SWAPBUFFERS) (HDC hdc);
+typedef int (WINAPI *DESCRIBEPIXELFMT) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+typedef int (WINAPI *GETPIXELFMT) (HDC);
+
+
+static CHOOSEPIXELFMT glChoosePixelFormat = NULL;
+static SETPIXELFMT glSetPixelFormat = NULL;
+static SWAPBUFFERS glSwapBuffers = NULL;
+static DESCRIBEPIXELFMT glDescribePixelFormat = NULL;
+static GETPIXELFMT glGetPixelFormat = NULL;
+
+/*
+ OpenGL Handle.
+*/
+HINSTANCE hOpenGL = NULL;
+
+static BOOL OpenGLInitFunction(PCSTR name,
+ FARPROC *funcptr)
+{
+ PVOID func;
+
+ func = (PVOID)GetProcAddress(hOpenGL, name);
+ if (func != NULL)
+ {
+ (void)InterlockedCompareExchangePointer((PVOID*)funcptr,
+ func,
+ NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL OpenGLEnable(void)
+{
+ HMODULE hModOpengl32;
+ BOOL Ret = TRUE;
+
+ hModOpengl32 = LoadLibraryW(L"OPENGL32.DLL");
+ if (hModOpengl32 == NULL)
+ return FALSE;
+
+ if (InterlockedCompareExchangePointer((PVOID*)&hOpenGL,
+ (PVOID)hModOpengl32,
+ NULL) != NULL)
+ {
+ FreeLibrary(hModOpengl32);
+
+ /* NOTE: Even though another thread was faster loading the
+ library we can't just bail out here. We really need
+ to *try* to locate every function. This is slow but
+ thread-safe */
+ }
+
+
+ if (!OpenGLInitFunction("wglChoosePixelFormat", &glChoosePixelFormat))
+ Ret = FALSE;
+
+ if (!OpenGLInitFunction("wglSetPixelFormat", &glSetPixelFormat))
+ Ret = FALSE;
+
+ if (!OpenGLInitFunction("wglSwapBuffers", &glSwapBuffers))
+ Ret = FALSE;
+
+ if (!OpenGLInitFunction("wglDescribePixelFormat", &glDescribePixelFormat))
+ Ret = FALSE;
+
+ if (!OpenGLInitFunction("wglGetPixelFormat", &glGetPixelFormat))
+ Ret = FALSE;
+
+ return Ret;
+}
+
+
+
+/*
+ * @implemented
+ */
+INT
+WINAPI
+ChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR * ppfd)
+{
+ if (glChoosePixelFormat == NULL)
+ if (OpenGLEnable() == FALSE)
+ return(0);
+
+ return(glChoosePixelFormat(hdc, ppfd));
+}
+
+
+
+/*
+ * @implemented
+ */
+INT
+WINAPI
+DescribePixelFormat(HDC hdc,
+ INT iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ if (glDescribePixelFormat == NULL)
+ if (OpenGLEnable() == FALSE)
+ return(0);
+
+ return(glDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd));
+}
+
+
+
+/*
+ * @implemented
+ */
+INT
+WINAPI
+GetPixelFormat(HDC hdc)
+{
+ if (glGetPixelFormat == NULL)
+ if (OpenGLEnable() == FALSE)
+ return(0);
+
+ return(glGetPixelFormat(hdc));
+}
+
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetPixelFormat(HDC hdc,
+ INT iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR * ppfd)
+{
++ /* Can only be set once */
++ INT current = GetPixelFormat(hdc);
++ if(current) return current == iPixelFormat ;
++
+ if (glSetPixelFormat == NULL)
+ if (OpenGLEnable() == FALSE)
+ return(0);
+
+ return(glSetPixelFormat(hdc, iPixelFormat, ppfd));
+}
+
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SwapBuffers(HDC hdc)
+{
+ if (glSwapBuffers == NULL)
+ if (OpenGLEnable() == FALSE)
+ return(0);
+
+
+ return(glSwapBuffers(hdc));
+}
+
+
+/*
+ Do this here for now.
+*/
+
+/*
+ * @implemented
+ */
+UINT
+WINAPI
+GetEnhMetaFilePixelFormat(
+ HENHMETAFILE hemf,
+ UINT cbBuffer,
+ PIXELFORMATDESCRIPTOR *ppfd
+ )
+{
+ ENHMETAHEADER pemh;
+
+ if(GetEnhMetaFileHeader(hemf, sizeof(ENHMETAHEADER), &pemh))
+ {
+ if(pemh.bOpenGL)
+ {
+ if(pemh.cbPixelFormat)
+ {
+ memcpy((void*)ppfd, UlongToPtr(pemh.offPixelFormat), cbBuffer );
+ return(pemh.cbPixelFormat);
+ }
+ }
+ }
+ return(0);
+}
+
+/* EOF */
--- /dev/null
- icd->refcount++;
-
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: lib/opengl32/opengl32.c
+ * PURPOSE: OpenGL32 lib
+ * PROGRAMMER: Anich Gregor (blight), Royce Mitchell III
+ * UPDATE HISTORY:
+ * Feb 1, 2004: Created
+ */
+
+#include "opengl32.h"
+
+/* function prototypes */
+static void OPENGL32_AppendICD( GLDRIVERDATA *icd );
+static void OPENGL32_RemoveICD( GLDRIVERDATA *icd );
+static GLDRIVERDATA *OPENGL32_LoadDriver( LPCWSTR regKey );
+static DWORD OPENGL32_InitializeDriver( GLDRIVERDATA *icd );
+static BOOL OPENGL32_UnloadDriver( GLDRIVERDATA *icd );
+static DWORD OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd );
+
+
+/* global vars */
+/* Do not assume it have the free value MAXDWORD set, any value can be in here */
+DWORD OPENGL32_tls = MAXDWORD;
+GLPROCESSDATA OPENGL32_processdata;
+
+
+static BOOL
+OPENGL32_ThreadAttach( void )
+{
+ GLTHREADDATA* lpData = NULL;
+ PROC *dispatchTable = NULL;
+ TEB *teb = NULL;
+
+ dispatchTable = (PROC*)HeapAlloc( GetProcessHeap(),
+ HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+ sizeof (((ICDTable *)(0))->dispatch_table) );
+ if (dispatchTable == NULL)
+ {
+ DBGPRINT( "Error: Couldn't allocate GL dispatch table" );
+ return FALSE;
+ }
+
+ lpData = (GLTHREADDATA*)HeapAlloc( GetProcessHeap(),
+ HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+ sizeof (GLTHREADDATA) );
+ if (lpData == NULL)
+ {
+ DBGPRINT( "Error: Couldn't allocate GLTHREADDATA" );
+ HeapFree( GetProcessHeap(), 0, dispatchTable );
+ return FALSE;
+ }
+
+ teb = NtCurrentTeb();
+
+ /* initialize dispatch table with empty functions */
+ #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
+ dispatchTable[icdidx] = (PROC)glEmptyFunc##stack; \
+ if (tebidx >= 0) \
+ teb->glDispatchTable[tebidx] = (PVOID)glEmptyFunc##stack;
+ GLFUNCS_MACRO
+ #undef X
+
+ teb->glTable = dispatchTable;
+ TlsSetValue( OPENGL32_tls, lpData );
+
+ return TRUE;
+}
+
+
+static void
+OPENGL32_ThreadDetach( void )
+{
+ GLTHREADDATA* lpData = NULL;
+ PROC *dispatchTable = NULL;
+
+ rosglMakeCurrent( NULL, NULL );
+
+ lpData = (GLTHREADDATA*)TlsGetValue( OPENGL32_tls );
+ if (lpData != NULL)
+ {
+ if (!HeapFree( GetProcessHeap(), 0, lpData ))
+ DBGPRINT( "Warning: HeapFree() on GLTHREADDATA failed (%d)",
+ GetLastError() );
+ lpData = NULL;
+ }
+
+ dispatchTable = NtCurrentTeb()->glTable;
+ if (dispatchTable != NULL)
+ {
+ if (!HeapFree( GetProcessHeap(), 0, dispatchTable ))
+ DBGPRINT( "Warning: HeapFree() on dispatch table failed (%d)",
+ GetLastError() );
+ }
+}
+
+
+static BOOL
+OPENGL32_ProcessAttach( void )
+{
+ SECURITY_ATTRIBUTES attrib = { sizeof (SECURITY_ATTRIBUTES), /* nLength */
+ NULL, /* lpSecurityDescriptor */
+ TRUE /* bInheritHandle */ };
+
+ OPENGL32_tls = TlsAlloc();
+ if (OPENGL32_tls == MAXDWORD)
+ return FALSE;
+
+ memset( &OPENGL32_processdata, 0, sizeof (OPENGL32_processdata) );
+
+ /* create driver, glrc & dcdata list mutex */
+ OPENGL32_processdata.driver_mutex = CreateMutex( &attrib, FALSE, NULL );
+ if (OPENGL32_processdata.driver_mutex == NULL)
+ {
+ DBGPRINT( "Error: Couldn't create driver_list mutex (%d)",
+ GetLastError() );
+ return FALSE;
+ }
+ OPENGL32_processdata.glrc_mutex = CreateMutex( &attrib, FALSE, NULL );
+ if (OPENGL32_processdata.glrc_mutex == NULL)
+ {
+ DBGPRINT( "Error: Couldn't create glrc_list mutex (%d)",
+ GetLastError() );
+ return FALSE;
+ }
+ OPENGL32_processdata.dcdata_mutex = CreateMutex( &attrib, FALSE, NULL );
+ if (OPENGL32_processdata.dcdata_mutex == NULL)
+ {
+ DBGPRINT( "Error: Couldn't create dcdata_list mutex (%d)",
+ GetLastError() );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+OPENGL32_ProcessDetach( void )
+{
+ GLDRIVERDATA *icd, *icd2;
+ GLDCDATA *dcdata, *dcdata2;
+ GLRC *glrc, *glrc2;
+
+ /* free lists */
+ for (dcdata = OPENGL32_processdata.dcdata_list; dcdata != NULL;)
+ {
+ dcdata2 = dcdata;
+ dcdata = dcdata->next;
+ if (!HeapFree( GetProcessHeap(), 0, dcdata2 ))
+ DBGPRINT( "Warning: HeapFree() on DCDATA 0x%08x failed (%d)",
+ dcdata2, GetLastError() );
+ }
+
+ for (glrc = OPENGL32_processdata.glrc_list; glrc != NULL;)
+ {
+ glrc2 = glrc;
+ glrc = glrc->next;
+ if (!HeapFree( GetProcessHeap(), 0, glrc2 ))
+ DBGPRINT( "Warning: HeapFree() on GLRC 0x%08x failed (%d)",
+ glrc2, GetLastError() );
+ }
+
+ for (icd = OPENGL32_processdata.driver_list; icd != NULL;)
+ {
+ icd2 = icd;
+ icd = icd->next;
+ if (!HeapFree( GetProcessHeap(), 0, icd2 ))
+ DBGPRINT( "Warning: HeapFree() on DRIVERDATA 0x%08x failed (%d)",
+ icd2, GetLastError() );
+ }
+
+ /* free mutexes */
+ if (OPENGL32_processdata.driver_mutex != NULL)
+ CloseHandle( OPENGL32_processdata.driver_mutex );
+ if (OPENGL32_processdata.glrc_mutex != NULL)
+ CloseHandle( OPENGL32_processdata.glrc_mutex );
+ if (OPENGL32_processdata.dcdata_mutex != NULL)
+ CloseHandle( OPENGL32_processdata.dcdata_mutex );
+
+ /* free TLS */
+ if (OPENGL32_tls != MAXDWORD)
+ TlsFree(OPENGL32_tls);
+}
+
+
+BOOL WINAPI
+DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
+{
+ DBGPRINT( "Info: Called!" );
+ switch ( Reason )
+ {
+ /* The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ DBGTRACE( "Process attach" );
+ if (!OPENGL32_ProcessAttach())
+ return FALSE;
+ /* No break: Initialize the index for first thread. */
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ DBGTRACE( "Thread attach" );
+ if (!OPENGL32_ThreadAttach())
+ return FALSE;
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ DBGTRACE( "Thread detach" );
+ /* Release the allocated memory for this thread.*/
+ OPENGL32_ThreadDetach();
+ break;
+
+ /* DLL unload due to process termination or FreeLibrary. */
+ case DLL_PROCESS_DETACH:
+ DBGTRACE( "Process detach" );
+ OPENGL32_ThreadDetach();
+ OPENGL32_ProcessDetach();
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/*! \brief Append ICD to linked list.
+ *
+ * \param icd GLDRIVERDATA to append to list
+ *
+ * \note Only call this when you hold the driver_mutex.
+ */
+static void
+OPENGL32_AppendICD( GLDRIVERDATA *icd )
+{
+ if (OPENGL32_processdata.driver_list == NULL)
+ OPENGL32_processdata.driver_list = icd;
+ else
+ {
+ GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = icd;
+ }
+}
+
+
+/*! \brief Remove ICD from linked list.
+ *
+ * \param icd GLDRIVERDATA to remove from list
+ *
+ * \note Only call this when you hold the driver_mutex.
+ */
+static void
+OPENGL32_RemoveICD( GLDRIVERDATA *icd )
+{
+ if (icd == OPENGL32_processdata.driver_list)
+ OPENGL32_processdata.driver_list = icd->next;
+ else
+ {
+ GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
+ while (p != NULL)
+ {
+ if (p->next == icd)
+ {
+ p->next = icd->next;
+ return;
+ }
+ p = p->next;
+ }
+ DBGPRINT( "Error: ICD 0x%08x not found in list!", icd );
+ }
+}
+
+
+/*! \brief Load an ICD.
+ *
+ * \param driver Name of installable client driver.
+ *
+ * \return Pointer to an allocated GLDRIVERDATA struct.
+ * \retval NULL Failure.
+ *
+ * \todo Call SetLastError() where appropriate.
+ */
+static GLDRIVERDATA *
+OPENGL32_LoadDriver( LPCWSTR driver )
+{
+ LONG ret;
+ GLDRIVERDATA *icd;
+
+ DBGPRINT( "Info: Loading driver %ws...", driver );
+
+ /* allocate driver data */
+ icd = (GLDRIVERDATA*)HeapAlloc( GetProcessHeap(),
+ HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+ sizeof (GLDRIVERDATA) );
+ if (icd == NULL)
+ {
+ DBGPRINT( "Error: Couldn't allocate GLDRIVERDATA! (%d)", GetLastError() );
+ return NULL;
+ }
+
+ ret = OPENGL32_RegGetDriverInfo( driver, icd );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldn't query driver information (%d)", ret );
+ if (!HeapFree( GetProcessHeap(), 0, icd ))
+ DBGPRINT( "Error: HeapFree() returned false, error code = %d",
+ GetLastError() );
+ return NULL;
+ }
+
+ DBGPRINT( "Info: Dll = %ws", icd->dll );
+ DBGPRINT( "Info: Version = 0x%08x", icd->version );
+ DBGPRINT( "Info: DriverVersion = 0x%08x", icd->driver_version );
+ DBGPRINT( "Info: Flags = 0x%08x", icd->flags );
+
+ /* load/initialize ICD */
+ ret = OPENGL32_InitializeDriver( icd );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldnt initialize ICD!" );
+ if (!HeapFree( GetProcessHeap(), 0, icd ))
+ DBGPRINT( "Error: HeapFree() returned false, error code = %d",
+ GetLastError() );
+ return NULL;
+ }
+
+ /* append ICD to list */
+ OPENGL32_AppendICD( icd );
+ DBGPRINT( "Info: ICD loaded." );
+
+ return icd;
+}
+
+
+/*! \brief Initialize a driver (Load DLL and DrvXxx procs)
+ *
+ * \param icd ICD to initialize with the dll, version, driverVersion
+ * and flags already filled.
+ * \return Error code.
+ * \retval ERROR_SUCCESS Success
+ */
+#define LOAD_DRV_PROC( icd, proc, required ) \
+ *(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \
+ if (required && icd->proc == NULL) { \
+ DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
+ FreeLibrary( icd->handle ); \
+ return GetLastError(); \
+ }
+
+static DWORD
+OPENGL32_InitializeDriver( GLDRIVERDATA *icd )
+{
+ /* check version */
+ if (icd->version > 2)
+ DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version );
+
+ /* load dll */
+ icd->handle = LoadLibraryW( icd->dll );
+ if (icd->handle == NULL)
+ {
+ DWORD err = GetLastError();
+ DBGPRINT( "Error: Couldn't load DLL! (%d)", err );
+ return err;
+ }
+
+ /* validate version */
+ if (icd->driver_version > 1)
+ {
+ LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE);
+ if (icd->DrvValidateVersion != NULL)
+ {
+ if (!icd->DrvValidateVersion( icd->driver_version ))
+ {
+ DBGPRINT( "Error: DrvValidateVersion failed!" );
+ DBGBREAK();
+ FreeLibrary( icd->handle );
+ return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */
+ }
+ }
+ else
+ DBGPRINT( "Info: DrvValidateVersion not exported by ICD" );
+ }
+
+ /* load DrvXXX procs */
+ LOAD_DRV_PROC(icd, DrvCopyContext, TRUE);
+ LOAD_DRV_PROC(icd, DrvCreateContext, FALSE);
+ LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE);
+ LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE);
+ LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE);
+ LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE);
+ LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE);
+ LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE);
+ LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE);
+ LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE);
+ LOAD_DRV_PROC(icd, DrvSetContext, TRUE);
+ LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE);
+ LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE);
+ LOAD_DRV_PROC(icd, DrvShareLists, TRUE);
+ LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE);
+ LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE);
+
+ /* we require at least one of DrvCreateContext and DrvCreateLayerContext */
+ if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL)
+ {
+ DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" );
+ FreeLibrary( icd->handle );
+ return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/*! \brief Unload ICD.
+ *
+ * \retval TRUE Success.
+ * \retval FALSE Failure.
+ */
+static BOOL
+OPENGL32_UnloadDriver( GLDRIVERDATA *icd )
+{
+ BOOL allOk = TRUE;
+
+ DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name );
+ if (icd->refcount != 0)
+ DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount );
+
+ /* unload dll */
+ if (!FreeLibrary( icd->handle ))
+ {
+ allOk = FALSE;
+ DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll,
+ GetLastError() );
+ }
+
+ /* free resources */
+ OPENGL32_RemoveICD( icd );
+ if (!HeapFree( GetProcessHeap(), 0, icd ))
+ {
+ allOk = FALSE;
+ DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d",
+ GetLastError() );
+ }
+
+ return allOk;
+}
+
+
+/*! \brief Load ICD (shared ICD data)
+ *
+ * \return Pointer to an allocated GLDRIVERDATA on success.
+ * \retval NULL Failure.
+ */
+GLDRIVERDATA *
+OPENGL32_LoadICD( LPCWSTR driver )
+{
+ GLDRIVERDATA *icd;
+
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return NULL; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
+ /* look if ICD is already loaded */
+ for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next)
+ {
+ if (!_wcsicmp( driver, icd->driver_name )) /* found */
+ {
- if (icd != NULL)
- icd->refcount = 1;
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+ return icd;
+ }
+ }
+
+ /* not found - try to load */
+ icd = OPENGL32_LoadDriver( driver );
- if (--icd->refcount == 0)
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+ return icd;
+}
+
+
+/*! \brief Unload ICD (shared ICD data)
+ *
+ * \retval TRUE Success.
+ * \retval FALSE Failure.
+ */
+BOOL
+OPENGL32_UnloadICD( GLDRIVERDATA *icd )
+{
+ BOOL ret = TRUE;
+
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return FALSE; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
++ if (icd->refcount == 0)
+ ret = OPENGL32_UnloadDriver( icd );
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+ return ret;
+}
+
+
+/*! \brief Enumerate OpenGLDrivers (from registry)
+ *
+ * \param idx Index of the driver to get information about.
+ * \param name Pointer to an array of WCHARs (can be NULL)
+ * \param cName Pointer to a DWORD. Input is len of name array.
+ * Output is length of the drivername.
+ * Can be NULL if name is NULL.
+ *
+ * \return Error code
+ * \retval ERROR_NO_MORE_ITEMS End of driver list.
+ * \retval ERROR_SUCCESS Success.
+ */
+#if 0 /* unused */
+DWORD
+OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
+{
+ HKEY hKey;
+ LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY;
+ LONG ret;
+ DWORD size;
+ WCHAR driver[256];
+
+ if (name == NULL)
+ return ERROR_SUCCESS; /* nothing to do */
+
+ if (cName == NULL)
+ return ERROR_INVALID_FUNCTION; /* we need cName when name is given */
+
+ /* open OpenGLDrivers registry key */
+ ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
+ return ret;
+ }
+
+ /* get subkey name */
+ size = sizeof (driver) / sizeof (driver[0]);
+ ret = RegEnumKeyW( hKey, idx, name, *cName );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret );
+ RegCloseKey( hKey );
+ return ret;
+ }
+ *cName = wcslen( name );
+
+ /* close key */
+ RegCloseKey( hKey );
+ return ERROR_SUCCESS;
+}
+#endif /* 0 -- unused */
+
+
+/*! \brief Get registry values for a driver given a name.
+ *
+ * \param driver Name of the driver to get information about.
+ * \param icd Pointer to GLDRIVERDATA.
+ *
+ * \return Error code.
+ * \retval ERROR_SUCCESS Success.
+ *
+ * \note On success the following fields of \a icd are filled: \a driver_name,
+ * \a dll, \a version, \a driver_version and \a flags.
+ */
+static DWORD
+OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd )
+{
+ HKEY hKey;
+ WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY2;
+ LONG ret;
+ DWORD type, size;
+
+ /* drivers registry values */
+ DWORD version = 1, driverVersion = 0, flags = 0;
+ WCHAR dll[256];
+
+ /* open driver registry key */
+ wcsncat( subKey, driver, 1024 );
+ ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
+ return ret;
+ }
+
+ /* query values */
+ size = sizeof (dll);
+ ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size );
+ if (ret != ERROR_SUCCESS || type != REG_SZ)
+ {
+ DBGPRINT( "Error: Couldn't query Dll value or not a string" );
+ RegCloseKey( hKey );
+ return ret;
+ }
+
+ size = sizeof (DWORD);
+ ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size );
+ if (ret != ERROR_SUCCESS || type != REG_DWORD)
+ DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" );
+
+ size = sizeof (DWORD);
+ ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type,
+ (LPBYTE)&driverVersion, &size );
+ if (ret != ERROR_SUCCESS || type != REG_DWORD)
+ DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" );
+
+ size = sizeof (DWORD);
+ ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size );
+ if (ret != ERROR_SUCCESS || type != REG_DWORD)
+ DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" );
+
+ /* close key */
+ RegCloseKey( hKey );
+
+ /* output data */
+ /* FIXME: NUL-terminate strings? */
+ wcsncpy( icd->driver_name, driver,
+ sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 );
+ wcsncpy( icd->dll, dll,
+ sizeof (icd->dll) / sizeof (icd->dll[0]) );
+ icd->version = version;
+ icd->driver_version = driverVersion;
+ icd->flags = flags;
+
+ return ERROR_SUCCESS;
+}
+
+/* EOF */
+
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: lib/opengl32/opengl32.h
+ * PURPOSE: OpenGL32 lib
+ * PROGRAMMER: Royce Mitchell III, Anich Gregor (blight)
+ * UPDATE HISTORY:
+ * Feb 1, 2004: Created
+ */
+
+#ifndef OPENGL32_PRIVATE_H
+#define OPENGL32_PRIVATE_H
+
+#define snwprintf _snwprintf
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define NDEBUG
+
+#ifndef PFD_GENERIC_ACCELERATED
+# define PFD_GENERIC_ACCELERATED 0x00001000
+#endif
+
+#define OPENGL_DRIVERS_SUBKEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"
+#define OPENGL_DRIVERS_SUBKEY2 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers\\"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <winreg.h>
+
+#define NTOS_MODE_USER
+#include <winddi.h>
+#include <ndk/ntndk.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+/* gl function list */
+#include "glfuncs.h"
+
+/* ICD index list/types */
+#include "icdtable.h"
+
+/* debug flags */
+#if !defined(NDEBUG)
+# define DEBUG_OPENGL32
+/* enable breakpoints */
+/*# define DEBUG_OPENGL32_BRKPTS*/
+/* dumps the list of (un)supported glXXX functions when an ICD is loaded. */
+# define DEBUG_OPENGL32_ICD_EXPORTS
+/* prints much information about whats going on */
+# define DEBUG_OPENGL32_TRACE
+#endif /* !NDEBUG */
+
+/* debug macros */
+# ifdef DEBUG_OPENGL32
+# include <debug.h>
+# define DBGPRINT( fmt, args... ) \
+ DPRINT( "OpenGL32.DLL: %s: "fmt"\n", __FUNCTION__, ##args )
+# endif
+
+#ifndef DBGPRINT
+# define DBGPRINT( ... ) do {} while (0)
+#endif
+
+#ifdef DEBUG_OPENGL32_BRKPTS
+# if defined(__GNUC__)
+# define DBGBREAK() __asm__( "int $3" );
+# elif defined(_MSC_VER)
+# define DBGBREAK() __asm { int 3 }
+# else
+# error Unsupported compiler!
+# endif
+#else
+# define DBGBREAK() do {} while (0)
+#endif
+
+#ifdef DEBUG_OPENGL32_TRACE
+# define DBGTRACE( args... ) DBGPRINT( args )
+#else
+# define DBGTRACE( ... ) do {} while (0)
+#endif
+
+/* function/data attributes */
+#define EXPORT __declspec(dllexport)
+#ifdef _MSC_VER
+# define NAKED __declspec(naked)
+# define SHARED
+# ifndef WINAPI
+# define WINAPI __stdcall
+# endif /* WINAPI */
+#else /* GCC */
+# define NAKED __attribute__((naked))
+# define SHARED __attribute__((section("shared"), shared))
+#endif
+
+#ifdef APIENTRY
+#undef APIENTRY
+#endif /* APIENTRY */
+#define APIENTRY __stdcall
+
+/* Called by the driver to set the dispatch table */
+typedef DWORD (WINAPI *SetContextCallBack)( const ICDTable * );
+
+/* OpenGL ICD data */
+typedef struct tagGLDRIVERDATA
+{
+ HMODULE handle; /*!< DLL handle */
+ UINT refcount; /*!< Number of references to this ICD */
+ WCHAR driver_name[256]; /*!< Name of ICD driver */
+
+ WCHAR dll[256]; /*!< Dll filename from registry */
+ DWORD version; /*!< Version value from registry */
+ DWORD driver_version; /*!< DriverVersion value from registry */
+ DWORD flags; /*!< Flags value from registry */
+
+ BOOL (WINAPI *DrvCopyContext)( HGLRC, HGLRC, UINT );
+ HGLRC (WINAPI *DrvCreateContext)( HDC );
+ HGLRC (WINAPI *DrvCreateLayerContext)( HDC, int );
+ BOOL (WINAPI *DrvDeleteContext)( HGLRC );
+ BOOL (WINAPI *DrvDescribeLayerPlane)( HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR );
+ int (WINAPI *DrvDescribePixelFormat)( IN HDC, IN int, IN UINT, OUT LPPIXELFORMATDESCRIPTOR );
+ int (WINAPI *DrvGetLayerPaletteEntries)( HDC, int, int, int, COLORREF * );
+ PROC (WINAPI *DrvGetProcAddress)( LPCSTR lpProcName );
+ void (WINAPI *DrvReleaseContext)( HGLRC hglrc ); /* maybe returns BOOL? */
+ BOOL (WINAPI *DrvRealizeLayerPalette)( HDC, int, BOOL );
+ PICDTable (WINAPI *DrvSetContext)( HDC hdc, HGLRC hglrc, SetContextCallBack callback );
+ int (WINAPI *DrvSetLayerPaletteEntries)( HDC, int, int, int, CONST COLORREF * );
+ BOOL (WINAPI *DrvSetPixelFormat)( IN HDC, IN int, const PIXELFORMATDESCRIPTOR * );
+ BOOL (WINAPI *DrvShareLists)( HGLRC, HGLRC );
+ BOOL (WINAPI *DrvSwapBuffers)( HDC );
+ BOOL (WINAPI *DrvSwapLayerBuffers)( HDC, UINT );
+ BOOL (WINAPI *DrvValidateVersion)( DWORD );
+
+ struct tagGLDRIVERDATA *next; /* next ICD -- linked list */
+} GLDRIVERDATA;
+
+/* Our private OpenGL context (stored in TLS) */
+typedef struct tagGLRC
+{
+ GLDRIVERDATA *icd; /*!< driver used for this context */
+ HDC hdc; /*!< DC handle */
+ BOOL is_current; /*!< Wether this context is current for some DC */
+ DWORD thread_id; /*!< Thread holding this context */
+
+ HGLRC hglrc; /*!< GLRC from DrvCreateContext (ICD internal) */
+
+ struct tagGLRC *next; /* linked list */
+} GLRC;
+
+/* OpenGL private device context data */
+typedef struct tagGLDCDATA
+{
+ HDC hdc; /*!< Device context handle for which this data is */
+ GLDRIVERDATA *icd; /*!< Driver used for this DC */
+ int pixel_format; /*!< Selected pixel format */
+
+ struct tagGLDCDATA *next; /* linked list */
+} GLDCDATA;
+
+
+/* Process data */
+typedef struct tagGLPROCESSDATA
+{
+ GLDRIVERDATA *driver_list; /*!< List of loaded drivers */
+ HANDLE driver_mutex; /*!< Mutex to protect driver list */
+ GLRC *glrc_list; /*!< List of GL rendering contexts */
+ HANDLE glrc_mutex; /*!< Mutex to protect glrc list */
+ GLDCDATA *dcdata_list; /*!< List of GL private DC data */
+ HANDLE dcdata_mutex; /*!< Mutex to protect glrc list */
+} GLPROCESSDATA;
+
+/* TLS data */
+typedef struct tagGLTHREADDATA
+{
+ GLRC *glrc; /*!< current GL rendering context */
+} GLTHREADDATA;
+
+extern DWORD OPENGL32_tls;
+extern GLPROCESSDATA OPENGL32_processdata;
+#define OPENGL32_threaddata ((GLTHREADDATA *)TlsGetValue( OPENGL32_tls ))
+
+/* function prototypes */
+GLDRIVERDATA *OPENGL32_LoadICD( LPCWSTR driver );
+BOOL OPENGL32_UnloadICD( GLDRIVERDATA *icd );
+BOOL APIENTRY rosglMakeCurrent( HDC hdc, HGLRC hglrc );
++int APIENTRY rosglGetPixelFormat( HDC );
+BOOL APIENTRY IntUseFontBitmapsA( HDC hDC, DWORD first, DWORD count, DWORD listBase );
+BOOL APIENTRY IntUseFontBitmapsW( HDC hDC, DWORD first, DWORD count, DWORD listBase );
+BOOL APIENTRY IntUseFontOutlinesA( HDC hDC, DWORD first, DWORD count, DWORD listBase,
+ FLOAT chordalDeviation, FLOAT extrusion, INT format,
+ GLYPHMETRICSFLOAT *glyphMetricsFloatArray );
+BOOL APIENTRY IntUseFontOutlinesW( HDC hDC, DWORD first, DWORD count, DWORD listBase,
+ FLOAT chordalDeviation, FLOAT extrusion, INT format,
+ GLYPHMETRICSFLOAT *glyphMetricsFloatArray );
+
+/* empty gl functions from gl.c */
+int WINAPI glEmptyFunc0( void );
+int WINAPI glEmptyFunc4( long );
+int WINAPI glEmptyFunc8( long, long );
+int WINAPI glEmptyFunc12( long, long, long );
+int WINAPI glEmptyFunc16( long, long, long, long );
+int WINAPI glEmptyFunc20( long, long, long, long, long );
+int WINAPI glEmptyFunc24( long, long, long, long, long, long );
+int WINAPI glEmptyFunc28( long, long, long, long, long, long, long );
+int WINAPI glEmptyFunc32( long, long, long, long, long, long, long, long );
+int WINAPI glEmptyFunc36( long, long, long, long, long, long, long, long,
+ long );
+int WINAPI glEmptyFunc40( long, long, long, long, long, long, long, long,
+ long, long );
+int WINAPI glEmptyFunc44( long, long, long, long, long, long, long, long,
+ long, long, long );
+int WINAPI glEmptyFunc48( long, long, long, long, long, long, long, long,
+ long, long, long, long );
+int WINAPI glEmptyFunc52( long, long, long, long, long, long, long, long,
+ long, long, long, long, long );
+int WINAPI glEmptyFunc56( long, long, long, long, long, long, long, long,
+ long, long, long, long, long, long );
+
+#ifdef OPENGL32_GL_FUNC_PROTOTYPES
+
+#define X(func,ret,typeargs,args,icdidx,tebidx,stack) ret WINAPI func typeargs;
+GLFUNCS_MACRO
+#undef X
+
+#endif /* OPENGL32_GL_FUNC_PROTOTYPES */
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* OPENGL32_PRIVATE_H */
+
+/* EOF */
--- /dev/null
- if (glrc->icd != NULL)
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: lib/opengl32/wgl.c
+ * PURPOSE: OpenGL32 lib, rosglXXX functions
+ * PROGRAMMER: Anich Gregor (blight)
+ * UPDATE HISTORY:
+ * Feb 2, 2004: Created
+ */
+
+#define OPENGL32_GL_FUNC_PROTOTYPES
+#include "opengl32.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if !defined(UNIMPLEMENTED)
+# define UNIMPLEMENTED DBGPRINT( "UNIMPLEMENTED" )
+#endif
+
+
+typedef struct _OPENGL_INFO
+{
+ DWORD Version; /*!< Driver interface version */
+ DWORD DriverVersion; /*!< Driver version */
+ WCHAR DriverName[256]; /*!< Driver name */
+} OPENGL_INFO, *POPENGL_INFO;
+
+
+/*! \brief Append OpenGL Rendering Context (GLRC) to list
+ *
+ * \param glrc [IN] Pointer to GLRC to append to list
+ */
+static
+void
+ROSGL_AppendContext( GLRC *glrc )
+{
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
+ if (OPENGL32_processdata.glrc_list == NULL)
+ OPENGL32_processdata.glrc_list = glrc;
+ else
+ {
+ GLRC *p = OPENGL32_processdata.glrc_list;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = glrc;
+ }
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+}
+
+
+/*! \brief Remove OpenGL Rendering Context (GLRC) from list
+ *
+ * \param glrc [IN] Pointer to GLRC to remove from list
+ */
+static
+void
+ROSGL_RemoveContext( GLRC *glrc )
+{
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
+ if (glrc == OPENGL32_processdata.glrc_list)
+ OPENGL32_processdata.glrc_list = glrc->next;
+ else
+ {
+ GLRC *p = OPENGL32_processdata.glrc_list;
+ while (p != NULL)
+ {
+ if (p->next == glrc)
+ {
+ p->next = glrc->next;
+ break;
+ }
+ p = p->next;
+ }
+ if (p == NULL)
+ DBGPRINT( "Error: GLRC 0x%08x not found in list!", glrc );
+ }
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+}
+
+
+/*! \brief Create a new GL Context (GLRC) and append it to the list
+ *
+ * \return Pointer to new GLRC on success
+ * \retval NULL Returned on failure (i.e. Out of memory)
+ */
+static
+GLRC *
+ROSGL_NewContext(void)
+{
+ GLRC *glrc;
+
+ /* allocate GLRC */
+ glrc = (GLRC*)HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, sizeof (GLRC) );
+
+ /* append to list */
+ ROSGL_AppendContext( glrc );
+
+ return glrc;
+}
+
+/*! \brief Delete all GLDCDATA with this IDC
+ *
+ * \param icd [IN] Pointer to a ICD
+ */
+static
+VOID
+ROSGL_DeleteDCDataForICD( GLDRIVERDATA *icd )
+{
+ GLDCDATA *p, **pptr;
+
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.dcdata_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return;
+ }
+
+ p = OPENGL32_processdata.dcdata_list;
+ pptr = &OPENGL32_processdata.dcdata_list;
+ while (p != NULL)
+ {
+ if (p->icd == icd)
+ {
+ *pptr = p->next;
+ OPENGL32_UnloadICD( p->icd );
+
+ if (!HeapFree( GetProcessHeap(), 0, p ))
+ DBGPRINT( "Warning: HeapFree() on GLDCDATA failed (%d)",
+ GetLastError() );
+
+ p = *pptr;
+ }
+ else
+ {
+ pptr = &p->next;
+ p = p->next;
+ }
+ }
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.dcdata_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+}
+
+
+/*! \brief Delete a GL Context (GLRC) and remove it from the list
+ *
+ * \param glrc [IN] Pointer to GLRC to delete
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+static
+BOOL
+ROSGL_DeleteContext( GLRC *glrc )
+{
+ /* unload icd */
- if (data->hdc == hdc) /* found */
++ if ((glrc->icd != NULL) && !(InterlockedDecrement((LONG*)&glrc->icd->refcount)))
++ {
++ /* This is the last context, remove the ICD */
+ ROSGL_DeleteDCDataForICD( glrc->icd );
++ }
+
+ /* remove from list */
+ ROSGL_RemoveContext( glrc );
+
+ /* free memory */
+ HeapFree( GetProcessHeap(), 0, glrc );
+
+ return TRUE;
+}
+
+
+/*! \brief Check wether a GLRC is in the list
+ *
+ * \param glrc [IN] Pointer to GLRC to look for in the list
+ *
+ * \retval TRUE GLRC was found
+ * \retval FALSE GLRC was not found
+ */
+static
+BOOL
+ROSGL_ContainsContext( GLRC *glrc )
+{
+ GLRC *p;
+ BOOL found = FALSE;
+
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.glrc_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return FALSE; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
+ p = OPENGL32_processdata.glrc_list;
+ while (p != NULL)
+ {
+ if (p == glrc)
+ {
+ found = TRUE;
+ break;
+ }
+ p = p->next;
+ }
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.glrc_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+ return found;
+}
+
+
+/*! \brief Get GL private DC data.
+ *
+ * This function adds an empty GLDCDATA to the list if there is no data for the
+ * given DC yet.
+ *
+ * \param hdc [IN] Handle to a Device Context for which to get the data
+ *
+ * \return Pointer to GLDCDATA on success
+ * \retval NULL on failure
+ */
+static
+GLDCDATA *
+ROSGL_GetPrivateDCData( HDC hdc )
+{
+ GLDCDATA *data;
+
+ /* check hdc */
+ if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC)
+ {
+ DBGPRINT( "Error: hdc is not a DC handle!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* synchronize */
+ if (WaitForSingleObject( OPENGL32_processdata.dcdata_mutex, INFINITE ) ==
+ WAIT_FAILED)
+ {
+ DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+ return NULL; /* FIXME: do we have to expect such an error and handle it? */
+ }
+
+ /* look for data in list */
+ data = OPENGL32_processdata.dcdata_list;
+ while (data != NULL)
+ {
- OPENGL32_UnloadICD(drvdata);
++ if ((data->hdc == hdc) || (WindowFromDC(data->hdc) == WindowFromDC(hdc))) /* found */
+ break;
+ data = data->next;
+ }
+
+ /* allocate new data if not found in list */
+ if (data == NULL)
+ {
+ data = HeapAlloc( GetProcessHeap(),
+ HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS,
+ sizeof (GLDCDATA) );
+ if (data == NULL)
+ {
+ DBGPRINT( "Error: HeapAlloc() failed (%d)", GetLastError() );
+ }
+ else
+ {
+ data->hdc = hdc;
+
+ /* append data to list */
+ if (OPENGL32_processdata.dcdata_list == NULL)
+ OPENGL32_processdata.dcdata_list = data;
+ else
+ {
+ GLDCDATA *p = OPENGL32_processdata.dcdata_list;
+ while (p->next != NULL)
+ p = p->next;
+ p->next = data;
+ }
+ }
+ }
+
+ /* release mutex */
+ if (!ReleaseMutex( OPENGL32_processdata.dcdata_mutex ))
+ DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+ return data;
+}
+
+
+/*! \brief Get ICD from HDC.
+ *
+ * This function asks the display driver which OpenGL ICD to load for the given
+ * HDC, loads it and returns a pointer to a GLDRIVERDATA struct on success.
+ *
+ * \param hdc [IN] Handle for DC for which to load/get the ICD
+ *
+ * \return Pointer to GLDRIVERDATA
+ * \retval NULL Failure.
+ */
+static
+GLDRIVERDATA *
+ROSGL_ICDForHDC( HDC hdc )
+{
+ GLDCDATA *dcdata;
+ GLDRIVERDATA *drvdata;
+
+ dcdata = ROSGL_GetPrivateDCData( hdc );
+ if (dcdata == NULL)
+ return NULL;
+
+ if (dcdata->icd == NULL)
+ {
+ LPCWSTR driverName;
+ OPENGL_INFO info;
+
+ /* NOTE: This might be done by multiple threads simultaneously, but only the fastest
+ actually gets to set the ICD! */
+
+ driverName = _wgetenv( L"OPENGL32_DRIVER" );
+ if (driverName == NULL)
+ {
+ DWORD dwInput;
+ LONG ret;
+
+ /* get driver name */
+ dwInput = OPENGL_GETINFO;
+ ret = ExtEscape( hdc, QUERYESCSUPPORT, sizeof (dwInput), (LPCSTR)&dwInput, 0, NULL );
+ if (ret > 0)
+ {
+ dwInput = 0;
+ ret = ExtEscape( hdc, OPENGL_GETINFO, sizeof (dwInput),
+ (LPCSTR)&dwInput, sizeof (OPENGL_INFO),
+ (LPSTR)&info );
+ }
+ if (ret <= 0)
+ {
+ HKEY hKey;
+ DWORD type, size;
+
+ if (ret < 0)
+ {
+ DBGPRINT( "Warning: ExtEscape to get the drivername failed! (%d)", GetLastError() );
+ if (MessageBox( WindowFromDC( hdc ), L"Couldn't get installable client driver name!\nUsing default driver.",
+ L"OPENGL32.dll: Warning", MB_OKCANCEL | MB_ICONWARNING ) == IDCANCEL)
+ {
+ return NULL;
+ }
+ }
+
+ /* open registry key */
+ ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, OPENGL_DRIVERS_SUBKEY, 0, KEY_QUERY_VALUE, &hKey );
+ if (ret != ERROR_SUCCESS)
+ {
+ DBGPRINT( "Error: Couldn't open registry key '%ws'", OPENGL_DRIVERS_SUBKEY );
+ SetLastError( ret );
+ return NULL;
+ }
+
+ /* query value */
+ size = sizeof (info.DriverName);
+ ret = RegQueryValueExW( hKey, L"DefaultDriver", 0, &type, (LPBYTE)info.DriverName, &size );
+ RegCloseKey( hKey );
+ if (ret != ERROR_SUCCESS || type != REG_SZ)
+ {
+ DBGPRINT( "Error: Couldn't query DefaultDriver value or not a string" );
+ SetLastError( ret );
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ wcsncpy( info.DriverName, driverName, sizeof (info.DriverName) / sizeof (info.DriverName[0]) );
+ }
+ /* load driver (or get a reference) */
+ drvdata = OPENGL32_LoadICD( info.DriverName );
+ if (drvdata == NULL)
+ {
+ WCHAR Buffer[256];
+ snwprintf(Buffer, sizeof(Buffer)/sizeof(WCHAR),
+ L"Couldn't load driver \"%s\".", info.DriverName);
+ MessageBox(WindowFromDC( hdc ), Buffer,
+ L"OPENGL32.dll: Warning",
+ MB_OK | MB_ICONWARNING);
+ }
+ else
+ {
+ /* Atomically set the ICD!!! */
+ if (InterlockedCompareExchangePointer((PVOID*)&dcdata->icd,
+ (PVOID)drvdata,
+ NULL) != NULL)
+ {
+ /* Too bad, somebody else was faster... */
++ DBGTRACE("Uh, Someone beat you to it!\n");
+ }
+ }
+ }
+
+ return dcdata->icd;
+}
+
+
+/*! \brief SetContextCallBack passed to DrvSetContext.
+ *
+ * This function gets called by the OpenGL driver whenever the current GL
+ * context (dispatch table) is to be changed.
+ *
+ * \param table [IN] Function pointer table (first DWORD is number of functions)
+ *
+ * \return unkown (maybe void? ERROR_SUCCESS at the moment)
+ */
+DWORD
+CALLBACK
+ROSGL_SetContextCallBack( const ICDTable *table )
+{
+ TEB *teb;
+ PROC *tebTable, *tebDispatchTable;
+ INT size;
+
+ teb = NtCurrentTeb();
+ tebTable = (PROC *)teb->glTable;
+ tebDispatchTable = (PROC *)teb->glDispatchTable;
+
+ DBGTRACE( "Called!" );
+
+ if (table != NULL)
+ {
+ DBGPRINT( "Function count: %d\n", table->num_funcs );
+
+ /* save table */
+ size = sizeof (PROC) * table->num_funcs;
+ memcpy( tebTable, table->dispatch_table, size );
+ memset( tebTable + table->num_funcs, 0,
+ sizeof (table->dispatch_table) - size );
+ }
+ else
+ {
+ DBGPRINT( "Unsetting current context" );
+ memset( tebTable, 0, sizeof (table->dispatch_table) );
+ }
+
+ /* put in empty functions as long as we dont have a fallback */
+ #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
+ if (tebTable[icdidx] == NULL) \
+ { \
+ if (table != NULL) \
+ DBGPRINT( "Warning: GL proc '%s' is NULL", #func ); \
+ tebTable[icdidx] = (PROC)glEmptyFunc##stack; \
+ }
+ GLFUNCS_MACRO
+#undef X
+
+ /* fill teb->glDispatchTable for fast calls */
+#define X(func, ret, typeargs, args, icdidx, tebidx, stack) \
+ if (tebidx >= 0) \
+ tebDispatchTable[tebidx] = tebTable[icdidx];
+ GLFUNCS_MACRO
+#undef X
+
+ DBGPRINT( "Done." );
+
+ return ERROR_SUCCESS;
+}
+
+
+/*! \brief Attempts to find the best matching pixel format for HDC
+ *
+ * This function is comparing each available format with the preferred one
+ * and returns the one which is closest to it.
+ * If PFD_DOUBLEBUFFER, PFD_STEREO or one of PFD_DRAW_TO_WINDOW,
+ * PFD_DRAW_TO_BITMAP, PFD_SUPPORT_GDI and PDF_SUPPORT_OPENGL is given then
+ * only formats which also support those will be enumerated (unless
+ * PFD_DOUBLEBUFFER_DONTCARE or PFD_STEREO_DONTCARE is also set)
+ *
+ * \param hdc [IN] Handle to DC for which to get a pixel format index
+ * \param pfd [IN] PFD describing what kind of format you want
+ *
+ * \return Pixel format index
+ * \retval 0 Failed to find a suitable format
+ */
+#define BUFFERDEPTH_SCORE(want, have) \
+ ((want == 0) ? (0) : ((want < have) ? (1) : ((want > have) ? (3) : (0))))
+
+/* Score if we want and not have it */
+#define FLAG_SCORE(want, have, flag) \
+ (((want & ~have) & flag) ? (1) : (0))
+
+/* Score if what we want is different than what we have, except when
+ _DONTCARE was set */
+#define FLAG_SCORE_DONTCARE(want, have, flag) \
+ ((!(have & flag ## _DONTCARE)) && ((want & flag) != (have & flag)) ? (1) : (0))
+
+int
+APIENTRY
+rosglChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *pfd )
+{
+ GLDRIVERDATA *icd;
+ PIXELFORMATDESCRIPTOR icdPfd;
+ int i;
+ int best = 0;
+ int score, bestScore = 0x7fff; /* used to choose a pfd if no exact match */
+ int icdNumFormats;
+
+ DBGTRACE( "Called!" );
+
+ /* load ICD */
+ icd = ROSGL_ICDForHDC( hdc );
+ if (icd == NULL)
+ return 0;
+
+ /* check input */
+ if (pfd->nSize != sizeof (PIXELFORMATDESCRIPTOR) || pfd->nVersion != 1)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
+
+ /* get number of formats */
+ icdNumFormats = icd->DrvDescribePixelFormat( hdc, 1,
+ sizeof (PIXELFORMATDESCRIPTOR), &icdPfd );
+ if (icdNumFormats == 0)
+ {
+ DBGPRINT( "Error: DrvDescribePixelFormat failed (%d)", GetLastError() );
+ return 0;
+ }
+ DBGPRINT( "Info: Enumerating %d pixelformats", icdNumFormats );
+
+ /* try to find best format */
+ for (i = 0; i < icdNumFormats; i++)
+ {
+ if (icd->DrvDescribePixelFormat( hdc, i + 1,
+ sizeof (PIXELFORMATDESCRIPTOR), &icdPfd ) == 0)
+ {
+ DBGPRINT( "Warning: DrvDescribePixelFormat failed (%d)",
+ GetLastError() );
+ break;
+ }
+
+ if ((pfd->dwFlags & PFD_GENERIC_ACCELERATED) != 0) /* we do not support such kind of drivers */
+ {
+ continue;
+ }
+
+ score = 0; /* higher is worse */
+
+ /* compare flags */
+ score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_DRAW_TO_WINDOW);
+ score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_DRAW_TO_BITMAP);
+ score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_SUPPORT_GDI);
+ score += FLAG_SCORE(pfd->dwFlags, icdPfd.dwFlags, PFD_SUPPORT_OPENGL);
+ score += FLAG_SCORE_DONTCARE(pfd->dwFlags, icdPfd.dwFlags, PFD_DOUBLEBUFFER);
+ score += FLAG_SCORE_DONTCARE(pfd->dwFlags, icdPfd.dwFlags, PFD_STEREO);
+
+ /* check other attribs */
+ if (pfd->iPixelType != icdPfd.iPixelType)
+ score += 5; /* this is really bad i think */
+ if (pfd->iLayerType != icdPfd.iLayerType)
+ score += 15; /* this is very very bad ;) */
+
+ score += BUFFERDEPTH_SCORE(pfd->cAlphaBits, icdPfd.cAlphaBits);
+ score += BUFFERDEPTH_SCORE(pfd->cAccumBits, icdPfd.cAccumBits);
+ score += BUFFERDEPTH_SCORE(pfd->cDepthBits, icdPfd.cDepthBits);
+ score += BUFFERDEPTH_SCORE(pfd->cStencilBits, icdPfd.cStencilBits);
+ score += BUFFERDEPTH_SCORE(pfd->cAuxBuffers, icdPfd.cAuxBuffers);
+
+ /* check score */
+ if (score < bestScore)
+ {
+ bestScore = score;
+ best = i + 1;
+ if (bestScore == 0)
+ break;
+ }
+ }
+
+ if (best == 0)
+ SetLastError( 0 ); /* FIXME: set appropriate error */
+
+ DBGPRINT( "Info: Suggesting pixelformat %d", best );
+ return best;
+}
+
+
+/*! \brief Copy data specified by mask from one GLRC to another.
+ *
+ * \param src [IN] Source GLRC
+ * \param src [OUT] Destination GLRC
+ * \param mask [IN] Bitfield like given to glPushAttrib()
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+BOOL
+APIENTRY
+rosglCopyContext( HGLRC hsrc, HGLRC hdst, UINT mask )
+{
+ GLRC *src = (GLRC *)hsrc;
+ GLRC *dst = (GLRC *)hdst;
+
+ /* check glrcs */
+ if (!ROSGL_ContainsContext( src ))
+ {
+ DBGPRINT( "Error: src GLRC not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+ if (!ROSGL_ContainsContext( dst ))
+ {
+ DBGPRINT( "Error: dst GLRC not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* I think this is only possible within one ICD */
+ if (src->icd != dst->icd)
+ {
+ DBGPRINT( "Error: src and dst GLRC use different ICDs!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* copy data (call ICD) */
+ return src->icd->DrvCopyContext( src->hglrc, dst->hglrc, mask );
+}
+
+
+/*! \brief Create a new GL Rendering Context.
+ *
+ * This function can create over- or underlay surfaces.
+ *
+ * \param hdc [IN] Handle for DC for which to create context
+ * \param layer [IN] Layer number to bind (draw?) to
+ *
+ * \return Handle for the created GLRC
+ * \retval NULL Failure
+ */
+HGLRC
+APIENTRY
+rosglCreateLayerContext( HDC hdc, int layer )
+{
+ GLDRIVERDATA *icd = NULL;
+ GLRC *glrc;
+ HGLRC drvHglrc = NULL;
+
+ DBGTRACE( "Called!" );
+
+/* if (GetObjectType( hdc ) != OBJ_DC)
+ {
+ DBGPRINT( "Error: hdc is not a DC handle!" );
+ return NULL;
+ }
+*/
+ /* create new GLRC */
+ glrc = ROSGL_NewContext();
+ if (glrc == NULL)
+ return NULL;
+
+ /* load ICD */
+ icd = ROSGL_ICDForHDC( hdc );
+ if (icd == NULL)
+ {
+ ROSGL_DeleteContext( glrc );
+ DBGPRINT( "Couldn't get ICD by HDC :-(" );
+ /* FIXME: fallback? */
+ return NULL;
+ }
++
++ /* Don't forget to refcount it, icd will be released when last context is deleted */
++ InterlockedIncrement((LONG*)&icd->refcount);
++
++ if(!rosglGetPixelFormat(hdc))
++ {
++ ROSGL_DeleteContext(glrc);
++ SetLastError(ERROR_INVALID_PIXEL_FORMAT);
++ return NULL;
++ }
+
+ /* create context */
+ if (icd->DrvCreateLayerContext != NULL)
+ drvHglrc = icd->DrvCreateLayerContext( hdc, layer );
+ if (drvHglrc == NULL)
+ {
+ if (layer == 0 && icd->DrvCreateContext != NULL)
+ drvHglrc = icd->DrvCreateContext( hdc );
+ else
+ DBGPRINT( "Warning: CreateLayerContext not supported by ICD!" );
+ }
+
+ if (drvHglrc == NULL)
+ {
+ /* FIXME: fallback to mesa? */
+ DBGPRINT( "Error: DrvCreate[Layer]Context failed! (%d)", GetLastError() );
+ ROSGL_DeleteContext( glrc );
+ return NULL;
+ }
+
+ /* we have our GLRC in glrc and the ICD's GLRC in drvHglrc */
+ glrc->hglrc = drvHglrc;
+ glrc->icd = icd;
+
+ return (HGLRC)glrc;
+}
+
+
+/*! \brief Create a new GL Rendering Context.
+ *
+ * \param hdc [IN] Handle for DC for which to create context
+ *
+ * \return Handle for the created GLRC
+ * \retval NULL Failure
+ */
+HGLRC
+APIENTRY
+rosglCreateContext( HDC hdc )
+{
+ return rosglCreateLayerContext( hdc, 0 );
+}
+
+
+/*! \brief Delete an OpenGL context
+ *
+ * \param hglrc [IN] Handle to GLRC to delete; must not be a threads current RC!
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure (i.e. GLRC is current for a thread)
+ */
+BOOL
+APIENTRY
+rosglDeleteContext( HGLRC hglrc )
+{
+ GLRC *glrc = (GLRC *)hglrc;
+
+ /* check if we know about this context */
+ if (!ROSGL_ContainsContext( glrc ))
+ {
+ DBGPRINT( "Error: hglrc not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* make sure GLRC is not current for some thread */
+ if (glrc->is_current)
+ {
+ DBGPRINT( "Error: GLRC is current for DC 0x%08x", glrc->hdc );
+ SetLastError( ERROR_INVALID_FUNCTION );
+ return FALSE;
+ }
+
+ /* release ICD's context */
+ if (glrc->hglrc != NULL)
+ {
+ if (!glrc->icd->DrvDeleteContext( glrc->hglrc ))
+ {
+ DBGPRINT( "Warning: DrvDeleteContext() failed (%d)", GetLastError() );
+ return FALSE;
+ }
+ }
+
+ /* free resources */
+ return ROSGL_DeleteContext( glrc );
+}
+
+
+BOOL
+APIENTRY
+rosglDescribeLayerPlane( HDC hdc, int iPixelFormat, int iLayerPlane,
+ UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd )
+{
+ UNIMPLEMENTED;
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return FALSE;
+}
+
+
+/*! \brief Gets information about a pixelformat.
+ *
+ * \param hdc [IN] Handle to DC
+ * \param iFormat [IN] Pixelformat index
+ * \param nBytes [IN] sizeof (pfd) - at most nBytes are copied into pfd
+ * \param pfd [OUT] Pointer to a PIXELFORMATDESCRIPTOR
+ *
+ * \return Maximum pixelformat index/number of formats
+ * \retval 0 Failure
+ */
+int
+APIENTRY
+rosglDescribePixelFormat( HDC hdc, int iFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR pfd )
+{
+ int ret = 0;
+ GLDRIVERDATA *icd = ROSGL_ICDForHDC( hdc );
+
+ if (icd != NULL)
+ {
+ ret = icd->DrvDescribePixelFormat( hdc, iFormat, nBytes, pfd );
+ if (ret == 0)
+ DBGPRINT( "Error: DrvDescribePixelFormat(format=%d) failed (%d)", iFormat, GetLastError() );
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_FUNCTION );
+ }
+
+ return ret;
+}
+
+
+/*! \brief Return the thread's current GLRC
+ *
+ * \return Handle for thread's current GLRC
+ * \retval NULL No current GLRC set
+ */
+HGLRC
+APIENTRY
+rosglGetCurrentContext()
+{
+ return (HGLRC)(OPENGL32_threaddata->glrc);
+}
+
+
+/*! \brief Return the thread's current DC
+ *
+ * \return Handle for thread's current DC
+ * \retval NULL No current DC/GLRC set
+ */
+HDC
+APIENTRY
+rosglGetCurrentDC()
+{
+ /* FIXME: is it correct to return NULL when there is no current GLRC or
+ is there another way to find out the wanted HDC? */
+ if (OPENGL32_threaddata->glrc == NULL)
+ return NULL;
+ return (HDC)(OPENGL32_threaddata->glrc->hdc);
+}
+
+
+int
+APIENTRY
+rosglGetLayerPaletteEntries( HDC hdc, int iLayerPlane, int iStart,
+ int cEntries, COLORREF *pcr )
+{
+ UNIMPLEMENTED;
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return 0;
+}
+
+
+/*! \brief Returns the current pixelformat.
+ *
+ * \param hdc [IN] Handle to DC to get the pixelformat from
+ *
+ * \return Pixelformat index
+ * \retval 0 Failure
+ */
+int
+WINAPI
+rosglGetPixelFormat( HDC hdc )
+{
+ GLDCDATA *dcdata;
+
+ DBGTRACE( "Called!" );
+
+ dcdata = ROSGL_GetPrivateDCData( hdc );
+ if (dcdata == NULL)
+ {
+ DBGPRINT( "Error: ROSGL_GetPrivateDCData failed!" );
+ return 0;
+ }
+
+ return dcdata->pixel_format;
+}
+
+
+/*! \brief Get the address for an OpenGL extension function.
+ *
+ * The addresses this function returns are only valid within the same thread
+ * which it was called from.
+ *
+ * \param proc [IN] Name of the function to look for
+ *
+ * \return The address of the proc
+ * \retval NULL Failure
+ */
+PROC
+APIENTRY
+rosglGetProcAddress( LPCSTR proc )
+{
+ PROC func;
+ GLDRIVERDATA *icd;
+
+ /* FIXME we should Flush the gl here */
+
+ if (OPENGL32_threaddata->glrc == NULL)
+ {
+ DBGPRINT( "Error: No current GLRC!" );
+ SetLastError( ERROR_INVALID_FUNCTION );
+ return NULL;
+ }
+
+ icd = OPENGL32_threaddata->glrc->icd;
+ func = icd->DrvGetProcAddress( proc );
+ if (func != NULL)
+ {
+ DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc );
+ return func;
+ }
+
+ /* FIXME: Should we return wgl/gl 1.1 functions? */
+ SetLastError( ERROR_PROC_NOT_FOUND );
+ return NULL;
+}
+
+PROC
+APIENTRY
+rosglGetDefaultProcAddress( LPCSTR proc )
+{
+ PROC func;
+ GLDRIVERDATA *icd;
+
+ /* wglGetDefaultProcAddress does not flush the gl */
+
+ if (OPENGL32_threaddata->glrc == NULL)
+ {
+ DBGPRINT( "Error: No current GLRC!" );
+ SetLastError( ERROR_INVALID_FUNCTION );
+ return NULL;
+ }
+
+ icd = OPENGL32_threaddata->glrc->icd;
+ func = icd->DrvGetProcAddress( proc );
+ if (func != NULL)
+ {
+ DBGPRINT( "Info: Proc \"%s\" loaded from ICD.", proc );
+ return func;
+ }
+
+ /* FIXME: Should we return wgl/gl 1.1 functions? */
+ SetLastError( ERROR_PROC_NOT_FOUND );
+ return NULL;
+}
+
+
+/*! \brief Make the given GLRC the threads current GLRC for hdc
+ *
+ * \param hdc [IN] Handle for a DC to be drawn on
+ * \param hglrc [IN] Handle for a GLRC to make current
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+BOOL
+APIENTRY
+rosglMakeCurrent( HDC hdc, HGLRC hglrc )
+{
+ GLRC *glrc = (GLRC *)hglrc;
+ ICDTable *icdTable = NULL;
+
+ DBGTRACE( "Called!" );
+
+ if (OPENGL32_threaddata == NULL)
+ return FALSE;
+
+ /* flush current context */
+ if (OPENGL32_threaddata->glrc != NULL)
+ {
+ glFlush();
+ }
+
+ /* check if current context is unset */
+ if (glrc == NULL)
+ {
+ if (OPENGL32_threaddata->glrc != NULL)
+ {
+ glrc = OPENGL32_threaddata->glrc;
+ glrc->icd->DrvReleaseContext( glrc->hglrc );
+ glrc->is_current = FALSE;
+ OPENGL32_threaddata->glrc = NULL;
+ }
++ else if ((GetObjectType(hdc) != OBJ_DC) && (GetObjectType(hdc) != OBJ_MEMDC))
++ {
++ DBGPRINT("Current context is NULL and requested HDC is invalid.\n");
++ SetLastError(ERROR_INVALID_HANDLE);
++ return FALSE;
++ }
+ }
+ else
+ {
+ /* check hdc */
+ if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC)
+ {
+ DBGPRINT( "Error: hdc is not a DC handle!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* check if we know about this glrc */
+ if (!ROSGL_ContainsContext( glrc ))
+ {
+ DBGPRINT( "Error: hglrc not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* check if it is available */
+ if (glrc->is_current && glrc->thread_id != GetCurrentThreadId()) /* used by another thread */
+ {
+ DBGPRINT( "Error: hglrc is current for thread 0x%08x", glrc->thread_id );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* call the ICD */
+ if (glrc->hglrc != NULL)
+ {
+ DBGPRINT( "Info: Calling DrvSetContext!" );
+ SetLastError( ERROR_SUCCESS );
+ icdTable = glrc->icd->DrvSetContext( hdc, glrc->hglrc,
+ (void *)ROSGL_SetContextCallBack );
+ if (icdTable == NULL)
+ {
+ DBGPRINT( "Error: DrvSetContext failed (%d)\n", GetLastError() );
+ return FALSE;
+ }
+ DBGPRINT( "Info: DrvSetContext succeeded!" );
+ }
+
+ /* make it current */
+ if (OPENGL32_threaddata->glrc != NULL)
+ OPENGL32_threaddata->glrc->is_current = FALSE;
+ glrc->is_current = TRUE;
+ glrc->thread_id = GetCurrentThreadId();
+ glrc->hdc = hdc;
+ OPENGL32_threaddata->glrc = glrc;
+ }
+
+ if (ROSGL_SetContextCallBack( icdTable ) != ERROR_SUCCESS && icdTable == NULL)
+ {
+ DBGPRINT( "Warning: ROSGL_SetContextCallBack failed!" );
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+APIENTRY
+rosglRealizeLayerPalette( HDC hdc, int iLayerPlane, BOOL bRealize )
+{
+ UNIMPLEMENTED;
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return FALSE;
+}
+
+
+int
+APIENTRY
+rosglSetLayerPaletteEntries( HDC hdc, int iLayerPlane, int iStart,
+ int cEntries, CONST COLORREF *pcr )
+{
+ UNIMPLEMENTED;
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return 0;
+}
+
+
+/*! \brief Set a DCs pixelformat
+ *
+ * \param hdc [IN] Handle to DC for which to set the format
+ * \param iFormat [IN] Index of the pixelformat to set
+ * \param pfd [IN] Not sure what this is for
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+BOOL
+WINAPI
+rosglSetPixelFormat( HDC hdc, int iFormat, CONST PIXELFORMATDESCRIPTOR *pfd )
+{
+ GLDRIVERDATA *icd;
+ GLDCDATA *dcdata;
+
+ DBGTRACE( "Called!" );
+
+ /* load ICD */
+ icd = ROSGL_ICDForHDC( hdc );
+ if (icd == NULL)
+ {
+ DBGPRINT( "Warning: ICDForHDC() failed" );
+ return FALSE;
+ }
+
+ /* call ICD */
+ if (!icd->DrvSetPixelFormat( hdc, iFormat, pfd ))
+ {
+ DBGPRINT( "Warning: DrvSetPixelFormat(format=%d) failed (%d)",
+ iFormat, GetLastError() );
+ return FALSE;
+ }
+
+ /* store format in private DC data */
+ dcdata = ROSGL_GetPrivateDCData( hdc );
+ if (dcdata == NULL)
+ {
+ DBGPRINT( "Error: ROSGL_GetPrivateDCData() failed!" );
+ return FALSE;
+ }
+ dcdata->pixel_format = iFormat;
+
+ return TRUE;
+}
+
+
+/*! \brief Enable display-list sharing between multiple GLRCs
+ *
+ * This will only work if both GLRCs are from the same driver.
+ *
+ * \param hglrc1 [IN] GLRC number 1
+ * \param hglrc2 [IN] GLRC number 2
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+BOOL
+APIENTRY
+rosglShareLists( HGLRC hglrc1, HGLRC hglrc2 )
+{
+ GLRC *glrc1 = (GLRC *)hglrc1;
+ GLRC *glrc2 = (GLRC *)hglrc2;
+
+ /* check glrcs */
+ if (!ROSGL_ContainsContext( glrc1 ))
+ {
+ DBGPRINT( "Error: hglrc1 not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+ if (!ROSGL_ContainsContext( glrc2 ))
+ {
+ DBGPRINT( "Error: hglrc2 not found!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* I think this is only possible within one ICD */
+ if (glrc1->icd != glrc2->icd)
+ {
+ DBGPRINT( "Error: hglrc1 and hglrc2 use different ICDs!" );
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+
+ /* share lists (call ICD) */
+ return glrc1->icd->DrvShareLists( glrc1->hglrc, glrc2->hglrc );
+}
+
+
+/*! \brief Flushes GL and swaps front/back buffer if appropriate
+ *
+ * \param hdc [IN] Handle to device context to swap buffers for
+ *
+ * \retval TRUE Success
+ * \retval FALSE Failure
+ */
+BOOL
+APIENTRY
+rosglSwapBuffers( HDC hdc )
+{
+ GLDRIVERDATA *icd = ROSGL_ICDForHDC( hdc );
+ DBGTRACE( "Called!" );
+ if (icd != NULL)
+ {
+ DBGPRINT( "Swapping buffers!" );
+ if (!icd->DrvSwapBuffers( hdc ))
+ {
+ DBGPRINT( "Error: DrvSwapBuffers failed (%d)", GetLastError() );
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* FIXME: implement own functionality? */
+ SetLastError( ERROR_INVALID_FUNCTION );
+ return FALSE;
+}
+
+
+BOOL
+APIENTRY
+rosglSwapLayerBuffers( HDC hdc, UINT fuPlanes )
+{
+ BOOL ret = FALSE;
+
+ if(fuPlanes & WGL_SWAP_MAIN_PLANE)
+ ret = rosglSwapBuffers(hdc);
+
+ if(fuPlanes &~WGL_SWAP_MAIN_PLANE)
+ DBGTRACE("wglSwapLayerBuffers is not fully implemented\n");
+
+ return ret;
+}
+
+
+BOOL
+APIENTRY
+rosglUseFontBitmapsA( HDC hdc, DWORD first, DWORD count, DWORD listBase )
+{
+ return IntUseFontBitmapsA(hdc, first, count, listBase);
+}
+
+
+BOOL
+APIENTRY
+rosglUseFontBitmapsW( HDC hdc, DWORD first, DWORD count, DWORD listBase )
+{
+ return IntUseFontBitmapsW(hdc, first, count, listBase);
+}
+
+BOOL
+APIENTRY
+rosglUseFontOutlinesA( HDC hdc, DWORD first, DWORD count, DWORD listBase,
+ FLOAT deviation, FLOAT extrusion, int format,
+ GLYPHMETRICSFLOAT *pgmf )
+{
+ return IntUseFontOutlinesA(hdc, first, count, listBase, deviation, extrusion, format, pgmf);
+}
+
+
+BOOL
+APIENTRY
+rosglUseFontOutlinesW( HDC hdc, DWORD first, DWORD count, DWORD listBase,
+ FLOAT deviation, FLOAT extrusion, int format,
+ GLYPHMETRICSFLOAT *pgmf )
+{
+ return IntUseFontOutlinesW(hdc, first, count, listBase, deviation, extrusion, format, pgmf);
+}
+
+#ifdef __cplusplus
+}; /* extern "C" */
+#endif /* __cplusplus */
+
+/* EOF */
--- /dev/null
- /* Loop through the driver names */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: GDI Driver Device Functions
+ * FILE: subsys/win32k/eng/device.c
+ * PROGRAMER: Jason Filby
+ * Timo Kreuzer
+ */
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+static PGRAPHICS_DEVICE gpGraphicsDeviceFirst = NULL;
+static PGRAPHICS_DEVICE gpGraphicsDeviceLast = NULL;
+static HSEMAPHORE ghsemGraphicsDeviceList;
+static ULONG giDevNum = 1;
+
+BOOL
+NTAPI
+InitDeviceImpl()
+{
+ ghsemGraphicsDeviceList = EngCreateSemaphore();
+ if (!ghsemGraphicsDeviceList)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+PGRAPHICS_DEVICE
+NTAPI
+EngpRegisterGraphicsDevice(
+ PUNICODE_STRING pustrDeviceName,
+ PUNICODE_STRING pustrDiplayDrivers,
+ PUNICODE_STRING pustrDescription,
+ PDEVMODEW pdmDefault)
+{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVICE_OBJECT pDeviceObject;
+ PFILE_OBJECT pFileObject;
+ NTSTATUS Status;
+ PWSTR pwsz;
+ ULONG i, cj, cModes = 0;
+ BOOL bEnable = TRUE;
+ PDEVMODEINFO pdminfo;
+ PDEVMODEW pdm, pdmEnd;
+ PLDEVOBJ pldev;
+
+ DPRINT1("EngpRegisterGraphicsDevice(%S)\n", pustrDeviceName->Buffer);
+
+ /* Allocate a GRAPHICS_DEVICE structure */
+ pGraphicsDevice = ExAllocatePoolWithTag(PagedPool,
+ sizeof(GRAPHICS_DEVICE),
+ GDITAG_GDEVICE);
+ if (!pGraphicsDevice)
+ {
+ DPRINT1("ExAllocatePoolWithTag failed\n");
+ return NULL;
+ }
+
+ /* Try to open the driver */
+ Status = IoGetDeviceObjectPointer(pustrDeviceName,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ &pFileObject,
+ &pDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not open driver, 0x%lx\n", Status);
+ ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE);
+ return NULL;
+ }
+
+ /* Enable the device */
+ EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cj);
+
+ /* Copy the device and file object pointers */
+ pGraphicsDevice->DeviceObject = pDeviceObject;
+ pGraphicsDevice->FileObject = pFileObject;
+
+ /* Copy device name */
+ wcsncpy(pGraphicsDevice->szNtDeviceName,
+ pustrDeviceName->Buffer,
+ sizeof(pGraphicsDevice->szNtDeviceName) / sizeof(WCHAR));
+
+ /* Create a win device name (FIXME: virtual devices!) */
+ swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\VIDEO%d", (CHAR)giDevNum);
+
+ /* Allocate a buffer for the strings */
+ cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR);
+ pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP);
+ if (!pwsz)
+ {
+ DPRINT1("Could not allocate string buffer\n");
+ ASSERT(FALSE); // FIXME
+ }
+
+ /* Copy display driver names */
+ pGraphicsDevice->pDiplayDrivers = pwsz;
+ RtlCopyMemory(pGraphicsDevice->pDiplayDrivers,
+ pustrDiplayDrivers->Buffer,
+ pustrDiplayDrivers->Length);
+
+ /* Copy description */
+ pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR);
+ RtlCopyMemory(pGraphicsDevice->pwszDescription,
+ pustrDescription->Buffer,
+ pustrDescription->Length + sizeof(WCHAR));
+
+ /* Initialize the pdevmodeInfo list and default index */
+ pGraphicsDevice->pdevmodeInfo = NULL;
+ pGraphicsDevice->iDefaultMode = 0;
+ pGraphicsDevice->iCurrentMode = 0;
+
+ // FIXME: initialize state flags
+ pGraphicsDevice->StateFlags = 0;
+
- for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
++ /* Loop through the driver names
++ * This is a REG_MULTI_SZ string */
+ for (; *pwsz; pwsz += wcslen(pwsz) + 1)
+ {
+ DPRINT1("trying driver: %ls\n", pwsz);
+ /* Try to load the display driver */
+ pldev = EngLoadDriver(pwsz, LDEV_DEVICE_DISPLAY);
+ if (!pldev)
+ {
+ DPRINT1("Could not load driver: '%ls'\n", pwsz);
+ continue;
+ }
+
+ /* Get the mode list from the driver */
+ pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject);
+ if (!pdminfo)
+ {
+ DPRINT1("Could not get mode list for '%ls'\n", pwsz);
+ continue;
+ }
+
+ /* Attach the mode info to the device */
+ pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo;
+ pGraphicsDevice->pdevmodeInfo = pdminfo;
+
+ /* Count DEVMODEs */
+ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+ for (pdm = pdminfo->adevmode;
+ pdm + 1 <= pdmEnd;
+ pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+ {
+ cModes++;
+ }
+
+ // FIXME: release the driver again until it's used?
+ }
+
+ if (!pGraphicsDevice->pdevmodeInfo || cModes == 0)
+ {
+ DPRINT1("No devmodes\n");
+ ExFreePool(pGraphicsDevice);
+ return NULL;
+ }
+
+ /* Allocate an index buffer */
+ pGraphicsDevice->cDevModes = cModes;
+ pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool,
+ cModes * sizeof(DEVMODEENTRY),
+ GDITAG_GDEVICE);
+ if (!pGraphicsDevice->pDevModeList)
+ {
+ DPRINT1("No devmode list\n");
+ ExFreePool(pGraphicsDevice);
+ return NULL;
+ }
+
+ /* Loop through all DEVMODEINFOs */
++ for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
+ pdminfo;
+ pdminfo = pdminfo->pdmiNext)
+ {
+ /* Calculate End of the DEVMODEs */
+ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+
+ /* Loop through the DEVMODEs */
+ for (pdm = pdminfo->adevmode;
+ pdm + 1 <= pdmEnd;
+ pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+ {
+ /* Compare with the default entry */
+ if (pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
+ pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
+ pdm->dmPelsHeight == pdmDefault->dmPelsHeight &&
+ pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
+ {
+ pGraphicsDevice->iDefaultMode = i;
+ pGraphicsDevice->iCurrentMode = i;
+ DPRINT1("Found default entry: %ld '%ls'\n", i, pdm->dmDeviceName);
+ }
+
+ /* Initialize the entry */
+ pGraphicsDevice->pDevModeList[i].dwFlags = 0;
+ pGraphicsDevice->pDevModeList[i].pdm = pdm;
+ i++;
+ }
+ }
+
+ /* Lock loader */
+ EngAcquireSemaphore(ghsemGraphicsDeviceList);
+
+ /* Insert the device into the global list */
+ pGraphicsDevice->pNextGraphicsDevice = gpGraphicsDeviceLast;
+ gpGraphicsDeviceLast = pGraphicsDevice;
+ if (!gpGraphicsDeviceFirst)
+ gpGraphicsDeviceFirst = pGraphicsDevice;
+
+ /* Increment device number */
+ giDevNum++;
+
+ /* Unlock loader */
+ EngReleaseSemaphore(ghsemGraphicsDeviceList);
+ DPRINT1("Prepared %ld modes for %ls\n", cModes, pGraphicsDevice->pwszDescription);
+
+ return pGraphicsDevice;
+}
+
+
+PGRAPHICS_DEVICE
+NTAPI
+EngpFindGraphicsDevice(
+ PUNICODE_STRING pustrDevice,
+ ULONG iDevNum,
+ DWORD dwFlags)
+{
+ UNICODE_STRING ustrCurrent;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG i;
+
+ /* Lock list */
+ EngAcquireSemaphore(ghsemGraphicsDeviceList);
+
+ if (pustrDevice)
+ {
+ /* Loop through the list of devices */
+ for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0;
+ pGraphicsDevice;
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++)
+ {
+ /* Compare the device name */
+ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+ if (RtlEqualUnicodeString(&ustrCurrent, pustrDevice, FALSE))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Loop through the list of devices */
+ for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0;
+ pGraphicsDevice && i < iDevNum;
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++);
+ }
+
+ /* Unlock list */
+ EngReleaseSemaphore(ghsemGraphicsDeviceList);
+
+ return pGraphicsDevice;
+}
+
+
+static
+NTSTATUS
+EngpFileIoRequest(
+ PFILE_OBJECT pFileObject,
+ ULONG ulMajorFunction,
+ LPVOID lpBuffer,
+ DWORD nBufferSize,
+ ULONGLONG ullStartOffset,
+ OUT LPDWORD lpInformation)
+{
+ PDEVICE_OBJECT pDeviceObject;
+ KEVENT Event;
+ PIRP pIrp;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ LARGE_INTEGER liStartOffset;
+
+ /* Get corresponding device object */
+ pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
+ if (!pDeviceObject)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Initialize an event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ /* Build IRP */
+ liStartOffset.QuadPart = ullStartOffset;
+ pIrp = IoBuildSynchronousFsdRequest(ulMajorFunction,
+ pDeviceObject,
+ lpBuffer,
+ nBufferSize,
+ &liStartOffset,
+ &Event,
+ &Iosb);
+ if (!pIrp)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Call the driver */
+ Status = IoCallDriver(pDeviceObject, pIrp);
+
+ /* Wait if neccessary */
+ if (STATUS_PENDING == Status)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
+ Status = Iosb.Status;
+ }
+
+ /* Return information to the caller about the operation. */
+ *lpInformation = Iosb.Information;
+
+ /* Return NTSTATUS */
+ return Status;
+}
+
+VOID
+APIENTRY
+EngFileWrite(
+ IN PFILE_OBJECT pFileObject,
+ IN PVOID lpBuffer,
+ IN SIZE_T nLength,
+ IN PSIZE_T lpBytesWritten)
+{
+ EngpFileIoRequest(pFileObject,
+ IRP_MJ_WRITE,
+ lpBuffer,
+ nLength,
+ 0,
+ lpBytesWritten);
+}
+
+NTSTATUS
+APIENTRY
+EngFileIoControl(
+ IN PFILE_OBJECT pFileObject,
+ IN DWORD dwIoControlCode,
+ IN PVOID lpInBuffer,
+ IN SIZE_T nInBufferSize,
+ OUT PVOID lpOutBuffer,
+ IN SIZE_T nOutBufferSize,
+ OUT LPDWORD lpInformation)
+{
+ PDEVICE_OBJECT pDeviceObject;
+ KEVENT Event;
+ PIRP pIrp;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+
+ /* Get corresponding device object */
+ pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
+ if (!pDeviceObject)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Initialize an event */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ /* Build IO control IRP */
+ pIrp = IoBuildDeviceIoControlRequest(dwIoControlCode,
+ pDeviceObject,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ FALSE,
+ &Event,
+ &Iosb);
+ if (!pIrp)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Call the driver */
+ Status = IoCallDriver(pDeviceObject, pIrp);
+
+ /* Wait if neccessary */
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
+ Status = Iosb.Status;
+ }
+
+ /* Return information to the caller about the operation. */
+ *lpInformation = Iosb.Information;
+
+ /* This function returns NTSTATUS */
+ return Status;
+}
+
+/*
+ * @implemented
+ */
+DWORD APIENTRY
+EngDeviceIoControl(
+ HANDLE hDevice,
+ DWORD dwIoControlCode,
+ LPVOID lpInBuffer,
+ DWORD nInBufferSize,
+ LPVOID lpOutBuffer,
+ DWORD nOutBufferSize,
+ DWORD *lpBytesReturned)
+{
+ PIRP Irp;
+ NTSTATUS Status;
+ KEVENT Event;
+ IO_STATUS_BLOCK Iosb;
+ PDEVICE_OBJECT DeviceObject;
+
+ DPRINT("EngDeviceIoControl() called\n");
+
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ DeviceObject = (PDEVICE_OBJECT) hDevice;
+
+ Irp = IoBuildDeviceIoControlRequest(dwIoControlCode,
+ DeviceObject,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize, FALSE, &Event, &Iosb);
+ if (!Irp) return ERROR_NOT_ENOUGH_MEMORY;
+
+ Status = IoCallDriver(DeviceObject, Irp);
+
+ if (Status == STATUS_PENDING)
+ {
+ (VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
+ Status = Iosb.Status;
+ }
+
+ DPRINT("EngDeviceIoControl(): Returning %X/%X\n", Iosb.Status,
+ Iosb.Information);
+
+ /* Return information to the caller about the operation. */
+ *lpBytesReturned = Iosb.Information;
+
+ /* Convert NT status values to win32 error codes. */
+ switch (Status)
+ {
+ case STATUS_INSUFFICIENT_RESOURCES:
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ case STATUS_BUFFER_OVERFLOW:
+ return ERROR_MORE_DATA;
+
+ case STATUS_NOT_IMPLEMENTED:
+ return ERROR_INVALID_FUNCTION;
+
+ case STATUS_INVALID_PARAMETER:
+ return ERROR_INVALID_PARAMETER;
+
+ case STATUS_BUFFER_TOO_SMALL:
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ case STATUS_DEVICE_DOES_NOT_EXIST:
+ return ERROR_DEV_NOT_EXIST;
+
+ case STATUS_PENDING:
+ return ERROR_IO_PENDING;
+ }
+
+ return Status;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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.
+ */
+/*
+ * Entry Point for win32k.sys
+ */
+
+#include <win32k.h>
+#include <include/napi.h>
+
+#define NDEBUG
+#include <debug.h>
+
+HANDLE hModuleWin;
+
+PGDI_HANDLE_TABLE INTERNAL_CALL GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject);
+BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process);
+/* FIXME */
+PGDI_HANDLE_TABLE GdiHandleTable = NULL;
+PSECTION_OBJECT GdiTableSection = NULL;
+
+HANDLE GlobalUserHeap = NULL;
+PSECTION_OBJECT GlobalUserHeapSection = NULL;
+
+PSERVERINFO gpsi = NULL; // Global User Server Information.
+
+HSEMAPHORE hsemDriverMgmt = NULL;
+
+SHORT gusLanguageID;
+
+extern ULONG_PTR Win32kSSDT[];
+extern UCHAR Win32kSSPT[];
+extern ULONG Win32kNumberOfSysCalls;
+
+NTSTATUS
+APIENTRY
+Win32kProcessCallback(struct _EPROCESS *Process,
+ BOOLEAN Create)
+{
+ PPROCESSINFO Win32Process;
+ DECLARE_RETURN(NTSTATUS);
+
+ DPRINT("Enter Win32kProcessCallback\n");
+ UserEnterExclusive();
+
+ /* Get the Win32 Process */
+ Win32Process = PsGetProcessWin32Process(Process);
+
+ /* Allocate one if needed */
+ if (!Win32Process)
+ {
+ /* FIXME - lock the process */
+ Win32Process = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(PROCESSINFO),
+ 'p23W');
+
+ if (Win32Process == NULL) RETURN( STATUS_NO_MEMORY);
+
+ RtlZeroMemory(Win32Process, sizeof(PROCESSINFO));
+
+ PsSetProcessWin32Process(Process, Win32Process);
+ /* FIXME - unlock the process */
+ }
+
+ if (Create)
+ {
+ SIZE_T ViewSize = 0;
+ LARGE_INTEGER Offset;
+ PVOID UserBase = NULL;
+ NTSTATUS Status;
+ extern PSECTION_OBJECT GlobalUserHeapSection;
+ DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
+
+ /* map the global heap into the process */
+ Offset.QuadPart = 0;
+ Status = MmMapViewOfSection(GlobalUserHeapSection,
+ 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 the global heap! 0x%x\n", Status);
+ RETURN(Status);
+ }
+ Win32Process->HeapMappings.Next = NULL;
+ Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
+ Win32Process->HeapMappings.UserMapping = UserBase;
+ Win32Process->HeapMappings.Count = 1;
+
+ InitializeListHead(&Win32Process->ClassList);
+
+ InitializeListHead(&Win32Process->MenuListHead);
+
+ InitializeListHead(&Win32Process->GDIBrushAttrFreeList);
+ InitializeListHead(&Win32Process->GDIDcAttrFreeList);
+
+ InitializeListHead(&Win32Process->PrivateFontListHead);
+ ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
+
+ InitializeListHead(&Win32Process->DriverObjListHead);
+ ExInitializeFastMutex(&Win32Process->DriverObjListLock);
+
+ Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
+
+ if(Process->Peb != NULL)
+ {
+ /* map the gdi handle table to user land */
+ Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(GdiTableSection, Process);
+ Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
+ }
+
+ Win32Process->peProcess = Process;
+ /* setup process flags */
+ Win32Process->W32PF_flags = 0;
+ }
+ else
+ {
+ DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
+ IntCleanupMenus(Process, Win32Process);
+ IntCleanupCurIcons(Process, Win32Process);
+ CleanupMonitorImpl();
+
+ /* no process windows should exist at this point, or the function will assert! */
+ DestroyProcessClasses(Win32Process);
+
+ GDI_CleanupForProcess(Process);
+
+ co_IntGraphicsCheck(FALSE);
+
+ /*
+ * Deregister logon application automatically
+ */
+ if(LogonProcess == Win32Process)
+ {
+ LogonProcess = NULL;
+ }
+ }
+
+ RETURN( STATUS_SUCCESS);
+
+CLEANUP:
+ UserLeave();
+ DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_);
+ END_CLEANUP;
+}
+
+
+NTSTATUS
+APIENTRY
+Win32kThreadCallback(struct _ETHREAD *Thread,
+ PSW32THREADCALLOUTTYPE Type)
+{
+ struct _EPROCESS *Process;
+ PTHREADINFO Win32Thread;
+ DECLARE_RETURN(NTSTATUS);
+
+ DPRINT("Enter Win32kThreadCallback\n");
+ UserEnterExclusive();
+
+ Process = Thread->ThreadsProcess;
+
+ /* Get the Win32 Thread */
+ Win32Thread = PsGetThreadWin32Thread(Thread);
+
+ /* Allocate one if needed */
+ if (!Win32Thread)
+ {
+ /* FIXME - lock the process */
+ Win32Thread = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(THREADINFO),
+ 't23W');
+
+ if (Win32Thread == NULL) RETURN( STATUS_NO_MEMORY);
+
+ RtlZeroMemory(Win32Thread, sizeof(THREADINFO));
+
+ PsSetThreadWin32Thread(Thread, Win32Thread);
+ /* FIXME - unlock the process */
+ }
+ if (Type == PsW32ThreadCalloutInitialize)
+ {
+ HWINSTA hWinSta = NULL;
+ PTEB pTeb;
+ HDESK hDesk = NULL;
+ NTSTATUS Status;
+ PUNICODE_STRING DesktopPath;
+ PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
+
+ DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
+
+ InitializeListHead(&Win32Thread->WindowListHead);
+ InitializeListHead(&Win32Thread->W32CallbackListHead);
+ InitializeListHead(&Win32Thread->PtiLink);
+
+ /*
+ * inherit the thread desktop and process window station (if not yet inherited) from the process startup
+ * info structure. See documentation of CreateProcess()
+ */
+ DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
+ Status = IntParseDesktopPath(Process,
+ DesktopPath,
+ &hWinSta,
+ &hDesk);
+ if(NT_SUCCESS(Status))
+ {
+ if(hWinSta != NULL)
+ {
+ if(Process != CsrProcess)
+ {
+ HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
+ if(hProcessWinSta != NULL)
+ {
+ /* our process is already assigned to a different window station, we don't need the handle anymore */
+ NtClose(hWinSta);
+ }
+ }
+ else
+ {
+ NtClose(hWinSta);
+ }
+ }
+
+ if (hDesk != NULL)
+ {
+ PDESKTOP DesktopObject;
+ Win32Thread->rpdesk = NULL;
+ Status = ObReferenceObjectByHandle(hDesk,
+ 0,
+ ExDesktopObjectType,
+ KernelMode,
+ (PVOID*)&DesktopObject,
+ NULL);
+ NtClose(hDesk);
+ if(NT_SUCCESS(Status))
+ {
+ if (!IntSetThreadDesktop(DesktopObject,
+ FALSE))
+ {
+ DPRINT1("Unable to set thread desktop\n");
+ }
+ }
+ else
+ {
+ DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
+ }
+ }
+ }
+ Win32Thread->TIF_flags &= ~TIF_INCLEANUP;
+ co_IntDestroyCaret(Win32Thread);
+ Win32Thread->ppi = PsGetCurrentProcessWin32Process();
+ pTeb = NtCurrentTeb();
+ if (pTeb)
+ {
+ Win32Thread->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
+ Win32Thread->pClientInfo->pClientThreadInfo = NULL;
+ }
+ Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
+ Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
+ Win32Thread->pEThread = Thread;
+ }
+ else
+ {
+ PSINGLE_LIST_ENTRY e;
+
+ DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
+
+ Win32Thread->TIF_flags |= TIF_INCLEANUP;
+ DceFreeThreadDCE(Win32Thread);
+ HOOK_DestroyThreadHooks(Thread);
++ /* Cleanup timers */
++ DestroyTimersForThread(Win32Thread);
+ UnregisterThreadHotKeys(Thread);
+ /* what if this co_ func crash in umode? what will clean us up then? */
+ co_DestroyThreadWindows(Thread);
+ IntBlockInput(Win32Thread, FALSE);
+ MsqDestroyMessageQueue(Win32Thread->MessageQueue);
+ IntCleanupThreadCallbacks(Win32Thread);
+
+ /* cleanup user object references stack */
+ e = PopEntryList(&Win32Thread->ReferencesList);
+ while (e)
+ {
+ PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry);
+ DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj);
+ UserDereferenceObject(ref->obj);
+
+ e = PopEntryList(&Win32Thread->ReferencesList);
+ }
+
+ IntSetThreadDesktop(NULL,
+ TRUE);
+
+ PsSetThreadWin32Thread(Thread, NULL);
+ }
+
+ RETURN( STATUS_SUCCESS);
+
+CLEANUP:
+ UserLeave();
+ DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_);
+ END_CLEANUP;
+}
+
+/* Only used in ntuser/input.c KeyboardThreadMain(). If it's
+ not called there anymore, please delete */
+NTSTATUS
+Win32kInitWin32Thread(PETHREAD Thread)
+{
+ PEPROCESS Process;
+
+ Process = Thread->ThreadsProcess;
+
+ if (Process->Win32Process == NULL)
+ {
+ /* FIXME - lock the process */
+ Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(PROCESSINFO));
+
+ if (Process->Win32Process == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(Process->Win32Process, sizeof(PROCESSINFO));
+ /* FIXME - unlock the process */
+
+ Win32kProcessCallback(Process, TRUE);
+ }
+
+ if (Thread->Tcb.Win32Thread == NULL)
+ {
+ Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(THREADINFO));
+ if (Thread->Tcb.Win32Thread == NULL)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(THREADINFO));
+
+ Win32kThreadCallback(Thread, PsW32ThreadCalloutInitialize);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
+
+/*
+ * This definition doesn't work
+ */
+NTSTATUS APIENTRY
+DriverEntry (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+{
+ NTSTATUS Status;
+ BOOLEAN Result;
+ WIN32_CALLOUTS_FPNS CalloutData = {0};
+ PVOID GlobalUserHeapBase = NULL;
+
+ /*
+ * Register user mode call interface
+ * (system service table index = 1)
+ */
+ Result = KeAddSystemServiceTable (Win32kSSDT,
+ NULL,
+ Win32kNumberOfSysCalls,
+ Win32kSSPT,
+ 1);
+ if (Result == FALSE)
+ {
+ DPRINT1("Adding system services failed!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ hModuleWin = MmPageEntireDriver(DriverEntry);
+ DPRINT("Win32k hInstance 0x%x!\n",hModuleWin);
+ /*
+ * Register Object Manager Callbacks
+ */
+ CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
+ CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
+ CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
+ CalloutData.ProcessCallout = Win32kProcessCallback;
+ CalloutData.ThreadCallout = Win32kThreadCallback;
+ CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
+
+ /*
+ * Register our per-process and per-thread structures.
+ */
+ PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
+
+ GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
+ &GlobalUserHeapBase,
+ 1 * 1024 * 1024); /* FIXME - 1 MB for now... */
+ if (GlobalUserHeap == NULL)
+ {
+ DPRINT1("Failed to initialize the global heap!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!gpsi)
+ {
+ gpsi = UserHeapAlloc(sizeof(SERVERINFO));
+ if (gpsi)
+ {
+ RtlZeroMemory(gpsi, sizeof(SERVERINFO));
+ DPRINT("Global Server Data -> %x\n", gpsi);
+ }
+ else
+ {
+ ASSERT(FALSE);
+ }
+ }
+
+ if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore();
+
+ GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection);
+ if (GdiHandleTable == NULL)
+ {
+ DPRINT1("Failed to initialize the GDI handle table.\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Create stock objects, ie. precreated objects commonly
+ used by win32 applications */
+ CreateStockObjects();
+ CreateSysColorObjects();
+
+ InitXlateImpl();
+ InitPDEVImpl();
+ InitLDEVImpl();
+ InitDeviceImpl();
+
+ Status = InitDcImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize Device context implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitUserImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize user implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitHotkeyImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize hotkey implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitWindowStationImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize window station implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitDesktopImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize desktop implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitWindowImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize window implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitMenuImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize menu implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = InitInputImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize input implementation.\n");
+ return(Status);
+ }
+
+ Status = InitKeyboardImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize keyboard implementation.\n");
+ return(Status);
+ }
+
+ Status = InitMonitorImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Failed to initialize monitor implementation!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = MsqInitializeImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize message queue implementation.\n");
+ return(Status);
+ }
+
+ Status = InitTimerImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize timer implementation.\n");
+ return(Status);
+ }
+
+ Status = InitAcceleratorImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize accelerator implementation.\n");
+ return(Status);
+ }
+
+ Status = InitGuiCheckImpl();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize GUI check implementation.\n");
+ return(Status);
+ }
+
+ /* Initialize FreeType library */
+ if (! InitFontSupport())
+ {
+ DPRINT1("Unable to initialize font support\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ gusLanguageID = IntGdiGetLanguageID();
+
+ return STATUS_SUCCESS;
+}
+
+/* EOF */
--- /dev/null
- if (ThreadQueue->WakeMask & QS_TIMER)
- if (PostTimerMessages(Window)) // If there are timers ready,
- goto CheckMessages; // go back and process them.
-
- // LOL! Polling Timer Queue? How much time is spent doing this?
- /* Check for WM_(SYS)TIMER messages */
- Present = MsqGetTimerMessage( ThreadQueue,
- Window,
- MsgFilterMin,
- MsgFilterMax,
- &Msg->Msg,
- RemoveMessages);
- if (Present)
- {
- Msg->FreeLParam = FALSE;
- goto MessageFound;
- }
+/*
+ * 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;
+ PUNICODE_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 = (PUNICODE_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 */