--- /dev/null
- dll\directx\bdaplgin\bdaplgin.ax 1
+; Main ReactOS package
+
+.Set DiskLabelTemplate="ReactOS" ; Label of disk
+.Set CabinetNameTemplate="reactos.cab" ; reactos.cab
+.Set InfFileName="reactos.inf" ; reactos.inf
+
+
+;.Set Cabinet=on
+;.Set Compress=on
+
+.InfBegin
+[Version]
+Signature = "$ReactOS$"
+
+[Directories]
+1 = system32
+2 = system32\drivers
+3 = Fonts
+4 =
+5 = system32\drivers\etc
+6 = inf
+7 = bin
+8 = media
+
+.InfEnd
+
+; Contents of disk
+.InfBegin
+[SourceFiles]
+.InfEnd
+
+
+; Base files
+base\applications\cacls\cacls.exe 1
+base\applications\calc\calc.exe 1
+base\applications\charmap\charmap.exe 1
+base\applications\cmdutils\dbgprint\dbgprint.exe 1
+base\applications\cmdutils\doskey\doskey.exe 1
+base\applications\cmdutils\find\find.exe 1
+base\applications\cmdutils\hostname\hostname.exe 1
+base\applications\cmdutils\lodctr\lodctr.exe 1
+base\applications\cmdutils\more\more.exe 1
+base\applications\cmdutils\reg\reg.exe 1
+base\applications\cmdutils\xcopy\xcopy.exe 1
+base\applications\control\control.exe 1
+base\applications\dxdiag\dxdiag.exe 1
+base\applications\fontview\fontview.exe 1
+base\applications\mscutils\devmgmt\devmgmt.exe 1
+base\applications\mscutils\eventvwr\eventvwr.exe 1
+base\applications\games\solitaire\sol.exe 1
+base\applications\games\spider\spider.exe 1
+base\applications\games\winemine\winemine.exe 1
+base\applications\hh\hh.exe 4
+base\applications\kbswitch\kbswitch.exe 1
+base\applications\kbswitch\kbsdll\kbsdll.dll 1
+base\applications\logoff\logoff.exe 1
+base\applications\magnify\magnify.exe 1
+base\applications\mplay32\mplay32.exe 1
+base\applications\msconfig\msconfig.exe 1
+base\applications\mstsc\mstsc.exe 1
+base\applications\network\arp\arp.exe 1
+base\applications\network\dwnl\dwnl.exe 1
+base\applications\network\route\route.exe 1
+base\applications\network\finger\finger.exe 1
+base\applications\network\ftp\ftp.exe 1
+base\applications\network\ipconfig\ipconfig.exe 1
+base\applications\network\netstat\netstat.exe 1
+base\applications\network\nslookup\nslookup.exe 1
+base\applications\network\ping\ping.exe 1
+base\applications\network\telnet\telnet.exe 1
+base\applications\network\tracert\tracert.exe 1
+base\applications\network\whois\whois.exe 1
+base\applications\notepad\notepad.exe 1
+base\applications\paint\paint.exe 1
+base\applications\rapps\rapps.exe 1
+base\applications\regedit\regedit.exe 4
+base\applications\regedit\clb\clb.dll 1
+base\applications\regedt32\regedt32.exe 1
+base\applications\sc\sc.exe 1
+base\applications\screensavers\3dtext\3dtext.scr 1
+base\applications\screensavers\logon\logon.scr 1
+base\applications\mscutils\servman\servman.exe 1
+base\applications\shutdown\shutdown.exe 1
+base\applications\sndrec32\sndrec32.exe 1
+base\applications\sndvol32\sndvol32.exe 1
+base\applications\taskmgr\taskmgr.exe 1
+base\applications\winhlp32\winhlp32.exe 4
+base\applications\winver\winver.exe 1
+base\applications\wordpad\wordpad.exe 1
+base\applications\write\write.exe 1
+
+base\services\audiosrv\audiosrv.exe 1
+base\services\eventlog\eventlog.exe 1
+base\services\rpcss\rpcss.exe 1
+base\services\spoolsv\spoolsv.exe 1
+base\services\tcpsvcs\tcpsvcs.exe 1
+base\services\telnetd\telnetd.exe 1
+base\services\tcpsvcs\quotes 5
+base\services\umpnpmgr\umpnpmgr.exe 1
+base\services\wlansvc\wlansvc.exe 1
+base\services\svchost\svchost.exe 1
+
+base\setup\setup\setup.exe 1
+base\setup\vmwinst\vmwinst.exe 1
+
+base\shell\cmd\cmd.exe 1
+base\shell\explorer\explorer.exe 4
+base\shell\explorer\explorer-cfg-template.xml 4
+base\shell\explorer\notifyhook\notifyhook.dll 1
+base\shell\explorer-new\explorer_new.exe 4 optional
+
+base\system\autochk\autochk.exe 1
+base\system\bootok\bootok.exe 1
+base\system\format\format.exe 1
+base\system\lsass\lsass.exe 1
+base\system\msiexec\msiexec.exe 1
+base\system\regsvr32\regsvr32.exe 1
+base\system\rundll32\rundll32.exe 1
+base\system\runonce\runonce.exe 1
+base\system\services\services.exe 1
+base\system\userinit\userinit.exe 1
+base\system\winlogon\winlogon.exe 1
+base\system\expand\expand.exe 1
+base\system\smss\smss.exe 1
+
+
+; Dynamic Link Libraries
+dll\3rdparty\mesa32\mesa32.dll 1
+dll\3rdparty\libjpeg\libjpeg.dll 1
+dll\3rdparty\libxslt\libxslt.dll 1
+dll\3rdparty\dxtn\dxtn.dll 1 optional
+
+dll\cpl\access\access.cpl 1
+dll\cpl\appwiz\appwiz.cpl 1
+dll\cpl\console\console.dll 1
+dll\cpl\desk\desk.cpl 1
+dll\cpl\hdwwiz\hdwwiz.cpl 1
+dll\cpl\input\input.dll 1
+dll\cpl\intl\intl.cpl 1
+dll\cpl\joy\joy.cpl 1
+;dll\cpl\liccpa\liccpa.cpl 1
+dll\cpl\main\main.cpl 1
+dll\cpl\mmsys\mmsys.cpl 1
+dll\cpl\ncpa\ncpa.cpl 1
+;dll\cpl\odbccp32\odbccp32.cpl 1
+dll\cpl\powercfg\powercfg.cpl 1
+dll\cpl\sysdm\sysdm.cpl 1
+;dll\cpl\telephon\telephon.cpl 1
+dll\cpl\timedate\timedate.cpl 1
+;dll\cpl\usrmgr\usrmgr.cpl 1
+
+dll\directx\amstream\amstream.dll 1
- dll\directx\msdvbnp\msdvbnp.ax 1
- dll\directx\msvidctl\msvidctl.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
- drivers\multimedia\bdasup\bdasup.sys 2
++;dll\directx\msdvbnp\msdvbnp.ax 1
++;dll\directx\msvidctl\msvidctl.dll 1
+dll\directx\quartz\quartz.dll 1
+dll\directx\qedit\qedit.dll 1
+dll\directx\wine\d3d8\d3d8.dll 1
+dll\directx\wine\wined3d\wined3d.dll 1
+dll\directx\wine\d3d9\d3d9.dll 1
+
+dll\keyboard\kbda1\kbda1.dll 1
+dll\keyboard\kbda2\kbda2.dll 1
+dll\keyboard\kbda3\kbda3.dll 1
+dll\keyboard\kbdal\kbdal.dll 1
+dll\keyboard\kbdarme\kbdarme.dll 1
+dll\keyboard\kbdarmw\kbdarmw.dll 1
+dll\keyboard\kbdaze\kbdaze.dll 1
+dll\keyboard\kbdazel\kbdazel.dll 1
+dll\keyboard\kbdbgm\kbdbgm.dll 1
+dll\keyboard\kbdbgt\kbdbgt.dll 1
+dll\keyboard\kbdblr\kbdblr.dll 1
+dll\keyboard\kbdbr\kbdbr.dll 1
+dll\keyboard\kbdbga\kbdbga.dll 1
+dll\keyboard\kbdbe\kbdbe.dll 1
+dll\keyboard\kbdbur\kbdbur.dll 1
+dll\keyboard\kbdcan\kbdcan.dll 1
+dll\keyboard\kbdcr\kbdcr.dll 1
+dll\keyboard\kbdcz\kbdcz.dll 1
+dll\keyboard\kbdcz1\kbdcz1.dll 1
+dll\keyboard\kbdda\kbdda.dll 1
+dll\keyboard\kbddv\kbddv.dll 1
+dll\keyboard\kbdes\kbdes.dll 1
+dll\keyboard\kbdest\kbdest.dll 1
+dll\keyboard\kbdfc\kbdfc.dll 1
+dll\keyboard\kbdfi\kbdfi.dll 1
+dll\keyboard\kbdfr\kbdfr.dll 1
+dll\keyboard\kbdgeo\kbdgeo.dll 1
+dll\keyboard\kbdgerg\kbdgerg.dll 1
+dll\keyboard\kbdgneo\kbdgneo.dll 1
+dll\keyboard\kbdgrist\kbdgrist.dll 1
+dll\keyboard\kbdgr\kbdgr.dll 1
+dll\keyboard\kbdhe\kbdhe.dll 1
+dll\keyboard\kbdheb\kbdheb.dll 1
+dll\keyboard\kbdhu\kbdhu.dll 1
+dll\keyboard\kbdic\kbdic.dll 1
+dll\keyboard\kbdinasa\kbdinasa.dll 1
+dll\keyboard\kbdinben\kbdinben.dll 1
+dll\keyboard\kbdindev\kbdindev.dll 1
+dll\keyboard\kbdinguj\kbdinguj.dll 1
+dll\keyboard\kbdinmal\kbdinmal.dll 1
+dll\keyboard\kbdir\kbdir.dll 1
+dll\keyboard\kbdit\kbdit.dll 1
+dll\keyboard\kbdja\kbdja.dll 1
+dll\keyboard\kbdkaz\kbdkaz.dll 1
+dll\keyboard\kbdla\kbdla.dll 1
+dll\keyboard\kbdlt1\kbdlt1.dll 1
+dll\keyboard\kbdlv\kbdlv.dll 1
+dll\keyboard\kbdmac\kbdmac.dll 1
+dll\keyboard\kbdne\kbdne.dll 1
+dll\keyboard\kbdno\kbdno.dll 1
+dll\keyboard\kbdpl1\kbdpl1.dll 1
+dll\keyboard\kbdpo\kbdpo.dll 1
+dll\keyboard\kbdro\kbdro.dll 1
+dll\keyboard\kbdru\kbdru.dll 1
+dll\keyboard\kbdru1\kbdru1.dll 1
+dll\keyboard\kbdsg\kbdsg.dll 1
+dll\keyboard\kbdsk\kbdsk.dll 1
+dll\keyboard\kbdsk1\kbdsk1.dll 1
+dll\keyboard\kbdsw\kbdsw.dll 1
+dll\keyboard\kbdtat\kbdtat.dll 1
+dll\keyboard\kbdth0\kbdth0.dll 1
+dll\keyboard\kbdth1\kbdth1.dll 1
+dll\keyboard\kbdth2\kbdth2.dll 1
+dll\keyboard\kbdth3\kbdth3.dll 1
+dll\keyboard\kbdtuf\kbdtuf.dll 1
+dll\keyboard\kbdtuq\kbdtuq.dll 1
+dll\keyboard\kbduk\kbduk.dll 1
+dll\keyboard\kbdur\kbdur.dll 1
+dll\keyboard\kbdurs\kbdurs.dll 1
+dll\keyboard\kbdus\kbdus.dll 1
+dll\keyboard\kbdusa\kbdusa.dll 1
+dll\keyboard\kbdusl\kbdusl.dll 1
+dll\keyboard\kbdusr\kbdusr.dll 1
+dll\keyboard\kbdusx\kbdusx.dll 1
+dll\keyboard\kbduzb\kbduzb.dll 1
+dll\keyboard\kbdvntc\kbdvntc.dll 1
+dll\keyboard\kbdycc\kbdycc.dll 1
+dll\keyboard\kbdycl\kbdycl.dll 1
+dll\keyboard\kbdko\kbdko.dll 1
+
+dll\ntdll\ntdll.dll 1
+
+dll\win32\acledit\acledit.dll 1
+dll\win32\aclui\aclui.dll 1
+dll\win32\activeds\activeds.dll 1
+dll\win32\advapi32\advapi32.dll 1
+dll\win32\advpack\advpack.dll 1
+dll\win32\actxprxy\actxprxy.dll 1
+dll\win32\atl\atl.dll 1
+dll\win32\authz\authz.dll 1
+dll\win32\avicap32\avicap32.dll 1
+dll\win32\avifil32\avifil32.dll 1
+dll\win32\batt\batt.dll 1
+dll\win32\bcrypt\bcrypt.dll 1
+dll\win32\beepmidi\beepmidi.dll 1
+dll\win32\browseui\browseui.dll 1
+dll\win32\cabinet\cabinet.dll 1
+dll\win32\cards\cards.dll 1
+dll\win32\cfgmgr32\cfgmgr32.dll 1
+dll\win32\clusapi\clusapi.dll 1
+dll\win32\comcat\comcat.dll 1
+dll\win32\comctl32\comctl32.dll 1
+dll\win32\comdlg32\comdlg32.dll 1
+dll\win32\compstui\compstui.dll 1
+dll\win32\credui\credui.dll 1
+dll\win32\crtdll\crtdll.dll 1
+dll\win32\crypt32\crypt32.dll 1
+dll\win32\cryptdlg\cryptdlg.dll 1
+dll\win32\cryptdll\cryptdll.dll 1
+dll\win32\cryptnet\cryptnet.dll 1
+dll\win32\cryptui\cryptui.dll 1
+dll\win32\dbghelp\dbghelp.dll 1
+dll\win32\dciman32\dciman32.dll 1
+dll\win32\dwmapi\dwmapi.dll 1
+dll\win32\devmgr\devmgr.dll 1
+dll\win32\dhcpcsvc\dhcpcsvc.dll 1
+dll\win32\dnsapi\dnsapi.dll 1
+dll\win32\faultrep\faultrep.dll 1
+dll\win32\fmifs\fmifs.dll 1
+dll\win32\fusion\fusion.dll 1
+dll\win32\gdi32\gdi32.dll 1
+dll\win32\gdiplus\gdiplus.dll 1
+dll\win32\getuname\getuname.dll 1
+dll\win32\glu32\glu32.dll 1
+dll\win32\hhctrl.ocx\hhctrl.ocx 1
+dll\win32\hid\hid.dll 1
+dll\win32\hlink\hlink.dll 1
+dll\win32\hnetcfg\hnetcfg.dll 1
+dll\win32\httpapi\httpapi.dll 1
+dll\win32\iccvid\iccvid.dll 1
+dll\win32\icmp\icmp.dll 1
+dll\win32\imaadp32.acm\imaadp32.acm 1
+dll\win32\imagehlp\imagehlp.dll 1
+dll\win32\imm32\imm32.dll 1
+dll\win32\inetcomm\inetcomm.dll 1
+dll\win32\inetmib1\inetmib1.dll 1
+dll\win32\initpki\initpki.dll 1
+dll\win32\inseng\inseng.dll 1
+dll\win32\iphlpapi\iphlpapi.dll 1
+dll\win32\itircl\itircl.dll 1
+dll\win32\itss\itss.dll 1
+dll\win32\jscript\jscript.dll 1
+dll\win32\kernel32\kernel32.dll 1
+dll\win32\loadperf\loadperf.dll 1
+dll\win32\localspl\localspl.dll 1
+dll\win32\localui\localui.dll 1
+dll\win32\lsasrv\lsasrv.dll 1
+dll\win32\lz32\lz32.dll 1
+dll\win32\mapi32\mapi32.dll 1
+dll\win32\mciavi32\mciavi32.dll 1
+dll\win32\mcicda\mcicda.dll 1
+dll\win32\mciqtz32\mciqtz32.dll 1
+dll\win32\mciseq\mciseq.dll 1
+dll\win32\mciwave\mciwave.dll 1
+dll\win32\mlang\mlang.dll 1
+dll\win32\mmdrv\mmdrv.dll 1
+dll\win32\modemui\modemui.dll 1
+dll\win32\mpr\mpr.dll 1
+dll\win32\mprapi\mprapi.dll 1
+dll\win32\msacm32\msacm32.dll 1
+dll\win32\msacm32\msacm32.drv\msacm32.drv 1
+dll\win32\msadp32.acm\msadp32.acm 1
+dll\win32\msafd\msafd.dll 1
+dll\win32\mscat32\mscat32.dll 1
+dll\win32\mscms\mscms.dll 1
+dll\win32\mscoree\mscoree.dll 1
+dll\win32\msctf\msctf.dll 1
+dll\win32\msftedit\msftedit.dll 1
+dll\win32\msg711.acm\msg711.acm 1
+dll\win32\msgina\msgina.dll 1
+dll\win32\msgsm32.acm\msgsm32.acm 1
+dll\win32\mshtml\mshtml.dll 1
+dll\win32\mshtml.tlb\mshtml.tlb 1
+dll\win32\msi\msi.dll 1
+dll\win32\msimg32\msimg32.dll 1
+dll\win32\msimtf\msimtf.dll 1
+dll\win32\msisip\msisip.dll 1
+dll\win32\msisys.ocx\msisys.ocx 1
+dll\win32\msnet32\msnet32.dll 1
+dll\win32\msrle32\msrle32.dll 1
+dll\win32\mssign32\mssign32.dll 1
+dll\win32\mssip32\mssip32.dll 1
+dll\win32\mstask\mstask.dll 1
+dll\win32\msvcrt\msvcrt.dll 1
+dll\win32\msvcrt20\msvcrt20.dll 1
+dll\win32\msvcrt40\msvcrt40.dll 1
+dll\win32\msvfw32\msvfw32.dll 1
+dll\win32\msvidc32\msvidc32.dll 1
+dll\win32\mswsock\mswsock.dll 1
+dll\win32\msxml3\msxml3.dll 1
+dll\win32\nddeapi\nddeapi.dll 1
+dll\win32\netapi32\netapi32.dll 1
+dll\win32\netcfgx\netcfgx.dll 1
+dll\win32\netid\netid.dll 1
+dll\win32\netshell\netshell.dll 1
+dll\win32\newdev\newdev.dll 1
+dll\win32\ntdsapi\ntdsapi.dll 1
+dll\win32\ntlanman\ntlanman.dll 1
+dll\win32\ntmarta\ntmarta.dll 1
+dll\win32\ntprint\ntprint.dll 1
+dll\win32\objsel\objsel.dll 1
+dll\win32\odbc32\odbc32.dll 1
+dll\win32\odbccp32\odbccp32.dll 1
+dll\win32\ole32\ole32.dll 1
+dll\win32\oleacc\oleacc.dll 1
+dll\win32\oleaut32\oleaut32.dll 1
+dll\win32\olecli32\olecli32.dll 1
+dll\win32\oledlg\oledlg.dll 1
+dll\win32\olepro32\olepro32.dll 1
+dll\win32\olesvr32\olesvr32.dll 1
+dll\win32\olethk32\olethk32.dll 1
+dll\win32\opengl32\opengl32.dll 1
+dll\win32\pdh\pdh.dll 1
+dll\win32\pidgen\pidgen.dll 1
+dll\win32\powrprof\powrprof.dll 1
+dll\win32\printui\printui.dll 1
+dll\win32\psapi\psapi.dll 1
+dll\win32\pstorec\pstorec.dll 1
+dll\win32\qmgr\qmgr.dll 1
+dll\win32\qmgrprxy\qmgrprxy.dll 1
+dll\win32\query\query.dll 1
+dll\win32\rasadhlp\rasadhlp.dll 1
+dll\win32\rasapi32\rasapi32.dll 1
+dll\win32\rasdlg\rasdlg.dll 1
+dll\win32\resutils\resutils.dll 1
+dll\win32\rasman\rasman.dll 1
+dll\win32\riched20\riched20.dll 1
+dll\win32\riched32\riched32.dll 1
+dll\win32\rpcrt4\rpcrt4.dll 1
+dll\win32\rsabase\rsabase.dll 1
+dll\win32\rsaenh\rsaenh.dll 1
+dll\win32\samlib\samlib.dll 1
+dll\win32\samsrv\samsrv.dll 1
+dll\win32\sccbase\sccbase.dll 1
+dll\win32\schannel\schannel.dll 1
+dll\win32\secur32\secur32.dll 1
+dll\win32\security\security.dll 1
+dll\win32\sensapi\sensapi.dll 1
+dll\win32\serialui\serialui.dll 1
+dll\win32\setupapi\setupapi.dll 1
+dll\win32\sfc\sfc.dll 1
+dll\win32\sfc_os\sfc_os.dll 1
+dll\win32\shdoclc\shdoclc.dll 1
+dll\win32\shdocvw\shdocvw.dll 1
+dll\win32\shell32\shell32.dll 1
+dll\win32\shfolder\shfolder.dll 1
+dll\win32\shimgvw\shimgvw.dll 1
+dll\win32\shlwapi\shlwapi.dll 1
+dll\win32\slbcsp\slbcsp.dll 1
+dll\win32\smdll\smdll.dll 1
+dll\win32\snmpapi\snmpapi.dll 1
+dll\win32\softpub\softpub.dll 1
+dll\win32\spoolss\spoolss.dll 1
+dll\win32\srclient\srclient.dll 1
+dll\win32\stdole2.tlb\stdole2.tlb 1
+dll\win32\stdole32.tlb\stdole32.tlb 1
+dll\win32\sti\sti.dll 1
+dll\win32\sxs\sxs.dll 1
+dll\win32\syssetup\syssetup.dll 1
+dll\win32\t2embed\t2embed.dll 1
+dll\win32\tapi32\tapi32.dll 1
+dll\win32\tapiui\tapiui.dll 1
+dll\win32\traffic\traffic.dll 1
+dll\win32\twain_32\twain_32.dll 1
+dll\win32\uext2\uext2.dll 1
+dll\win32\ufat\ufat.dll 1
+dll\win32\ufatx\ufatx.dll 1 optional
+dll\win32\untfs\untfs.dll 1
+dll\win32\updspapi\updspapi.dll 1
+dll\win32\url\url.dll 1
+dll\win32\urlmon\urlmon.dll 1
+dll\win32\user32\user32.dll 1
+dll\win32\userenv\userenv.dll 1
+dll\win32\usp10\usp10.dll 1
+dll\win32\uxtheme\uxtheme.dll 1
+dll\win32\vdmdbg\vdmdbg.dll 1
+dll\win32\version\version.dll 1
+dll\win32\windowscodecs\windowscodecs.dll 1
+dll\win32\winemp3.acm\winemp3.acm 1
+dll\win32\winfax\winfax.dll 1
+dll\win32\winhttp\winhttp.dll 1
+dll\win32\wininet\wininet.dll 1
+dll\win32\winmm\winmm.dll 1
+dll\win32\winspool\winspool.drv 1
+dll\win32\winsta\winsta.dll 1
+dll\win32\wlanapi\wlanapi.dll 1
+dll\win32\wintrust\wintrust.dll 1
+dll\win32\wldap32\wldap32.dll 1
+dll\win32\wmi\wmi.dll 1
+dll\win32\ws2_32\ws2_32.dll 1
+dll\win32\ws2help\ws2help.dll 1
+dll\win32\wshirda\wshirda.dll 1
+dll\win32\wshtcpip\wshtcpip.dll 1
+dll\win32\wsock32\wsock32.dll 1
+dll\win32\wtsapi32\wtsapi32.dll 1
+dll\win32\wuapi\wuapi.dll 1
+dll\win32\xinput1_1\xinput1_1.dll 1
+dll\win32\xinput1_2\xinput1_2.dll 1
+dll\win32\xinput1_3\xinput1_3.dll 1
+dll\win32\xinput9_1_0\xinput9_1_0.dll 1
+dll\win32\xmllite\xmllite.dll 1
+dll\win32\winmm\midimap\midimap.dll 1
+dll\win32\wdmaud.drv\wdmaud.drv 1
+
+; Shell Extensions
+dll\shellext\deskadp\deskadp.dll 1
+dll\shellext\deskmon\deskmon.dll 1
+
+; Drivers
+drivers\base\bootvid\bootvid.dll 1
+drivers\base\beep\beep.sys 2
+drivers\base\null\null.sys 2
+drivers\base\nmidebug\nmidebug.sys 2
+
+drivers\battery\battc\battc.sys 2
+
+drivers\bus\acpi\cmbatt\cmbatt.sys 2
+drivers\bus\acpi\compbatt\compbatt.sys 2
+
+drivers\directx\dxapi\dxapi.sys 2
+drivers\directx\dxg\dxg.sys 2
+drivers\directx\dxgthk\dxgthk.sys 2
+
+drivers\filesystems\fs_rec\fs_rec.sys 2
+drivers\filesystems\msfs\msfs.sys 2
+drivers\filesystems\mup\mup.sys 2
+drivers\filesystems\npfs\npfs.sys 2
+
+drivers\input\mouclass\mouclass.sys 2
+drivers\input\sermouse\sermouse.sys 2
+
+drivers\ksfilter\ks\ks.sys 2
++;drivers\multimedia\bdasup\bdasup.sys 2
+
+drivers\network\afd\afd.sys 2
+drivers\network\ndis\ndis.sys 2
+drivers\network\tcpip\tcpip.sys 2
+drivers\network\tdi\tdi.sys 2
+drivers\network\dd\ne2000\ne2000.sys 2
+drivers\network\dd\pcnet\pcnet.sys 2
+
+drivers\serial\serenum\serenum.sys 2
+drivers\serial\serial\serial.sys 2
+
+drivers\storage\ide\pciide\pciide.sys 2
+drivers\storage\ide\pciidex\pciidex.sys 2
+
+;drivers\usb\miniport\usbohci\usbohci.sys 2
+;drivers\usb\miniport\usbuhci\usbuhci.sys 2
+;drivers\usb\usbhub\usbhub.sys 2
+;drivers\usb\usbport\usbport.sys 2
+drivers\usb\nt4compat\usbdriver\usbdriver.sys 2
+
+drivers\video\displays\vga\vgaddi.dll 1
+drivers\video\displays\framebuf\framebuf.dll 1
+drivers\video\miniport\vga\vgamp.sys 2
+drivers\video\miniport\vbe\vbemp.sys 2
+drivers\video\videoprt\videoprt.sys 2
+drivers\video\font\ftfd\ftfd.dll 1
+
+drivers\wdm\audio\filters\kmixer\kmixer.sys 2
+drivers\wdm\audio\sysaudio\sysaudio.sys 2
+drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2
+drivers\wdm\audio\backpln\portcls\portcls.sys 2
+drivers\wdm\audio\drm\drmk\drmk.sys 2
+drivers\wmi\wmilib.sys 2
+
+; Media
+media\fonts\DejaVuSans.ttf 3
+media\fonts\DejaVuSans-Bold.ttf 3
+media\fonts\DejaVuSans-BoldOblique.ttf 3
+media\fonts\DejaVuSansMono.ttf 3
+media\fonts\DejaVuSansMono-Bold.ttf 3
+media\fonts\DejaVuSansMono-BoldOblique.ttf 3
+media\fonts\DejaVuSansMono-Oblique.ttf 3
+media\fonts\DejaVuSans-Oblique.ttf 3
+media\fonts\DejaVuSerif.ttf 3
+media\fonts\DejaVuSerif-Bold.ttf 3
+media\fonts\DejaVuSerif-BoldItalic.ttf 3
+media\fonts\DejaVuSerif-Italic.ttf 3
+
+media\fonts\FreeMono.ttf 3
+media\fonts\FreeMonoBold.ttf 3
+media\fonts\FreeMonoBoldOblique.ttf 3
+media\fonts\FreeMonoOblique.ttf 3
+
+media\fonts\LiberationMono-Bold.ttf 3
+media\fonts\LiberationMono-BoldItalic.ttf 3
+media\fonts\LiberationMono-Italic.ttf 3
+media\fonts\LiberationMono-Regular.ttf 3
+media\fonts\LiberationSans-Bold.ttf 3
+media\fonts\LiberationSans-BoldItalic.ttf 3
+media\fonts\LiberationSans-Italic.ttf 3
+media\fonts\LiberationSans-Regular.ttf 3
+media\fonts\LiberationSerif-Bold.ttf 3
+media\fonts\LiberationSerif-BoldItalic.ttf 3
+media\fonts\LiberationSerif-Italic.ttf 3
+media\fonts\LiberationSerif-Regular.ttf 3
+
+media\fonts\Marlett.ttf 3
+media\fonts\symbol.ttf 3
+media\fonts\tahoma.ttf 3
+media\fonts\tahomabd.ttf 3
+
+media\vgafonts\vgafonts.cab 4
+
+media\nls\c_037.nls 1
+media\nls\c_424.nls 1
+media\nls\c_500.nls 1
+media\nls\c_737.nls 1
+media\nls\c_775.nls 1
+media\nls\c_850.nls 1
+media\nls\c_852.nls 1
+media\nls\c_855.nls 1
+media\nls\c_856.nls 1
+media\nls\c_857.nls 1
+media\nls\c_860.nls 1
+media\nls\c_861.nls 1
+media\nls\c_862.nls 1
+media\nls\c_863.nls 1
+media\nls\c_864.nls 1
+media\nls\c_865.nls 1
+media\nls\c_866.nls 1
+media\nls\c_869.nls 1
+media\nls\c_874.nls 1
+media\nls\c_875.nls 1
+media\nls\c_878.nls 1
+media\nls\c_932.nls 1
+media\nls\c_936.nls 1
+media\nls\c_949.nls 1
+media\nls\c_950.nls 1
+media\nls\c_1006.nls 1
+media\nls\c_1026.nls 1
+media\nls\c_1250.nls 1
+media\nls\c_1251.nls 1
+media\nls\c_1253.nls 1
+media\nls\c_1254.nls 1
+media\nls\c_1255.nls 1
+media\nls\c_1256.nls 1
+media\nls\c_1257.nls 1
+media\nls\c_1258.nls 1
+media\nls\c_10000.nls 1
+media\nls\c_10006.nls 1
+media\nls\c_10007.nls 1
+media\nls\c_10029.nls 1
+media\nls\c_10079.nls 1
+media\nls\c_10081.nls 1
+media\nls\c_20866.nls 1
+media\nls\c_21866.nls 1
+media\nls\c_28591.nls 1
+media\nls\c_28592.nls 1
+media\nls\c_28593.nls 1
+media\nls\c_28594.nls 1
+media\nls\c_28595.nls 1
+media\nls\c_28596.nls 1
+media\nls\c_28597.nls 1
+media\nls\c_28598.nls 1
+media\nls\c_28599.nls 1
+media\nls\c_28600.nls 1
+media\nls\c_28603.nls 1
+media\nls\c_28604.nls 1
+media\nls\c_28605.nls 1
+media\nls\c_28606.nls 1
+media\drivers\etc\hosts 5
+media\drivers\etc\services 5
+media\inf\audio.inf 6
+media\inf\acpi.inf 6
+media\inf\battery.inf 6
+media\inf\cdrom.inf 6
+media\inf\cpu.inf 6
+media\inf\display.inf 6
+media\inf\font.inf 6
+media\inf\fdc.inf 6
+media\inf\hdc.inf 6
+media\inf\intl.inf 6
+media\inf\layout.inf 6
+media\inf\machine.inf 6
+media\inf\msmouse.inf 6
+media\inf\keyboard.inf 6
+media\inf\ks.inf 6
+media\inf\NET_NIC.inf 6
+media\inf\netamd.inf 6
+media\inf\netisa.inf 6
+media\inf\netrtpnt.inf 6
+media\inf\nettcpip.inf 6
+media\inf\ports.inf 6
+media\inf\scsi.inf 6
+media\inf\syssetup.inf 6
+media\inf\usbport.inf 6
+media\inf\usb.inf 6
+media\inf\usbstor.inf 6
+media\inf\xboxdisp.inf 6
+
+
+; Media Files
+media\sounds\ReactOS_LogOn.wav 8
+
+; Ini Files
+boot\bootdata\system.ini 4
+
+; Regression Testing
+boot\bootdata\bootcdregtest\regtest.cmd 7 optional
+
+; Subsystems
+subsystems\win32\csrss\csrss.exe 1
+subsystems\win32\csrss\win32csr\win32csr.dll 1
+subsystems\win32\csrss\csrsrv\csrsrv.dll 1
+subsystems\ntvdm\ntvdm.exe 1
+subsystems\win32\win32k\win32k.sys 1
+
+; Optional/proprietary files
+modules\optional\DroidSansFallback.ttf 3 optional
+modules\optional\NOTICE_for_Droid_Font.txt 4 optional
+modules\optional\netkvm2k.inf 6 optional
+modules\optional\netkvm2k.cat 6 optional
+modules\optional\netkvm.sys 2 optional
+modules\optional\alcxwdm.inf 6 optional
+modules\optional\alcxwdm.sys 2 optional
+modules\optional\mfc42.dll 1 optional
+modules\optional\mfc42u.dll 1 optional
+modules\optional\mfc71.dll 1 optional
+modules\optional\mfc71u.dll 1 optional
+modules\optional\msvbvm50.dll 1 optional
+modules\optional\msvbvm60.dll 1 optional
+modules\optional\msvcirt.dll 1 optional
+modules\optional\msvcp71.dll 1 optional
+modules\optional\msvcr71.dll 1 optional
+modules\optional\vmx_fb.dll 1 optional
+modules\optional\vmx_mode.dll 1 optional
+modules\optional\vmx_svga.inf 6 optional
+modules\optional\vmx_svga.sys 2 optional
+modules\optional\wine_gecko-1.0.0-x86.cab 4 optional
+
+; Rosapps
+modules\rosapps\applications\screensavers\cylfrac\cylfrac.scr 1 optional
+modules\rosapps\applications\screensavers\matrix\matrix.scr 1 optional
+modules\rosapps\applications\screensavers\blankscr\scrnsave.scr 1 optional
+modules\rosapps\applications\screensavers\starfield\starfield.scr 1 optional
+modules\rosapps\applications\screensavers\mazescr\mazescr.scr 1 optional
+modules\rosapps\applications\screensavers\butterflies\butterflies.scr 1 optional
+modules\rosapps\applications\cmdutils\comp\comp.exe 1 optional
+modules\rosapps\applications\cmdutils\mode\mode.exe 1 optional
+modules\rosapps\applications\cmdutils\sort\sort.exe 1 optional
+modules\rosapps\applications\cmdutils\tee\tee.exe 1 optional
+modules\rosapps\applications\cmdutils\touch\touch.exe 1 optional
+modules\rosapps\applications\cmdutils\uptime\uptime.exe 1 optional
+modules\rosapps\applications\cmdutils\y\y.exe 1 optional
+modules\rosapps\applications\devutils\gdb2\gdb2.exe 1 optional
+modules\rosapps\applications\devutils\gdihv\gdihv.exe 1 optional
+modules\rosapps\applications\devutils\genguid\genguid.exe 1 optional
+modules\rosapps\applications\sysutils\gettype\gettype.exe 1 optional
+modules\rosapps\applications\net\ncftp\ncftp.exe 1 optional
+modules\rosapps\applications\net\netreg\netreg.exe 1 optional
+modules\rosapps\applications\net\niclist\niclist.exe 1 optional
+modules\rosapps\applications\net\roshttpd\roshttpd.exe 1 optional
+modules\rosapps\applications\notevil\notevil.exe 1 optional
+modules\rosapps\applications\sysutils\chkdsk\chkdsk.exe 1 optional
+modules\rosapps\applications\sysutils\systeminfo\systeminfo.exe 1 optional
+modules\rosapps\applications\sysutils\chklib\chklib.exe 1 optional
+modules\rosapps\applications\sysutils\ctm\ctm.exe 1 optional
+modules\rosapps\applications\sysutils\kill\kill.exe 1 optional
+modules\rosapps\applications\sysutils\lsdd\lsdd.exe 1 optional
+modules\rosapps\applications\sysutils\man\man.exe 1 optional
+modules\rosapps\applications\sysutils\pedump\pedump.exe 1 optional
+modules\rosapps\applications\sysutils\regexpl\regexpl.exe 1 optional
+modules\rosapps\applications\sysutils\tcat\tcat.exe 1 optional
+modules\rosapps\applications\sysutils\tlist\tlist.exe 1 optional
+modules\rosapps\applications\sysutils\screenshot\screenshot.exe 1 optional
+modules\rosapps\applications\sysutils\utils\binpatch\binpatch.exe 1 optional
+modules\rosapps\applications\sysutils\utils\cat\cat.exe 1 optional
+modules\rosapps\applications\sysutils\utils\driver\load\load.exe 1 optional
+modules\rosapps\applications\sysutils\utils\driver\unload\unload.exe 1 optional
+modules\rosapps\applications\sysutils\utils\infinst\infinst.exe 1 optional
+modules\rosapps\applications\sysutils\utils\nts2w32err\nts2w32err.exe 1 optional
+modules\rosapps\applications\sysutils\utils\objdir\objdir.exe 1 optional
+modules\rosapps\applications\sysutils\utils\partinfo\partinfo.exe 1 optional
+modules\rosapps\applications\sysutils\utils\ps\ps.exe 1 optional
+modules\rosapps\applications\sysutils\utils\rosperf\rosperf.exe 1 optional
+modules\rosapps\applications\sysutils\utils\stats\stats.exe 1 optional
+modules\rosapps\applications\sysutils\utils\tickcount\tickcount.exe 1 optional
+modules\rosapps\applications\winfile\winfile.exe 1 optional
+modules\rosapps\demos\maze\maze.exe 1 optional
+modules\rosapps\drivers\green\green.sys 2 optional
+
+; Rostests
+modules\rostests\rosautotest\rosautotest.exe 1 optional
+modules\rostests\drivers\kmtest\kmtest.sys 2 optional
+modules\rostests\drivers\kmtest\kmtestassist.sys 2 optional
+modules\rostests\tests\pseh2\pseh2_test.exe 7 optional
+modules\rostests\winetests\advapi32\advapi32_winetest.exe 7 optional
+modules\rostests\winetests\advpack\advpack_winetest.exe 7 optional
+modules\rostests\winetests\browseui\browseui_winetest.exe 7 optional
+modules\rostests\winetests\cabinet\cabinet_winetest.exe 7 optional
+modules\rostests\winetests\comcat\comcat_winetest.exe 7 optional
+modules\rostests\winetests\comctl32\comctl32_winetest.exe 7 optional
+modules\rostests\winetests\comdlg32\comdlg32_winetest.exe 7 optional
+modules\rostests\winetests\crypt32\crypt32_winetest.exe 7 optional
+modules\rostests\winetests\cryptnet\cryptnet_winetest.exe 7 optional
+modules\rostests\winetests\dsound\dsound_winetest.exe 7 optional
+modules\rostests\winetests\gdi32\gdi32_winetest.exe 7 optional
+modules\rostests\winetests\gdiplus\gdiplus_winetest.exe 7 optional
+modules\rostests\winetests\hlink\hlink_winetest.exe 7 optional
+modules\rostests\winetests\icmp\icmp_winetest.exe 7 optional
+modules\rostests\winetests\iphlpapi\iphlpapi_winetest.exe 7 optional
+modules\rostests\winetests\jscript\jscript_winetest.exe 7 optional
+modules\rostests\winetests\kernel32\kernel32_winetest.exe 7 optional
+modules\rostests\winetests\lz32\lz32_winetest.exe 7 optional
+modules\rostests\winetests\mapi32\mapi32_winetest.exe 7 optional
+modules\rostests\winetests\mlang\mlang_winetest.exe 7 optional
+modules\rostests\winetests\mshtml\mshtml_winetest.exe 7 optional
+modules\rostests\winetests\msi\msi_winetest.exe 7 optional
+modules\rostests\winetests\mstask\mstask_winetest.exe 7 optional
+modules\rostests\winetests\msvcrt\msvcrt_winetest.exe 7 optional
+modules\rostests\winetests\msxml3\msxml3_winetest.exe 7 optional
+modules\rostests\winetests\netapi32\netapi32_winetest.exe 7 optional
+modules\rostests\winetests\ntdll\ntdll_winetest.exe 7 optional
+modules\rostests\winetests\odbccp32\odbccp32_winetest.exe 7 optional
+modules\rostests\winetests\ole32\ole32_winetest.exe 7 optional
+modules\rostests\winetests\oleaut32\oleaut32_winetest.exe 7 optional
+modules\rostests\winetests\powrprof\powrprof_winetest.exe 7 optional
+modules\rostests\winetests\psapi\psapi_winetest.exe 7 optional
+modules\rostests\winetests\riched20\riched20_winetest.exe 7 optional
+modules\rostests\winetests\rpcrt4\rpcrt4_winetest.exe 7 optional
+modules\rostests\winetests\rsabase\rsabase_winetest.exe 7 optional
+modules\rostests\winetests\rsaenh\rsaenh_winetest.exe 7 optional
+modules\rostests\winetests\schannel\schannel_winetest.exe 7 optional
+modules\rostests\winetests\secur32\secur32_winetest.exe 7 optional
+modules\rostests\winetests\setupapi\setupapi_winetest.exe 7 optional
+modules\rostests\winetests\shdocvw\shdocvw_winetest.exe 7 optional
+modules\rostests\winetests\shell32\shell32_winetest.exe 7 optional
+modules\rostests\winetests\shlwapi\shlwapi_winetest.exe 7 optional
+modules\rostests\winetests\urlmon\urlmon_winetest.exe 7 optional
+modules\rostests\winetests\user32\user32_winetest.exe 7 optional
+modules\rostests\winetests\usp10\usp10_winetest.exe 7 optional
+modules\rostests\winetests\uxtheme\uxtheme_winetest.exe 7 optional
+modules\rostests\winetests\version\version_winetest.exe 7 optional
+modules\rostests\winetests\winhttp\winhttp_winetest.exe 7 optional
+modules\rostests\winetests\wininet\wininet_winetest.exe 7 optional
+modules\rostests\winetests\winmm\winmm_winetest.exe 7 optional
+modules\rostests\winetests\wintrust\wintrust_winetest.exe 7 optional
+modules\rostests\winetests\wlanapi\wlanapi_winetest.exe 7 optional
+modules\rostests\winetests\ws2_32\ws2_32_winetest.exe 7 optional
+modules\rostests\winetests\xmllite\xmllite_winetest.exe 7 optional
+
+
+modules\wallpaper\Angelus_02_ROSWP.bmp 4 optional
--- /dev/null
- pbo->pvRbrush = EngAllocMem(0, cj, 'rbdG');
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: GDI Driver Brush Functions
+ * FILE: subsystem/win32/win32k/eng/engbrush.c
+ * PROGRAMER: Jason Filby
+ * Timo Kreuzer
+ */
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/** Internal functions ********************************************************/
+
+VOID
+NTAPI
+EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
+{
+ ASSERT(pebo);
+ ASSERT(pbrush);
+ ASSERT(pdc);
+
+ pebo->BrushObject.flColorType = 0;
+ pebo->BrushObject.pvRbrush = NULL;
+ pebo->pbrush = pbrush;
+ pebo->pengbrush = NULL;
+ pebo->flattrs = pbrush->flAttrs;
+
+ /* Initialize 1 bpp fore and back colors */
+ pebo->crCurrentBack = pdc->pdcattr->crBackgroundClr;
+ pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
+
+ pebo->psurfTrg = pdc->dclevel.pSurface;
+ ASSERT(pebo->psurfTrg);
+ ASSERT(pebo->psurfTrg->ppal);
+
+ pebo->ppalSurf = pebo->psurfTrg->ppal;
+ GDIOBJ_IncrementShareCount(&pebo->ppalSurf->BaseObject);
+
+ if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
+ {
+ /* NULL brushes don't need a color */
+ pebo->BrushObject.iSolidColor = 0;
+ }
+ else if (pbrush->flAttrs & GDIBRUSH_IS_SOLID)
+ {
+ /* Set the RGB color */
+ EBRUSHOBJ_vSetSolidBrushColor(pebo, pbrush->BrushAttr.lbColor);
+ }
+ else
+ {
+ /* This is a pattern brush that needs realization */
+ pebo->BrushObject.iSolidColor = 0xFFFFFFFF;
+
+ /* Use foreground color of hatch brushes */
+ if (pbrush->flAttrs & GDIBRUSH_IS_HATCH)
+ pebo->crCurrentText = pbrush->BrushAttr.lbColor;
+ }
+}
+
+VOID
+FASTCALL
+EBRUSHOBJ_vSetSolidBrushColor(EBRUSHOBJ *pebo, COLORREF crColor)
+{
+ ULONG iSolidColor;
+ EXLATEOBJ exlo;
+
+ /* Never use with non-solid brushes */
+ ASSERT(pebo->flattrs & GDIBRUSH_IS_SOLID);
+
+ /* Set the RGB color */
+ pebo->crRealize = crColor;
+ pebo->ulRGBColor = crColor;
+
+ /* Initialize an XLATEOBJ RGB -> surface */
+ EXLATEOBJ_vInitialize(&exlo,
+ &gpalRGB,
+ pebo->ppalSurf,
+ pebo->crCurrentBack,
+ 0,
+ 0);
+
+ /* Translate the brush color to the target format */
+ iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
+ pebo->BrushObject.iSolidColor = iSolidColor;
+
+ /* Clean up the XLATEOBJ */
+ EXLATEOBJ_vCleanup(&exlo);
+}
+
+VOID
+NTAPI
+EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo)
+{
+ /* Check if there's a GDI realisation */
+ if (pebo->pengbrush)
+ {
+ EngDeleteSurface(pebo->pengbrush);
+ pebo->pengbrush = NULL;
+ }
+
+ /* Check if there's a driver's realisation */
+ if (pebo->BrushObject.pvRbrush)
+ {
+ /* Free allocated driver memory */
+ EngFreeMem(pebo->BrushObject.pvRbrush);
+ pebo->BrushObject.pvRbrush = NULL;
+ }
+
+ PALETTE_ShareUnlockPalette(pebo->ppalSurf);
+}
+
+VOID
+NTAPI
+EBRUSHOBJ_vUpdate(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
+{
+ /* Cleanup the brush */
+ EBRUSHOBJ_vCleanup(pebo);
+
+ /* Reinitialize */
+ EBRUSHOBJ_vInit(pebo, pbrush, pdc);
+}
+
+/**
+ * This function is not exported, because it makes no sense for
+ * The driver to punt back to this function */
+BOOL
+APIENTRY
+EngRealizeBrush(
+ BRUSHOBJ *pbo,
+ SURFOBJ *psoDst,
+ SURFOBJ *psoPattern,
+ SURFOBJ *psoMask,
+ XLATEOBJ *pxlo,
+ ULONG iHatch)
+{
+ EBRUSHOBJ *pebo;
+ HBITMAP hbmpRealize;
+ SURFOBJ *psoRealize;
+ POINTL ptlSrc = {0, 0};
+ RECTL rclDest;
+ ULONG lWidth;
+
+ /* Calculate width in bytes of the realized brush */
+ lWidth = DIB_GetDIBWidthBytes(psoPattern->sizlBitmap.cx,
+ BitsPerFormat(psoDst->iBitmapFormat));
+
+ /* Allocate a bitmap */
+ hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap,
+ lWidth,
+ psoDst->iBitmapFormat,
+ BMF_NOZEROINIT,
+ NULL);
+ if (!hbmpRealize)
+ {
+ return FALSE;
+ }
+
+ /* Lock the bitmap */
+ psoRealize = EngLockSurface(hbmpRealize);
+ if (!psoRealize)
+ {
+ EngDeleteSurface(hbmpRealize);
+ return FALSE;
+ }
+
+ /* Copy the bits to the new format bitmap */
+ rclDest.left = rclDest.top = 0;
+ rclDest.right = psoPattern->sizlBitmap.cx;
+ rclDest.bottom = psoPattern->sizlBitmap.cy;
+ EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc);
+
+ /* Unlock the bitmap again */
+ EngUnlockSurface(psoRealize);
+
+ pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
+ pebo->pengbrush = (PVOID)hbmpRealize;
+
+ return TRUE;
+}
+
+BOOL
+NTAPI
+EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver)
+{
+ BOOL bResult;
+ PFN_DrvRealizeBrush pfnRealzizeBrush = NULL;
+ PSURFACE psurfPattern, psurfMask;
+ PPDEVOBJ ppdev = NULL;
+ EXLATEOBJ exlo;
+
+ /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */
+ ASSERT(pebo->psurfTrg);
+
+ ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
+
+ // FIXME: all SURFACEs need a PDEV
+ if (ppdev && bCallDriver)
+ pfnRealzizeBrush = ppdev->DriverFunctions.RealizeBrush;
+
+ if (!pfnRealzizeBrush)
+ pfnRealzizeBrush = EngRealizeBrush;
+
+ psurfPattern = SURFACE_ShareLockSurface(pebo->pbrush->hbmPattern);
+ ASSERT(psurfPattern);
+ ASSERT(psurfPattern->ppal);
+
+ /* FIXME: implement mask */
+ psurfMask = NULL;
+
+ /* Initialize XLATEOBJ for the brush */
+ EXLATEOBJ_vInitialize(&exlo,
+ psurfPattern->ppal,
+ pebo->psurfTrg->ppal,
+ 0,
+ pebo->crCurrentBack,
+ pebo->crCurrentText);
+
+ /* Create the realization */
+ bResult = pfnRealzizeBrush(&pebo->BrushObject,
+ &pebo->psurfTrg->SurfObj,
+ &psurfPattern->SurfObj,
+ psurfMask ? &psurfMask->SurfObj : NULL,
+ &exlo.xlo,
+ -1); // FIXME: what about hatch brushes?
+
+ /* Cleanup the XLATEOBJ */
+ EXLATEOBJ_vCleanup(&exlo);
+
+ /* Unlock surfaces */
+ if (psurfPattern)
+ SURFACE_ShareUnlockSurface(psurfPattern);
+ if (psurfMask)
+ SURFACE_ShareUnlockSurface(psurfMask);
+
+ return bResult;
+}
+
+PVOID
+NTAPI
+EBRUSHOBJ_pvGetEngBrush(EBRUSHOBJ *pebo)
+{
+ BOOL bResult;
+
+ if (!pebo->pengbrush)
+ {
+ bResult = EBRUSHOBJ_bRealizeBrush(pebo, FALSE);
+ if (!bResult)
+ {
+ if (pebo->pengbrush)
+ EngDeleteSurface(pebo->pengbrush);
+ pebo->pengbrush = NULL;
+ }
+ }
+
+ return pebo->pengbrush;
+}
+
+
+/** Exported DDI functions ****************************************************/
+
+/*
+ * @implemented
+ */
+PVOID APIENTRY
+BRUSHOBJ_pvAllocRbrush(
+ IN BRUSHOBJ *pbo,
+ IN ULONG cj)
+{
++ pbo->pvRbrush = EngAllocMem(0, cj, GDITAG_RBRUSH);
+ return pbo->pvRbrush;
+}
+
+/*
+ * @implemented
+ */
+PVOID APIENTRY
+BRUSHOBJ_pvGetRbrush(
+ IN BRUSHOBJ *pbo)
+{
+ EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
+ BOOL bResult;
+
+ if (!pbo->pvRbrush)
+ {
+ bResult = EBRUSHOBJ_bRealizeBrush(pebo, TRUE);
+ if (!bResult)
+ {
+ if (pbo->pvRbrush)
+ {
+ EngFreeMem(pbo->pvRbrush);
+ pbo->pvRbrush = NULL;
+ }
+ }
+ }
+
+ return pbo->pvRbrush;
+}
+
+/*
+ * @implemented
+ */
+ULONG APIENTRY
+BRUSHOBJ_ulGetBrushColor(
+ IN BRUSHOBJ *pbo)
+{
+ EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
+ return pebo->ulRGBColor;
+}
+
+/* EOF */
--- /dev/null
- Process->Win32Process = ExAllocatePool(NonPagedPool, sizeof(PROCESSINFO));
+/*
+ * 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);
+ KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+ 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 */
- Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool, sizeof(THREADINFO));
++ Process->Win32Process = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_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 = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_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;
+ }
+
+ /* Initialize default palettes */
+ PALETTE_Init();
+
+ /* 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
- wce = ExAllocatePool(PagedPool, sizeof(CLIPBOARDCHAINELEMENT));
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Clipboard routines
+ * FILE: subsys/win32k/ntuser/clipboard.c
+ * PROGRAMER: Filip Navara <xnavara@volny.cz>
+ * Pablo Borobia <pborobia@gmail.com>
+ */
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#define DATA_DELAYED_RENDER 0
+#define DATA_SYNTHESIZED_RENDER -1
+
+PTHREADINFO ClipboardThread;
+PTHREADINFO ClipboardOwnerThread;
+PWINDOW_OBJECT ClipboardWindow;
+PWINDOW_OBJECT ClipboardViewerWindow;
+PWINDOW_OBJECT ClipboardOwnerWindow;
+BOOL sendDrawClipboardMsg;
+BOOL recentlySetClipboard;
+BOOL delayedRender;
+UINT lastEnumClipboardFormats;
+DWORD ClipboardSequenceNumber = 0;
+
+PCLIPBOARDCHAINELEMENT WindowsChain = NULL;
+PCLIPBOARDELEMENT ClipboardData = NULL;
+
+PCHAR synthesizedData;
+DWORD synthesizedDataSize;
+
+
+/*==============================================================*/
+
+/* return the pointer to the prev window of the finded window,
+ if NULL does not exists in the chain */
+PCLIPBOARDCHAINELEMENT FASTCALL
+IntIsWindowInChain(PWINDOW_OBJECT window)
+{
+ PCLIPBOARDCHAINELEMENT wce = WindowsChain;
+
+ while (wce)
+ {
+ if (wce->window == window)
+ {
+ break;
+ }
+ wce = wce->next;
+ }
+
+ return wce;
+}
+
+VOID FASTCALL printChain(VOID)
+{
+ /*test*/
+ PCLIPBOARDCHAINELEMENT wce2 = WindowsChain;
+ while (wce2)
+ {
+ DPRINT1("chain: %p\n", wce2->window->hSelf);
+ wce2 = wce2->next;
+ }
+}
+
+/* the new window always have to be the first in the chain */
+PCLIPBOARDCHAINELEMENT FASTCALL
+IntAddWindowToChain(PWINDOW_OBJECT window)
+{
+ PCLIPBOARDCHAINELEMENT wce = NULL;
+
+ if (!IntIsWindowInChain(window))
+ {
+ wce = WindowsChain;
+
- ce = ExAllocatePool(PagedPool, sizeof(CLIPBOARDELEMENT));
++ wce = ExAllocatePoolWithTag(PagedPool, sizeof(CLIPBOARDCHAINELEMENT), USERTAG_CLIPBOARD);
+ if (wce == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ goto exit_addChain;
+ }
+
+ wce->window = window;
+ wce->next = WindowsChain;
+
+ WindowsChain = wce;
+
+ //printChain();
+ }
+exit_addChain:
+
+ /* return the next window to beremoved later */
+ return wce;
+}
+
+PCLIPBOARDCHAINELEMENT FASTCALL
+IntRemoveWindowFromChain(PWINDOW_OBJECT window)
+{
+ PCLIPBOARDCHAINELEMENT wce = WindowsChain;
+ PCLIPBOARDCHAINELEMENT *link = &WindowsChain;
+
+ if (IntIsWindowInChain(window))
+ {
+ while (wce != NULL)
+ {
+ if (wce->window == window)
+ {
+ *link = wce->next;
+ break;
+ }
+
+ link = &wce->next;
+ wce = wce->next;
+ }
+
+ //printChain();
+
+ return wce;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/*==============================================================*/
+/* if format exists, returns a non zero value (pointing to format object) */
+PCLIPBOARDELEMENT FASTCALL
+intIsFormatAvailable(UINT format)
+{
+ PCLIPBOARDELEMENT ret = NULL;
+ PCLIPBOARDELEMENT ce = ClipboardData;
+
+ while(ce)
+ {
+ if (ce->format == format)
+ {
+ ret = ce;
+ break;
+ }
+ ce = ce->next;
+ }
+ return ret;
+}
+
+/* counts how many distinct format were are in the clipboard */
+DWORD FASTCALL
+IntCountClipboardFormats(VOID)
+{
+ DWORD ret = 0;
+ PCLIPBOARDELEMENT ce = ClipboardData;
+
+ while(ce)
+ {
+ ret++;
+ ce = ce->next;
+ }
+ return ret;
+}
+
+/* adds a new format and data to the clipboard */
+PCLIPBOARDELEMENT FASTCALL
+intAddFormatedData(UINT format, HANDLE hData, DWORD size)
+{
+ PCLIPBOARDELEMENT ce = NULL;
+
- hCBData = ExAllocatePool(PagedPool, size);
++ ce = ExAllocatePoolWithTag(PagedPool, sizeof(CLIPBOARDELEMENT), USERTAG_CLIPBOARD);
+ if (ce == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ else
+ {
+ ce->format = format;
+ ce->size = size;
+ ce->hData = hData;
+ ce->next = ClipboardData;
+
+ ClipboardData = ce;
+
+ IntIncrementSequenceNumber();
+ }
+
+ return ce;
+}
+
+/* removes a format and its data from the clipboard */
+BOOL FASTCALL
+intRemoveFormatedData(UINT format)
+{
+ BOOL ret = FALSE;
+ PCLIPBOARDELEMENT ce = ClipboardData;
+ PCLIPBOARDELEMENT *link = &ClipboardData;
+
+ if (intIsFormatAvailable(format))
+ {
+ while (ce != NULL)
+ {
+ if (ce->format == format)
+ {
+ *link = ce->next;
+ break;
+ }
+
+ link = &ce->next;
+ ce = ce->next;
+ }
+
+ if (ce->hData)
+ {
+ ExFreePool(ce->hData);
+ }
+ ExFreePool(ce);
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+VOID FASTCALL
+IntEmptyClipboardData(VOID)
+{
+ PCLIPBOARDELEMENT ce = ClipboardData;
+ PCLIPBOARDELEMENT tmp;
+
+ while(ce)
+ {
+ tmp = ce->next;
+ if (ce->hData)
+ {
+ ExFreePool(ce->hData);
+ }
+ ExFreePool(ce);
+ ce = tmp;
+ }
+
+ ClipboardData = NULL;
+}
+
+/*==============================================================*/
+
+HANDLE FASTCALL
+renderBITMAPfromDIB(LPBYTE pDIB)
+{
+ HDC hdc;
+ HBITMAP hbitmap;
+ unsigned int offset;
+ BITMAPV5INFO bmi;
+ NTSTATUS Status ;
+
+ //hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
+ hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE);
+
+ /* Probe it */
+ _SEH2_TRY
+ {
+ Status = ProbeAndConvertToBitmapV5Info(&bmi, (BITMAPINFO*)pDIB, DIB_RGB_COLORS, 0);
+ offset = DIB_BitmapInfoSize((BITMAPINFO*)pDIB, DIB_RGB_COLORS);
+ ProbeForRead(pDIB + offset, bmi.bmiHeader.bV5SizeImage, 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ UserReleaseDC(ClipboardWindow, hdc, FALSE);
+ return NULL;
+ }
+
+ hbitmap = GreCreateDIBitmapInternal(hdc,
+ bmi.bmiHeader.bV5Width,
+ bmi.bmiHeader.bV5Height,
+ CBM_INIT,
+ pDIB+offset,
+ &bmi,
+ DIB_RGB_COLORS,
+ 0,
+ 0);
+ //UserReleaseDC(NULL, hdc, FALSE);
+ UserReleaseDC(ClipboardWindow, hdc, FALSE);
+
+ return hbitmap;
+}
+
+BOOL FASTCALL
+canSinthesize(UINT format)
+{
+ BOOL ret = FALSE;
+
+ switch(format)
+ {
+ case CF_BITMAP:
+ case CF_METAFILEPICT:
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+/* returns the size of the sinthesized data */
+DWORD FASTCALL
+synthesizeData(UINT format)
+{
+ DWORD ret = 0;
+
+ synthesizedData = NULL;
+ synthesizedDataSize = 0;
+
+ if (!canSinthesize(format))
+ {
+ return 0;
+ }
+
+ switch (format)
+ {
+ case CF_BITMAP:
+ {
+ break;
+ }
+
+ case CF_METAFILEPICT:
+ {
+ break;
+ }
+ }
+
+ ret = 1;
+
+ return ret;
+}
+
+VOID FASTCALL
+freeSynthesizedData(VOID)
+{
+ ExFreePool(synthesizedData);
+}
+
+/*==============================================================*/
+
+BOOL FASTCALL
+intIsClipboardOpenByMe(VOID)
+{
+ /* check if we open the clipboard */
+ if (ClipboardThread && ClipboardThread == PsGetCurrentThreadWin32Thread())
+ {
+ /* yes, we got a thread and its the same that opens the clipboard */
+ return TRUE;
+
+ }
+ /* will fail if not thread (closed) or not open by me*/
+ return FALSE;
+}
+
+/* IntClipboardFreeWindow it's called when a window was destroyed */
+VOID FASTCALL
+IntClipboardFreeWindow(PWINDOW_OBJECT window)
+{
+ /* called from co_UserFreeWindow in window.c */
+ /* check if clipboard is not locked by this window, if yes, unlock it */
+ if (ClipboardThread == PsGetCurrentThreadWin32Thread())
+ {
+ /* the window that opens the clipboard was destroyed */
+ ClipboardThread = NULL;
+ ClipboardWindow = NULL;
+ //TODO: free clipboard
+ }
+ if (window == ClipboardOwnerWindow)
+ {
+ /* the owner window was destroyed */
+ ClipboardOwnerWindow = NULL;
+ ClipboardOwnerThread = NULL;
+ }
+ /* remove window from window chain */
+ if (IntIsWindowInChain(window))
+ {
+ PCLIPBOARDCHAINELEMENT w = IntRemoveWindowFromChain(window);
+ if (w)
+ {
+ ExFreePool(w);
+ }
+ }
+}
+
+BOOL APIENTRY
+NtUserOpenClipboard(HWND hWnd, DWORD Unknown1)
+{
+
+ PWINDOW_OBJECT Window;
+ BOOL ret = FALSE;
+
+ UserEnterExclusive();
+
+ sendDrawClipboardMsg = FALSE;
+ recentlySetClipboard = FALSE;
+
+ if (ClipboardThread)
+ {
+ /* clipboard is already open */
+ if (ClipboardThread == PsGetCurrentThreadWin32Thread())
+ {
+ if (ClipboardOwnerWindow)
+ {
+ if (ClipboardOwnerWindow->hSelf == hWnd)
+ {
+ ret = TRUE;
+ }
+ }
+ else
+ {
+ if (hWnd == NULL)
+ {
+ ret = TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+
+ if (hWnd != NULL)
+ {
+ Window = UserGetWindowObject(hWnd);
+
+ if (Window != NULL)
+ {
+ ClipboardWindow = Window;
+ ClipboardThread = PsGetCurrentThreadWin32Thread();
+ ret = TRUE;
+ }
+ else
+ {
+ ClipboardWindow = NULL;
+ ClipboardThread = NULL;
+ ClipboardOwnerWindow = NULL;
+ ClipboardOwnerThread = NULL;
+ }
+ }
+ else
+ {
+ ClipboardWindow = NULL;
+ ClipboardThread = PsGetCurrentThreadWin32Thread();
+ ret = TRUE;
+ }
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+BOOL APIENTRY
+NtUserCloseClipboard(VOID)
+{
+ BOOL ret = FALSE;
+
+ UserEnterExclusive();
+
+ if (intIsClipboardOpenByMe())
+ {
+ ClipboardWindow = NULL;
+ ClipboardThread = NULL;
+ ret = TRUE;
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN);
+ }
+
+ recentlySetClipboard = FALSE;
+
+ UserLeave();
+
+ if (sendDrawClipboardMsg && WindowsChain)
+ {
+ /* only send message to the first window in the chain, then they'll do the chain */
+ /* commented because it makes a crash in co_MsqSendMessage
+ ASSERT(WindowsChain->window);
+ ASSERT(WindowsChain->window->hSelf);
+ DPRINT1("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", WindowsChain->window->hSelf);
+ co_IntSendMessage(WindowsChain->window->hSelf, WM_DRAWCLIPBOARD, 0, 0);
+ */
+ }
+
+ return ret;
+}
+
+HWND APIENTRY
+NtUserGetOpenClipboardWindow(VOID)
+{
+ HWND ret = NULL;
+
+ UserEnterShared();
+
+ if (ClipboardWindow)
+ {
+ ret = ClipboardWindow->hSelf;
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+BOOL APIENTRY
+NtUserChangeClipboardChain(HWND hWndRemove, HWND hWndNewNext)
+{
+ BOOL ret = FALSE;
+ PCLIPBOARDCHAINELEMENT w = NULL;
+ PWINDOW_OBJECT removeWindow;
+ UserEnterExclusive();
+
+ removeWindow = UserGetWindowObject(hWndRemove);
+
+ if (removeWindow)
+ {
+ if ((ret = !!IntIsWindowInChain(removeWindow)))
+ {
+ w = IntRemoveWindowFromChain(removeWindow);
+ if (w)
+ {
+ ExFreePool(w);
+ }
+ }
+ }
+
+ if (ret && WindowsChain)
+ {
+ // only send message to the first window in the chain,
+ // then they do the chain
+
+ /* WindowsChain->window may be NULL */
+ LPARAM lparam = WindowsChain->window == NULL ? 0 : (LPARAM)WindowsChain->window->hSelf;
+ DPRINT1("Message: WM_CHANGECBCHAIN to %p", WindowsChain->window->hSelf);
+ co_IntSendMessage(WindowsChain->window->hSelf, WM_CHANGECBCHAIN, (WPARAM)hWndRemove, lparam);
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+DWORD APIENTRY
+NtUserCountClipboardFormats(VOID)
+{
+ DWORD ret = 0;
+
+ if (ClipboardData)
+ {
+ ret = IntCountClipboardFormats();
+ }
+
+ return ret;
+}
+
+DWORD APIENTRY
+NtUserEmptyClipboard(VOID)
+{
+ BOOL ret = FALSE;
+
+ UserEnterExclusive();
+
+ if (intIsClipboardOpenByMe())
+ {
+ if (ClipboardData)
+ {
+ IntEmptyClipboardData();
+ }
+
+ ClipboardOwnerWindow = ClipboardWindow;
+ ClipboardOwnerThread = ClipboardThread;
+
+ IntIncrementSequenceNumber();
+
+ ret = TRUE;
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN);
+ }
+
+ if (ret && ClipboardOwnerWindow)
+ {
+ DPRINT("Clipboard: WM_DESTROYCLIPBOARD to %p", ClipboardOwnerWindow->hSelf);
+ co_IntSendMessage( ClipboardOwnerWindow->hSelf, WM_DESTROYCLIPBOARD, 0, 0);
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+HANDLE APIENTRY
+NtUserGetClipboardData(UINT uFormat, PVOID pBuffer)
+{
+ HANDLE ret = NULL;
+
+ UserEnterShared();
+
+ if (intIsClipboardOpenByMe())
+ {
+ /* when Unknown1 is zero, we returns to user32 the data size */
+ if (!pBuffer)
+ {
+ PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat);
+
+ if (data)
+ {
+ /* format exists in clipboard */
+ if (data->size == DATA_DELAYED_RENDER)
+ {
+ /* tell owner what data needs to be rendered */
+ if (ClipboardOwnerWindow)
+ {
+ ASSERT(ClipboardOwnerWindow->hSelf);
+ co_IntSendMessage(ClipboardOwnerWindow->hSelf, WM_RENDERFORMAT, (WPARAM)uFormat, 0);
+ data = intIsFormatAvailable(uFormat);
+ ASSERT(data->size);
+ ret = (HANDLE)(ULONG_PTR)data->size;
+ }
+ }
+ else
+ {
+ if (data->size == DATA_SYNTHESIZED_RENDER)
+ {
+ data->size = synthesizeData(uFormat);
+ }
+
+ }
+ ret = (HANDLE)(ULONG_PTR)data->size;
+ }
+ else
+ {
+ /* there is no data in this format */
+ //ret = (HANDLE)FALSE;
+ }
+ }
+ else
+ {
+ PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat);
+
+ if (data)
+ {
+ if (data->size == DATA_DELAYED_RENDER)
+ {
+ // we rendered it in 1st call of getclipboard data
+ }
+ else
+ {
+ if (data->size == DATA_SYNTHESIZED_RENDER)
+ {
+ if (uFormat == CF_BITMAP)
+ {
+ /* BITMAP & METAFILEs returns a GDI handle */
+ PCLIPBOARDELEMENT data = intIsFormatAvailable(CF_DIB);
+ if (data)
+ {
+ ret = renderBITMAPfromDIB(data->hData);
+ }
+ }
+ else
+ {
+ ret = (HANDLE)pBuffer;
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(pBuffer, synthesizedDataSize, 1);
+ memcpy(pBuffer, (PCHAR)synthesizedData, synthesizedDataSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret = NULL;
+ }
+ _SEH2_END
+
+ freeSynthesizedData();
+ }
+ }
+ else
+ {
+ ret = (HANDLE)pBuffer;
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(pBuffer, data->size, 1);
+ memcpy(pBuffer, (PCHAR)data->hData, data->size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ret = NULL;
+ }
+ _SEH2_END
+ }
+ }
+
+ }
+
+ }
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN);
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+INT APIENTRY
+NtUserGetClipboardFormatName(UINT format, PUNICODE_STRING FormatName,
+ INT cchMaxCount)
+{
+ UNICODE_STRING sFormatName;
+ INT ret = 0;
+
+ /* if the format is built-in we fail */
+ if (format < 0xc000)
+ {
+ /* registetrated formats are >= 0xc000 */
+ return 0;
+ }
+
+ if((cchMaxCount < 1) || !FormatName)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWriteUnicodeString(FormatName);
+ sFormatName = *(volatile UNICODE_STRING *)FormatName;
+ ProbeForWrite(sFormatName.Buffer, sFormatName.MaximumLength, 1);
+
+ ret = IntGetAtomName((RTL_ATOM)format, sFormatName.Buffer, cchMaxCount * sizeof(WCHAR));
+
+ if (ret >= 0)
+ {
+ ret = ret / sizeof(WCHAR);
+ sFormatName.Length = ret;
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ return ret;
+}
+
+HWND APIENTRY
+NtUserGetClipboardOwner(VOID)
+{
+ HWND ret = NULL;
+
+ UserEnterShared();
+
+ if (ClipboardOwnerWindow)
+ {
+ ret = ClipboardOwnerWindow->hSelf;
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+HWND APIENTRY
+NtUserGetClipboardViewer(VOID)
+{
+ HWND ret = NULL;
+
+ UserEnterShared();
+
+ if (WindowsChain)
+ {
+ ret = WindowsChain->window->hSelf;
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+INT APIENTRY
+NtUserGetPriorityClipboardFormat(UINT *paFormatPriorityList, INT cFormats)
+{
+ INT i;
+ UINT *priorityList;
+ INT ret = 0;
+
+ UserEnterExclusive();
+
+ _SEH2_TRY
+ {
+ if (IntCountClipboardFormats() == 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ProbeForRead(paFormatPriorityList, cFormats, sizeof(UINT));
+
+ priorityList = paFormatPriorityList;
+
+ ret = -1;
+
+ for (i = 0; i < cFormats; i++)
+ {
+ if (intIsFormatAvailable(priorityList[i]))
+ {
+ ret = priorityList[i];
+ break;
+ }
+ }
+
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ UserLeave();
+
+ return ret;
+
+}
+
+BOOL APIENTRY
+NtUserIsClipboardFormatAvailable(UINT format)
+{
+ BOOL ret = FALSE;
+
+ UserEnterShared();
+
+ ret = (intIsFormatAvailable(format) != NULL);
+
+ UserLeave();
+
+ return ret;
+}
+
+
+
+HANDLE APIENTRY
+NtUserSetClipboardData(UINT uFormat, HANDLE hMem, DWORD size)
+{
+ HANDLE hCBData = NULL;
+ UNICODE_STRING unicodeString;
+ OEM_STRING oemString;
+ ANSI_STRING ansiString;
+
+ UserEnterExclusive();
+
+ /* to place data here the we need to be the owner */
+ if (ClipboardOwnerThread == PsGetCurrentThreadWin32Thread())
+ {
+ PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat);
+ if (data)
+ {
+
+ if (data->size == DATA_DELAYED_RENDER)
+ {
+ intRemoveFormatedData(uFormat);
+ }
+ else
+ {
+ // we already have this format on clipboard
+ goto exit_setCB;
+ }
+ }
+
+ if (hMem)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead(hMem, size, 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(goto exit_setCB);
+ }
+ _SEH2_END;
+
+ if (intIsClipboardOpenByMe())
+ {
+ delayedRender = FALSE;
+ }
+
+ if (!canSinthesize(uFormat))
+ {
- hCBData = ExAllocatePool(PagedPool, size);
++ hCBData = ExAllocatePoolWithTag(PagedPool, size, USERTAG_CLIPBOARD);
+ memcpy(hCBData, hMem, size);
+ intAddFormatedData(uFormat, hCBData, size);
+ DPRINT1("Data stored\n");
+ }
+
+ sendDrawClipboardMsg = TRUE;
+ recentlySetClipboard = TRUE;
+ lastEnumClipboardFormats = uFormat;
+
+ /* conversions */
+ switch (uFormat)
+ {
+ case CF_TEXT:
+ {
+ //TODO : sinthesize CF_UNICODETEXT & CF_OEMTEXT
+ // CF_TEXT -> CF_UNICODETEXT
+ ansiString.Buffer = hCBData;
+ ansiString.Length = size;
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ intAddFormatedData(CF_UNICODETEXT, unicodeString.Buffer, unicodeString.Length * sizeof(WCHAR));
+ // CF_TEXT -> CF_OEMTEXT
+ RtlUnicodeStringToOemString(&oemString, &unicodeString, TRUE);
+ intAddFormatedData(CF_OEMTEXT, oemString.Buffer, oemString.Length);
+ //HKCU\Control Panel\International\Locale
+ //intAddFormatedData(CF_LOCALE, oemString.Buffer, oemString.Length);
+ break;
+ }
+ case CF_UNICODETEXT:
+ {
+ //TODO : sinthesize CF_TEXT & CF_OEMTEXT
+ //CF_UNICODETEXT -> CF_TEXT
+ unicodeString.Buffer = hCBData;
+ unicodeString.Length = size;
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ intAddFormatedData(CF_TEXT, ansiString.Buffer, ansiString.Length);
+ //CF_UNICODETEXT -> CF_OEMTEXT
+ RtlUnicodeStringToOemString(&oemString, &unicodeString, TRUE);
+ intAddFormatedData(CF_OEMTEXT, oemString.Buffer, oemString.Length);
+ break;
+ }
+ case CF_OEMTEXT:
+ {
+ //TODO : sinthesize CF_TEXT & CF_UNICODETEXT
+ //CF_OEMTEXT -> CF_UNICODETEXT
+ oemString.Buffer = hCBData;
+ oemString.Length = size;
+ RtlOemStringToUnicodeString(&unicodeString, &oemString, TRUE);
+ intAddFormatedData(CF_UNICODETEXT, unicodeString.Buffer, unicodeString.Length * sizeof(WCHAR));
+ //CF_OEMTEXT -> CF_TEXT
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ intAddFormatedData(CF_TEXT, ansiString.Buffer, ansiString.Length);
+ break;
+ }
+ case CF_BITMAP:
+ {
+ // we need to render the DIB or DIBV5 format as soon as possible
+ // because pallette information may change
+
+ HDC hdc;
+ INT ret;
+ BITMAP bm;
+ BITMAPINFO bi;
+ SURFACE *psurf;
+
+ hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
+
+
+ psurf = SURFACE_LockSurface(hMem);
+ BITMAP_GetObject(psurf, sizeof(BITMAP), (PVOID)&bm);
+ if(psurf)
+ {
+ SURFACE_UnlockSurface(psurf);
+ }
+
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = bm.bmWidth;
+ bi.bmiHeader.biHeight = bm.bmHeight;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biSizeImage = 0;
+ bi.bmiHeader.biXPelsPerMeter = 0;
+ bi.bmiHeader.biYPelsPerMeter = 0;
+ bi.bmiHeader.biClrUsed = 0;
+
+ ret = NtGdiGetDIBitsInternal(hdc, hMem, 0, bm.bmHeight, NULL, &bi, DIB_RGB_COLORS, 0, 0);
+
+ size = bi.bmiHeader.biSizeImage + sizeof(BITMAPINFOHEADER);
+
++ hCBData = ExAllocatePoolWithTag(PagedPool, size, USERTAG_CLIPBOARD);
+ memcpy(hCBData, &bi, sizeof(BITMAPINFOHEADER));
+
+ ret = NtGdiGetDIBitsInternal(hdc, hMem, 0, bm.bmHeight, (LPBYTE)hCBData + sizeof(BITMAPINFOHEADER), &bi, DIB_RGB_COLORS, 0, 0);
+
+ UserReleaseDC(NULL, hdc, FALSE);
+
+ intAddFormatedData(CF_DIB, hCBData, size);
+ intAddFormatedData(CF_BITMAP, 0, DATA_SYNTHESIZED_RENDER);
+ // intAddFormatedData(CF_DIBV5, hCBData, size);
+
+ break;
+ }
+ case CF_DIB:
+ {
+ intAddFormatedData(CF_BITMAP, 0, DATA_SYNTHESIZED_RENDER);
+ // intAddFormatedData(CF_DIBV5, hCBData, size);
+ /* investigate */
+ // intAddFormatedData(CF_PALETTE, hCBData, size);
+ break;
+ }
+ case CF_DIBV5:
+ // intAddFormatedData(CF_BITMAP, hCBData, size);
+ // intAddFormatedData(CF_PALETTE, hCBData, size);
+ // intAddFormatedData(CF_DIB, hCBData, size);
+ break;
+ case CF_ENHMETAFILE:
+ // intAddFormatedData(CF_METAFILEPICT, hCBData, size);
+ break;
+ case CF_METAFILEPICT:
+ // intAddFormatedData(CF_ENHMETAFILE, hCBData, size);
+ break;
+ }
+
+ }
+ else
+ {
+ // the window provides data in the specified format
+ delayedRender = TRUE;
+ sendDrawClipboardMsg = TRUE;
+ intAddFormatedData(uFormat, NULL, 0);
+ DPRINT1("SetClipboardData delayed format: %d\n", uFormat);
+ }
+
+
+ }
+
+exit_setCB:
+
+ UserLeave();
+
+ return hMem;
+}
+
+HWND APIENTRY
+NtUserSetClipboardViewer(HWND hWndNewViewer)
+{
+ HWND ret = NULL;
+ PCLIPBOARDCHAINELEMENT newWC = NULL;
+ PWINDOW_OBJECT window;
+
+ UserEnterExclusive();
+
+ window = UserGetWindowObject(hWndNewViewer);
+
+ if (window)
+ {
+ if ((newWC = IntAddWindowToChain(window)))
+ {
+ if (newWC)
+ {
+ // newWC->next may be NULL if we are the first window in the chain
+ if (newWC->next)
+ {
+ // return the next HWND available window in the chain
+ ret = newWC->next->window->hSelf;
+ }
+ }
+ }
+ }
+
+ UserLeave();
+
+ return ret;
+}
+
+UINT APIENTRY
+IntEnumClipboardFormats(UINT uFormat)
+{
+ UINT ret = 0;
+
+ if (intIsClipboardOpenByMe())
+ {
+ if (uFormat == 0)
+ {
+ if (recentlySetClipboard)
+ {
+ ret = lastEnumClipboardFormats;
+ }
+ else
+ {
+ /* return the first available format */
+ if (ClipboardData)
+ {
+ ret = ClipboardData->format;
+ }
+ }
+ }
+ else
+ {
+ if (recentlySetClipboard)
+ {
+ ret = 0;
+ }
+ else
+ {
+ /* querying nextt available format */
+ PCLIPBOARDELEMENT data = intIsFormatAvailable(uFormat);
+
+ if (data)
+ {
+ if (data->next)
+ {
+ ret = data->next->format;
+ }
+ else
+ {
+ /* reached the end */
+ ret = 0;
+ }
+ }
+ }
+
+ }
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_CLIPBOARD_NOT_OPEN);
+ }
+
+ return ret;
+}
+
+// This number is incremented whenever the contents of the clipboard change
+// or the clipboard is emptied.
+// If clipboard rendering is delayed,
+// the sequence number is not incremented until the changes are rendered.
+VOID FASTCALL
+IntIncrementSequenceNumber(VOID)
+{
+ PTHREADINFO pti;
+ PWINSTATION_OBJECT WinStaObj;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ WinStaObj = pti->rpdesk->rpwinstaParent;
+
+ WinStaObj->Clipboard->ClipboardSequenceNumber++;
+}
+
+DWORD APIENTRY
+NtUserGetClipboardSequenceNumber(VOID)
+{
+ //windowstation sequence number
+ //if no WINSTA_ACCESSCLIPBOARD access to the window station,
+ //the function returns zero.
+ DWORD sn;
+
+ HWINSTA WinSta;
+ PWINSTATION_OBJECT WinStaObj;
+ NTSTATUS Status;
+
+ WinSta = UserGetProcessWindowStation();
+
+ Status = IntValidateWindowStationHandle(WinSta, KernelMode, WINSTA_ACCESSCLIPBOARD, &WinStaObj);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("No WINSTA_ACCESSCLIPBOARD access\n");
+ SetLastNtError(Status);
+ return 0;
+ }
+
+ sn = WinStaObj->ClipboardSequenceNumber;
+
+ ObDereferenceObject(WinStaObj);
+
+ //local copy
+ //sn = ClipboardSequenceNumber;
+
+ return sn;
+}
+
+
+/**************** VISTA FUNCTIONS******************/
+
+BOOL APIENTRY NtUserAddClipboardFormatListener(
+ HWND hwnd
+)
+{
+ UNIMPLEMENTED;
+ return FALSE;
+}
+
+BOOL APIENTRY NtUserRemoveClipboardFormatListener(
+ HWND hwnd
+)
+{
+ UNIMPLEMENTED;
+ return FALSE;
+}
+
+BOOL APIENTRY NtUserGetUpdatedClipboardFormats(
+ PUINT lpuiFormats,
+ UINT cFormats,
+ PUINT pcFormatsOut
+)
+{
+ UNIMPLEMENTED;
+ return FALSE;
+}
+
+/* EOF */
--- /dev/null
- list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Desktops
+ * FILE: subsystems/win32/win32k/ntuser/desktop.c
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISION HISTORY:
+ * 06-06-2001 CSH Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+#define TRACE DPRINT
+#define WARN DPRINT1
+#define ERR DPRINT1
+
+static
+VOID
+IntFreeDesktopHeap(
+ IN OUT PDESKTOP Desktop
+);
+
+/* GLOBALS *******************************************************************/
+
+/* Currently active desktop */
+PDESKTOP InputDesktop = NULL;
+HDESK InputDesktopHandle = NULL;
+HDC ScreenDeviceContext = NULL;
+BOOL g_PaintDesktopVersion = FALSE;
+
+GENERIC_MAPPING IntDesktopMapping =
+{
+ STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE |
+ DESKTOP_READOBJECTS,
+ STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU |
+ DESKTOP_CREATEWINDOW |
+ DESKTOP_HOOKCONTROL |
+ DESKTOP_JOURNALPLAYBACK |
+ DESKTOP_JOURNALRECORD |
+ DESKTOP_WRITEOBJECTS,
+ STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
+ STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU |
+ DESKTOP_CREATEWINDOW |
+ DESKTOP_ENUMERATE |
+ DESKTOP_HOOKCONTROL |
+ DESKTOP_JOURNALPLAYBACK |
+ DESKTOP_JOURNALRECORD |
+ DESKTOP_READOBJECTS |
+ DESKTOP_SWITCHDESKTOP |
+ DESKTOP_WRITEOBJECTS
+};
+
+/* OBJECT CALLBACKS **********************************************************/
+
+NTSTATUS
+APIENTRY
+IntDesktopObjectParse(IN PVOID ParseObject,
+ IN PVOID ObjectType,
+ IN OUT PACCESS_STATE AccessState,
+ IN KPROCESSOR_MODE AccessMode,
+ IN ULONG Attributes,
+ IN OUT PUNICODE_STRING CompleteName,
+ IN OUT PUNICODE_STRING RemainingName,
+ IN OUT PVOID Context OPTIONAL,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
+ OUT PVOID *Object)
+{
+ NTSTATUS Status;
+ PDESKTOP Desktop;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PLIST_ENTRY NextEntry, ListHead;
+ PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
+ PUNICODE_STRING DesktopName;
+
+ /* Set the list pointers and loop the window station */
+ ListHead = &WinStaObject->DesktopListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current desktop */
+ Desktop = CONTAINING_RECORD(NextEntry, DESKTOP, ListEntry);
+
+ /* Get its name */
+ DesktopName = GET_DESKTOP_NAME(Desktop);
+ if (DesktopName)
+ {
+ /* Compare the name */
+ if (RtlEqualUnicodeString(RemainingName,
+ DesktopName,
+ (Attributes & OBJ_CASE_INSENSITIVE)))
+ {
+ /* We found a match. Did this come from a create? */
+ if (Context)
+ {
+ /* Unless OPEN_IF was given, fail with an error */
+ if (!(Attributes & OBJ_OPENIF))
+ {
+ /* Name collision */
+ return STATUS_OBJECT_NAME_COLLISION;
+ }
+ else
+ {
+ /* Otherwise, return with a warning only */
+ Status = STATUS_OBJECT_NAME_EXISTS;
+ }
+ }
+ else
+ {
+ /* This was a real open, so this is OK */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Reference the desktop and return it */
+ ObReferenceObject(Desktop);
+ *Object = Desktop;
+ return Status;
+ }
+ }
+
+ /* Go to the next desktop */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* If we got here but this isn't a create, then fail */
+ if (!Context) return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ /* Create the desktop object */
+ InitializeObjectAttributes(&ObjectAttributes, RemainingName, 0, NULL, NULL);
+ Status = ObCreateObject(KernelMode,
+ ExDesktopObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(DESKTOP),
+ 0,
+ 0,
+ (PVOID)&Desktop);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Initialize shell hook window list and set the parent */
+ RtlZeroMemory(Desktop, sizeof(DESKTOP));
+ InitializeListHead(&Desktop->ShellHookWindows);
+ Desktop->rpwinstaParent = (PWINSTATION_OBJECT)ParseObject;
+
+ /* Put the desktop on the window station's list of associated desktops */
+ InsertTailList(&Desktop->rpwinstaParent->DesktopListHead,
+ &Desktop->ListEntry);
+
+ /* Set the desktop object and return success */
+ *Object = Desktop;
+ return STATUS_SUCCESS;
+}
+
+VOID APIENTRY
+IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
+{
+ PDESKTOP Desktop = (PDESKTOP)Parameters->Object;
+
+ DPRINT("Deleting desktop (0x%X)\n", Desktop);
+
+ /* Remove the desktop from the window station's list of associcated desktops */
+ RemoveEntryList(&Desktop->ListEntry);
+
+ IntFreeDesktopHeap(Desktop);
+}
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS
+FASTCALL
+InitDesktopImpl(VOID)
+{
+ /* Set Desktop Object Attributes */
+ ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP);
+ ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FASTCALL
+CleanupDesktopImpl(VOID)
+{
+ return STATUS_SUCCESS;
+}
+
+static int GetSystemVersionString(LPWSTR buffer)
+{
+ RTL_OSVERSIONINFOEXW versionInfo;
+ int len;
+
+ versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+
+ if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
+ return 0;
+
+ if (versionInfo.dwMajorVersion <= 4)
+ len = swprintf(buffer,
+ L"ReactOS Version %d.%d %s Build %d",
+ versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+ else
+ len = swprintf(buffer,
+ L"ReactOS %s (Build %d)",
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+
+ return len;
+}
+
+
+NTSTATUS FASTCALL
+IntParseDesktopPath(PEPROCESS Process,
+ PUNICODE_STRING DesktopPath,
+ HWINSTA *hWinSta,
+ HDESK *hDesktop)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING WinSta, Desktop, FullName;
+ BOOL DesktopPresent = FALSE;
+ BOOL WinStaPresent = FALSE;
+ NTSTATUS Status;
+
+ ASSERT(hWinSta);
+
+ *hWinSta = NULL;
+
+ if(hDesktop != NULL)
+ {
+ *hDesktop = NULL;
+ }
+
+ RtlInitUnicodeString(&WinSta, NULL);
+ RtlInitUnicodeString(&Desktop, NULL);
+
+ if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
+ {
+ PWCHAR c = DesktopPath->Buffer;
+ USHORT wl = 0;
+ USHORT l = DesktopPath->Length;
+
+ /*
+ * Parse the desktop path string which can be in the form "WinSta\Desktop"
+ * or just "Desktop". In latter case WinSta0 will be used.
+ */
+
+ while(l > 0)
+ {
+ if(*c == L'\\')
+ {
+ wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
+ break;
+ }
+ l -= sizeof(WCHAR);
+ c++;
+ }
+
+ if(wl > 0)
+ {
+ WinSta.Length = wl;
+ WinSta.MaximumLength = wl + sizeof(WCHAR);
+ WinSta.Buffer = DesktopPath->Buffer;
+
+ WinStaPresent = TRUE;
+ c++;
+ }
+
+ Desktop.Length = DesktopPath->Length - wl;
+ if(wl > 0)
+ {
+ Desktop.Length -= sizeof(WCHAR);
+ }
+ if(Desktop.Length > 0)
+ {
+ Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
+ Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
+ DesktopPresent = TRUE;
+ }
+ }
+
+ if(!WinStaPresent)
+ {
+#if 0
+ /* search the process handle table for (inherited) window station
+ handles, use a more appropriate one than WinSta0 if possible. */
+ if (!ObFindHandleForObject(Process,
+ NULL,
+ ExWindowStationObjectType,
+ NULL,
+ (PHANDLE)hWinSta))
+#endif
+ {
+ /* we had no luck searching for opened handles, use WinSta0 now */
+ RtlInitUnicodeString(&WinSta, L"WinSta0");
+ }
+ }
+
+ if(!DesktopPresent && hDesktop != NULL)
+ {
+#if 0
+ /* search the process handle table for (inherited) desktop
+ handles, use a more appropriate one than Default if possible. */
+ if (!ObFindHandleForObject(Process,
+ NULL,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)hDesktop))
+#endif
+ {
+ /* we had no luck searching for opened handles, use Desktop now */
+ RtlInitUnicodeString(&Desktop, L"Default");
+ }
+ }
+
+ if(*hWinSta == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the window station */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExWindowStationObjectType,
+ KernelMode,
+ NULL,
+ 0,
+ NULL,
+ (HANDLE*)hWinSta);
+
+ ExFreePoolWithTag(FullName.Buffer, TAG_STRING);
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ if(hDesktop != NULL && *hDesktop == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
+ {
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the desktop object */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ 0,
+ NULL,
+ (HANDLE*)hDesktop);
+
+ ExFreePoolWithTag(FullName.Buffer, TAG_STRING);
+
+ if(!NT_SUCCESS(Status))
+ {
+ *hDesktop = NULL;
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ SetLastNtError(Status);
+ DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * IntValidateDesktopHandle
+ *
+ * Validates the desktop handle.
+ *
+ * Remarks
+ * If the function succeeds, the handle remains referenced. If the
+ * fucntion fails, last error is set.
+ */
+
+NTSTATUS FASTCALL
+IntValidateDesktopHandle(
+ HDESK Desktop,
+ KPROCESSOR_MODE AccessMode,
+ ACCESS_MASK DesiredAccess,
+ PDESKTOP *Object)
+{
+ NTSTATUS Status;
+
+ Status = ObReferenceObjectByHandle(
+ Desktop,
+ DesiredAccess,
+ ExDesktopObjectType,
+ AccessMode,
+ (PVOID*)Object,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ SetLastNtError(Status);
+
+ return Status;
+}
+
+PDESKTOP FASTCALL
+IntGetActiveDesktop(VOID)
+{
+ return InputDesktop;
+}
+
+/*
+ * returns or creates a handle to the desktop object
+ */
+HDESK FASTCALL
+IntGetDesktopObjectHandle(PDESKTOP DesktopObject)
+{
+ NTSTATUS Status;
+ HDESK Ret;
+
+ ASSERT(DesktopObject);
+
+ if (!ObFindHandleForObject(PsGetCurrentProcess(),
+ DesktopObject,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)&Ret))
+ {
+ Status = ObOpenObjectByPointer(DesktopObject,
+ 0,
+ NULL,
+ 0,
+ ExDesktopObjectType,
+ UserMode,
+ (PHANDLE)&Ret);
+ if(!NT_SUCCESS(Status))
+ {
+ /* unable to create a handle */
+ DPRINT1("Unable to create a desktop handle\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ DPRINT1("Got handle: %lx\n", Ret);
+ }
+
+ return Ret;
+}
+
+PUSER_MESSAGE_QUEUE FASTCALL
+IntGetFocusMessageQueue(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return(NULL);
+ }
+ return (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
+}
+
+VOID FASTCALL
+IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
+{
+ PUSER_MESSAGE_QUEUE Old;
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return;
+ }
+ if(NewQueue != NULL)
+ {
+ if(NewQueue->Desktop != NULL)
+ {
+ DPRINT("Message Queue already attached to another desktop!\n");
+ return;
+ }
+ IntReferenceMessageQueue(NewQueue);
+ (void)InterlockedExchangePointer((PVOID*)&NewQueue->Desktop, pdo);
+ }
+ Old = (PUSER_MESSAGE_QUEUE)InterlockedExchangePointer((PVOID*)&pdo->ActiveMessageQueue, NewQueue);
+ if(Old != NULL)
+ {
+ (void)InterlockedExchangePointer((PVOID*)&Old->Desktop, 0);
+ IntDereferenceMessageQueue(Old);
+ }
+}
+
+HWND FASTCALL IntGetDesktopWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+ return pdo->DesktopWindow;
+}
+
+PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+
+ return UserGetWindowObject(pdo->DesktopWindow);
+}
+
+HWND FASTCALL IntGetMessageWindow(VOID)
+{
+ PDESKTOP pdo = IntGetActiveDesktop();
+
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+ return pdo->spwndMessage->head.h;
+}
+
+HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP pdo = pti->rpdesk;
+ if (NULL == pdo)
+ {
+ DPRINT1("Thread doesn't have a desktop\n");
+ return NULL;
+ }
+ return pdo->DesktopWindow;
+}
+
+BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
+{
+ if (bEnable)
+ {
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].Name = L"PaintDesktopVersion";
+ QueryTable[0].EntryContext = &g_PaintDesktopVersion;
+
+ /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
+ L"Control Panel\\Desktop",
+ QueryTable, NULL, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
+ Status);
+ g_PaintDesktopVersion = FALSE;
+ return FALSE;
+ }
+
+ DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);
+
+ return TRUE;
+ }
+ else
+ {
+ g_PaintDesktopVersion = FALSE;
+ return TRUE;
+ }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+HDC FASTCALL
+UserGetDesktopDC(ULONG DcType, BOOL EmptyDC, BOOL ValidatehWnd)
+{
+ PWINDOW_OBJECT DesktopObject = 0;
+ HDC DesktopHDC = 0;
+
+ if (DcType == DC_TYPE_DIRECT)
+ {
+ DesktopObject = UserGetDesktopWindow();
+ DesktopHDC = (HDC)UserGetWindowDC(DesktopObject);
+ }
+ else
+ {
+ HDEV hDev;
+ hDev = (HDEV)pPrimarySurface;
+ DesktopHDC = IntGdiCreateDisplayDC(hDev, DcType, EmptyDC);
+ }
+
+ return DesktopHDC;
+}
+
+VOID APIENTRY
+UserRedrawDesktop()
+{
+ PWINDOW_OBJECT Window = NULL;
+
+ Window = UserGetDesktopWindow();
+
+ IntInvalidateWindows( Window,
+ Window->hrgnUpdate,
+ RDW_FRAME |
+ RDW_ERASE |
+ RDW_INVALIDATE |
+ RDW_ALLCHILDREN);
+}
+
+
+NTSTATUS FASTCALL
+co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height)
+{
+ CSR_API_MESSAGE Request;
+
+ Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
+ Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+ Request.Data.ShowDesktopRequest.Width = Width;
+ Request.Data.ShowDesktopRequest.Height = Height;
+
+ return co_CsrNotify(&Request);
+}
+
+NTSTATUS FASTCALL
+IntHideDesktop(PDESKTOP Desktop)
+{
+#if 0
+ CSRSS_API_REQUEST Request;
+ CSRSS_API_REPLY Reply;
+
+ Request.Type = CSRSS_HIDE_DESKTOP;
+ Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+
+ return NotifyCsrss(&Request, &Reply);
+#else
+
+ PWINDOW_OBJECT DesktopWindow;
+ PWND DesktopWnd;
+
+ DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
+ if (! DesktopWindow)
+ {
+ return ERROR_INVALID_WINDOW_HANDLE;
+ }
+ DesktopWnd = DesktopWindow->Wnd;
+ DesktopWnd->style &= ~WS_VISIBLE;
+
+ return STATUS_SUCCESS;
+#endif
+}
+
+
+
+
+static
+HWND* FASTCALL
+UserBuildShellHookHwndList(PDESKTOP Desktop)
+{
+ ULONG entries=0;
+ PSHELL_HOOK_WINDOW Current;
+ HWND* list;
+
+ /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ entries++;
+
+ if (!entries) return NULL;
+
++ list = ExAllocatePoolWithTag(PagedPool, sizeof(HWND) * (entries + 1), USERTAG_WINDOWLIST); /* alloc one extra for nullterm */
+ if (list)
+ {
+ HWND* cursor = list;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ *cursor++ = Current->hWnd;
+
+ *cursor = NULL; /* nullterm list */
+ }
+
+ return list;
+}
+
+/*
+ * Send the Message to the windows registered for ShellHook
+ * notifications. The lParam contents depend on the Message. See
+ * MSDN for more details (RegisterShellHookWindow)
+ */
+VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
+{
+ PDESKTOP Desktop = IntGetActiveDesktop();
+ HWND* HwndList;
+
+ static UINT MsgType = 0;
+
+ if (!MsgType)
+ {
+
+ /* Too bad, this doesn't work.*/
+#if 0
+ UNICODE_STRING Str;
+ RtlInitUnicodeString(&Str, L"SHELLHOOK");
+ MsgType = UserRegisterWindowMessage(&Str);
+#endif
+
+ MsgType = IntAddAtom(L"SHELLHOOK");
+
+ DPRINT("MsgType = %x\n", MsgType);
+ if (!MsgType)
+ DPRINT1("LastError: %x\n", GetLastNtError());
+ }
+
+ if (!Desktop)
+ {
+ DPRINT("IntShellHookNotify: No desktop!\n");
+ return;
+ }
+
+ HwndList = UserBuildShellHookHwndList(Desktop);
+ if (HwndList)
+ {
+ HWND* cursor = HwndList;
+
+ for (; *cursor; cursor++)
+ {
+ DPRINT("Sending notify\n");
+ co_IntPostOrSendMessage(*cursor,
+ MsgType,
+ Message,
+ lParam);
+ }
+
+ ExFreePool(HwndList);
+ }
+
+}
+
+/*
+ * Add the window to the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ *
+ * TODO: Validate the window? I'm not sure if sending these messages to
+ * an unsuspecting application that is not your own is a nice thing to do.
+ */
+BOOL IntRegisterShellHookWindow(HWND hWnd)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP Desktop = pti->rpdesk;
+ PSHELL_HOOK_WINDOW Entry;
+
+ DPRINT("IntRegisterShellHookWindow\n");
+
+ /* First deregister the window, so we can be sure it's never twice in the
+ * list.
+ */
+ IntDeRegisterShellHookWindow(hWnd);
+
+ Entry = ExAllocatePoolWithTag(PagedPool,
+ sizeof(SHELL_HOOK_WINDOW),
+ TAG_WINSTA);
+
+ if (!Entry)
+ return FALSE;
+
+ Entry->hWnd = hWnd;
+
+ InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
+
+ return TRUE;
+}
+
+/*
+ * Remove the window from the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ */
+BOOL IntDeRegisterShellHookWindow(HWND hWnd)
+{
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PDESKTOP Desktop = pti->rpdesk;
+ PSHELL_HOOK_WINDOW Current;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ {
+ if (Current->hWnd == hWnd)
+ {
+ RemoveEntryList(&Current->ListEntry);
+ ExFreePool(Current);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static VOID
+IntFreeDesktopHeap(IN OUT PDESKTOP Desktop)
+{
+ if (Desktop->hsectionDesktop != NULL)
+ {
+ ObDereferenceObject(Desktop->hsectionDesktop);
+ Desktop->hsectionDesktop = NULL;
+ }
+}
+/* SYSCALLS *******************************************************************/
+
+/*
+ * NtUserCreateDesktop
+ *
+ * Creates a new desktop.
+ *
+ * Parameters
+ * poaAttribs
+ * Object Attributes.
+ *
+ * lpszDesktopDevice
+ * Name of the device.
+ *
+ * pDeviceMode
+ * Device Mode.
+ *
+ * dwFlags
+ * Interaction flags.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ *
+ * Return Value
+ * If the function succeeds, the return value is a handle to the newly
+ * created desktop. If the specified desktop already exists, the function
+ * succeeds and returns a handle to the existing desktop. When you are
+ * finished using the handle, call the CloseDesktop function to close it.
+ * If the function fails, the return value is NULL.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserCreateDesktop(
+ POBJECT_ATTRIBUTES poa,
+ PUNICODE_STRING lpszDesktopDevice,
+ LPDEVMODEW lpdmw,
+ DWORD dwFlags,
+ ACCESS_MASK dwDesiredAccess)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PTHREADINFO W32Thread;
+ PWINSTATION_OBJECT WinStaObject;
+ PDESKTOP DesktopObject;
+ UNICODE_STRING DesktopName;
+ NTSTATUS Status = STATUS_SUCCESS;
+ HDESK Desktop;
+ CSR_API_MESSAGE Request;
+ PVOID DesktopHeapSystemBase = NULL;
+ SIZE_T DesktopInfoSize;
+ UNICODE_STRING SafeDesktopName;
+ ULONG DummyContext;
+ ULONG_PTR HeapSize = 4 * 1024 * 1024; /* FIXME */
+ HWINSTA hWindowStation = NULL ;
+ PUNICODE_STRING lpszDesktopName = NULL;
+ UNICODE_STRING ClassName, MenuName;
+ LARGE_STRING WindowName;
+ PWND pWnd = NULL;
+ CREATESTRUCTW Cs;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
+
+ _SEH2_TRY
+ {
+ ProbeForRead( poa,
+ sizeof(OBJECT_ATTRIBUTES),
+ 1);
+
+ hWindowStation = poa->RootDirectory;
+ lpszDesktopName = poa->ObjectName;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status =_SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed reading Object Attributes from user space.\n");
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Status = IntValidateWindowStationHandle(
+ hWindowStation,
+ KernelMode,
+ 0, /* FIXME - WINSTA_CREATEDESKTOP */
+ &WinStaObject);
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
+ hWindowStation, lpszDesktopName);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ if(lpszDesktopName != NULL)
+ {
+ Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&SafeDesktopName, NULL);
+ }
+
+ if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+ &SafeDesktopName))
+ {
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ ObDereferenceObject(WinStaObject);
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ RETURN( NULL);
+ }
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ ObDereferenceObject(WinStaObject);
+
+ /*
+ * Try to open already existing desktop
+ */
+
+ DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
+
+ /* Initialize ObjectAttributes for the desktop object */
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DesktopName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ dwDesiredAccess,
+ (PVOID)&DummyContext,
+ (HANDLE*)&Desktop);
+ if (!NT_SUCCESS(Status)) RETURN(NULL);
+ if (Status == STATUS_OBJECT_NAME_EXISTS)
+ {
+ ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
+ RETURN( Desktop);
+ }
+
+ /* Reference the desktop */
+ Status = ObReferenceObjectByHandle(Desktop,
+ 0,
+ ExDesktopObjectType,
+ KernelMode,
+ (PVOID)&DesktopObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) RETURN(NULL);
+
+ DesktopObject->hsectionDesktop = NULL;
+ DesktopObject->pheapDesktop = UserCreateHeap(&DesktopObject->hsectionDesktop,
+ &DesktopHeapSystemBase,
+ HeapSize);
+ if (DesktopObject->pheapDesktop == NULL)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Failed to create desktop heap!\n");
+ RETURN(NULL);
+ }
+
+ DesktopInfoSize = FIELD_OFFSET(DESKTOPINFO,
+ szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);
+
+ DesktopObject->pDeskInfo = RtlAllocateHeap(DesktopObject->pheapDesktop,
+ HEAP_NO_SERIALIZE,
+ DesktopInfoSize);
+
+ if (DesktopObject->pDeskInfo == NULL)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Failed to create the DESKTOP structure!\n");
+ RETURN(NULL);
+ }
+
+ RtlZeroMemory(DesktopObject->pDeskInfo,
+ DesktopInfoSize);
+
+ DesktopObject->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
+ DesktopObject->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
+ RtlCopyMemory(DesktopObject->pDeskInfo->szDesktopName,
+ lpszDesktopName->Buffer,
+ lpszDesktopName->Length);
+
+ /* Initialize some local (to win32k) desktop state. */
+ InitializeListHead(&DesktopObject->PtiList);
+ DesktopObject->ActiveMessageQueue = NULL;
+ ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create desktop handle\n");
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ /*
+ * Create a handle for CSRSS and notify CSRSS for Creating Desktop Window.
+ *
+ * Honestly, I believe this is a cleverly written hack that allowed ReactOS
+ * to function at the beginning of the project by ramroding the GUI into
+ * operation and making the desktop window work from user space.
+ * (jt)
+ */
+ Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
+ Status = CsrInsertObject(Desktop,
+ GENERIC_ALL,
+ (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create desktop handle for CSRSS\n");
+ ZwClose(Desktop);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Status = co_CsrNotify(&Request);
+ if (! NT_SUCCESS(Status))
+ {
+ CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
+ DPRINT1("Failed to notify CSRSS about new desktop\n");
+ ZwClose(Desktop);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ W32Thread = PsGetCurrentThreadWin32Thread();
+
+ if (!W32Thread->rpdesk) IntSetThreadDesktop(DesktopObject,FALSE);
+
+ /*
+ Based on wine/server/window.c in get_desktop_window.
+ */
+
+ ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE])));
+ ClassName.Length = 0;
+ RtlZeroMemory(&MenuName, sizeof(MenuName));
+ RtlZeroMemory(&WindowName, sizeof(WindowName));
+
+ RtlZeroMemory(&Cs, sizeof(Cs));
+ Cs.cx = Cs.cy = 100;
+ Cs.style = WS_POPUP|WS_CLIPCHILDREN;
+ Cs.hInstance = hModClient;
+ Cs.lpszName = (LPCWSTR) &WindowName;
+ Cs.lpszClass = (LPCWSTR) &ClassName;
+
+ pWnd = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName);
+ if (!pWnd)
+ {
+ DPRINT1("Failed to create Message window handle\n");
+ }
+ else
+ {
+ DesktopObject->spwndMessage = pWnd;
+ }
+
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserOpenDesktop
+ *
+ * Opens an existing desktop.
+ *
+ * Parameters
+ * lpszDesktopName
+ * Name of the existing desktop.
+ *
+ * dwFlags
+ * Interaction flags.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ * Return Value
+ * Handle to the desktop or zero on failure.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserOpenDesktop(
+ PUNICODE_STRING lpszDesktopName,
+ DWORD dwFlags,
+ ACCESS_MASK dwDesiredAccess)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HWINSTA WinSta;
+ PWINSTATION_OBJECT WinStaObject;
+ UNICODE_STRING DesktopName;
+ UNICODE_STRING SafeDesktopName;
+ NTSTATUS Status;
+ HDESK Desktop;
+ BOOL Result;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
+
+ /*
+ * Validate the window station handle and compose the fully
+ * qualified desktop name
+ */
+
+ WinSta = UserGetProcessWindowStation();
+ Status = IntValidateWindowStationHandle(
+ WinSta,
+ KernelMode,
+ 0,
+ &WinStaObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta);
+ SetLastNtError(Status);
+ RETURN( 0);
+ }
+
+ if(lpszDesktopName != NULL)
+ {
+ Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+ }
+ else
+ {
+ RtlInitUnicodeString(&SafeDesktopName, NULL);
+ }
+
+ Result = IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+ &SafeDesktopName);
+
+ if (lpszDesktopName)
+ ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
+ ObDereferenceObject(WinStaObject);
+
+
+ if (!Result)
+ {
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ RETURN( 0);
+ }
+
+
+ DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
+
+ /* Initialize ObjectAttributes for the desktop object */
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DesktopName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ KernelMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (HANDLE*)&Desktop);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ ExFreePool(DesktopName.Buffer);
+ RETURN( 0);
+ }
+
+ DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
+ ExFreePool(DesktopName.Buffer);
+
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserOpenInputDesktop
+ *
+ * Opens the input (interactive) desktop.
+ *
+ * Parameters
+ * dwFlags
+ * Interaction flags.
+ *
+ * fInherit
+ * Inheritance option.
+ *
+ * dwDesiredAccess
+ * Requested type of access.
+ *
+ * Return Value
+ * Handle to the input desktop or zero on failure.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserOpenInputDesktop(
+ DWORD dwFlags,
+ BOOL fInherit,
+ ACCESS_MASK dwDesiredAccess)
+{
+ PDESKTOP Object;
+ NTSTATUS Status;
+ HDESK Desktop;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenInputDesktop\n");
+ UserEnterExclusive();
+
+ DPRINT("About to open input desktop\n");
+
+ /* Get a pointer to the desktop object */
+
+ Status = IntValidateDesktopHandle(
+ InputDesktopHandle,
+ UserMode,
+ 0,
+ &Object);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
+ RETURN((HDESK)0);
+ }
+
+ /* Create a new handle to the object */
+
+ Status = ObOpenObjectByPointer(
+ Object,
+ 0,
+ NULL,
+ dwDesiredAccess,
+ ExDesktopObjectType,
+ UserMode,
+ (HANDLE*)&Desktop);
+
+ ObDereferenceObject(Object);
+
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("Successfully opened input desktop\n");
+ RETURN((HDESK)Desktop);
+ }
+
+ SetLastNtError(Status);
+ RETURN((HDESK)0);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserCloseDesktop
+ *
+ * Closes a desktop handle.
+ *
+ * Parameters
+ * hDesktop
+ * Handle to the desktop.
+ *
+ * Return Value
+ * Status
+ *
+ * Remarks
+ * The desktop handle can be created with NtUserCreateDesktop or
+ * NtUserOpenDesktop. This function will fail if any thread in the calling
+ * process is using the specified desktop handle or if the handle refers
+ * to the initial desktop of the calling process.
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserCloseDesktop(HDESK hDesktop)
+{
+ PDESKTOP Object;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCloseDesktop\n");
+ UserEnterExclusive();
+
+ DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
+
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &Object);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ ObDereferenceObject(Object);
+
+ DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
+
+ Status = ZwClose(hDesktop);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+
+
+/*
+ * NtUserPaintDesktop
+ *
+ * The NtUserPaintDesktop function fills the clipping region in the
+ * specified device context with the desktop pattern or wallpaper. The
+ * function is provided primarily for shell desktops.
+ *
+ * Parameters
+ * hDC
+ * Handle to the device context.
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserPaintDesktop(HDC hDC)
+{
+ RECTL Rect;
+ HBRUSH DesktopBrush, PreviousBrush;
+ HWND hWndDesktop;
+ BOOL doPatBlt = TRUE;
+ PWINDOW_OBJECT WndDesktop;
+ int len;
+ COLORREF color_old;
+ UINT align_old;
+ int mode_old;
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+ PWINSTATION_OBJECT WinSta = pti->rpdesk->rpwinstaParent;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserPaintDesktop\n");
+
+ GdiGetClipBox(hDC, &Rect);
+
+ hWndDesktop = IntGetDesktopWindow();
+
+ WndDesktop = UserGetWindowObject(hWndDesktop);
+ if (!WndDesktop)
+ {
+ RETURN(FALSE);
+ }
+
+ DesktopBrush = (HBRUSH)WndDesktop->Wnd->pcls->hbrBackground;
+
+
+ /*
+ * Paint desktop background
+ */
+
+ if (WinSta->hbmWallpaper != NULL)
+ {
+ PWINDOW_OBJECT DeskWin;
+
+ DeskWin = UserGetWindowObject(hWndDesktop);
+
+ if (DeskWin)
+ {
+ SIZE sz;
+ int x, y;
+ HDC hWallpaperDC;
+
+ sz.cx = DeskWin->Wnd->rcWindow.right - DeskWin->Wnd->rcWindow.left;
+ sz.cy = DeskWin->Wnd->rcWindow.bottom - DeskWin->Wnd->rcWindow.top;
+
+ if (WinSta->WallpaperMode == wmStretch ||
+ WinSta->WallpaperMode == wmTile)
+ {
+ x = 0;
+ y = 0;
+ }
+ else
+ {
+ /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */
+ x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
+ y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
+ }
+
+ hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
+ if(hWallpaperDC != NULL)
+ {
+ HBITMAP hOldBitmap;
+
+ /* fill in the area that the bitmap is not going to cover */
+ if (x > 0 || y > 0)
+ {
+ /* FIXME - clip out the bitmap
+ can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);"
+ once we support DSTINVERT */
+ PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectBrush(hDC, PreviousBrush);
+ }
+
+ /*Do not fill the background after it is painted no matter the size of the picture */
+ doPatBlt = FALSE;
+
+ hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, WinSta->hbmWallpaper);
+
+ if (WinSta->WallpaperMode == wmStretch)
+ {
+ if(Rect.right && Rect.bottom)
+ NtGdiStretchBlt(hDC,
+ x,
+ y,
+ sz.cx,
+ sz.cy,
+ hWallpaperDC,
+ 0,
+ 0,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ SRCCOPY,
+ 0);
+
+ }
+ else if (WinSta->WallpaperMode == wmTile)
+ {
+ /* paint the bitmap across the screen then down */
+ for(y = 0; y < Rect.bottom; y += WinSta->cyWallpaper)
+ {
+ for(x = 0; x < Rect.right; x += WinSta->cxWallpaper)
+ {
+ NtGdiBitBlt(hDC,
+ x,
+ y,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ hWallpaperDC,
+ 0,
+ 0,
+ SRCCOPY,
+ 0,
+ 0);
+ }
+ }
+ }
+ else
+ {
+ NtGdiBitBlt(hDC,
+ x,
+ y,
+ WinSta->cxWallpaper,
+ WinSta->cyWallpaper,
+ hWallpaperDC,
+ 0,
+ 0,
+ SRCCOPY,
+ 0,
+ 0);
+ }
+ NtGdiSelectBitmap(hWallpaperDC, hOldBitmap);
+ NtGdiDeleteObjectApp(hWallpaperDC);
+ }
+ }
+ }
+
+ /* Back ground is set to none, clear the screen */
+ if (doPatBlt)
+ {
+ PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectBrush(hDC, PreviousBrush);
+ }
+
+ /*
+ * Display system version on the desktop background
+ */
+
+ if (g_PaintDesktopVersion)
+ {
+ static WCHAR s_wszVersion[256] = {0};
+ RECTL rect;
+
+ if (*s_wszVersion)
+ {
+ len = wcslen(s_wszVersion);
+ }
+ else
+ {
+ len = GetSystemVersionString(s_wszVersion);
+ }
+
+ if (len)
+ {
+ if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
+ {
+ rect.right = UserGetSystemMetrics(SM_CXSCREEN);
+ rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+ }
+
+ color_old = IntGdiSetTextColor(hDC, RGB(255,255,255));
+ align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
+ mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
+
+ GreExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0);
+
+ IntGdiSetBkMode(hDC, mode_old);
+ IntGdiSetTextAlign(hDC, align_old);
+ IntGdiSetTextColor(hDC, color_old);
+ }
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
+/*
+ * NtUserSwitchDesktop
+ *
+ * Sets the current input (interactive) desktop.
+ *
+ * Parameters
+ * hDesktop
+ * Handle to desktop.
+ *
+ * Return Value
+ * Status
+ *
+ * Status
+ * @unimplemented
+ */
+
+BOOL APIENTRY
+NtUserSwitchDesktop(HDESK hDesktop)
+{
+ PDESKTOP DesktopObject;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSwitchDesktop\n");
+
+ DPRINT("About to switch desktop (0x%X)\n", hDesktop);
+
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /*
+ * Don't allow applications switch the desktop if it's locked, unless the caller
+ * is the logon application itself
+ */
+ if((DesktopObject->rpwinstaParent->Flags & WSS_LOCKED) &&
+ LogonProcess != NULL && LogonProcess != PsGetCurrentProcessWin32Process())
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ if(DesktopObject->rpwinstaParent != InputWindowStation)
+ {
+ ObDereferenceObject(DesktopObject);
+ DPRINT1("Switching desktop 0x%x denied because desktop doesn't belong to the interactive winsta!\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /* FIXME: Fail if the process is associated with a secured
+ desktop such as Winlogon or Screen-Saver */
+ /* FIXME: Connect to input device */
+
+ /* Set the active desktop in the desktop's window station. */
+ InputWindowStation->ActiveDesktop = DesktopObject;
+
+ /* Set the global state. */
+ InputDesktop = DesktopObject;
+ InputDesktopHandle = hDesktop;
+
+ ObDereferenceObject(DesktopObject);
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/*
+ * NtUserResolveDesktopForWOW
+ *
+ * Status
+ * @unimplemented
+ */
+
+DWORD APIENTRY
+NtUserResolveDesktopForWOW(DWORD Unknown0)
+{
+ UNIMPLEMENTED
+ return 0;
+}
+
+/*
+ * NtUserGetThreadDesktop
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK APIENTRY
+NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
+{
+ NTSTATUS Status;
+ PETHREAD Thread;
+ PDESKTOP DesktopObject;
+ HDESK Ret, hThreadDesktop;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+ DECLARE_RETURN(HDESK);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserGetThreadDesktop\n");
+
+ if(!dwThreadId)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ if(Thread->ThreadsProcess == PsGetCurrentProcess())
+ {
+ /* just return the handle, we queried the desktop handle of a thread running
+ in the same context */
+ Ret = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk;
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+ }
+
+ /* get the desktop handle and the desktop of the thread */
+ if(!(hThreadDesktop = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk) ||
+ !(DesktopObject = ((PTHREADINFO)Thread->Tcb.Win32Thread)->rpdesk))
+ {
+ ObDereferenceObject(Thread);
+ DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
+ RETURN(NULL);
+ }
+
+ /* we could just use DesktopObject instead of looking up the handle, but latter
+ may be a bit safer (e.g. when the desktop is being destroyed */
+ /* switch into the context of the thread we're trying to get the desktop from,
+ so we can use the handle */
+ KeAttachProcess(&Thread->ThreadsProcess->Pcb);
+ Status = ObReferenceObjectByHandle(hThreadDesktop,
+ GENERIC_ALL,
+ ExDesktopObjectType,
+ UserMode,
+ (PVOID*)&DesktopObject,
+ &HandleInformation);
+ KeDetachProcess();
+
+ /* the handle couldn't be found, there's nothing to get... */
+ if(!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Thread);
+ RETURN(NULL);
+ }
+
+ /* lookup our handle table if we can find a handle to the desktop object,
+ if not, create one */
+ Ret = IntGetDesktopObjectHandle(DesktopObject);
+
+ /* all done, we got a valid handle to the desktop */
+ ObDereferenceObject(DesktopObject);
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+static NTSTATUS
+IntUnmapDesktopView(IN PDESKTOP DesktopObject)
+{
+ PTHREADINFO ti;
+ PPROCESSINFO CurrentWin32Process;
+ PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("DO %p\n");
+
+ CurrentWin32Process = PsGetCurrentProcessWin32Process();
+ PrevLink = &CurrentWin32Process->HeapMappings.Next;
+
+ /* unmap if we're the last thread using the desktop */
+ HeapMapping = *PrevLink;
+ while (HeapMapping != NULL)
+ {
+ if (HeapMapping->KernelMapping == (PVOID)DesktopObject->pheapDesktop)
+ {
+ if (--HeapMapping->Count == 0)
+ {
+ *PrevLink = HeapMapping->Next;
+
+ Status = MmUnmapViewOfSection(PsGetCurrentProcess(),
+ HeapMapping->UserMapping);
+
+ ObDereferenceObject(DesktopObject);
+
+ UserHeapFree(HeapMapping);
+ break;
+ }
+ }
+
+ PrevLink = &HeapMapping->Next;
+ HeapMapping = HeapMapping->Next;
+ }
+
+ ti = GetW32ThreadInfo();
+ if (ti != NULL)
+ {
+ GetWin32ClientInfo()->pDeskInfo = NULL;
+ }
+ GetWin32ClientInfo()->ulClientDelta = 0;
+
+ return Status;
+}
+
+static NTSTATUS
+IntMapDesktopView(IN PDESKTOP DesktopObject)
+{
+ PTHREADINFO ti;
+ PPROCESSINFO CurrentWin32Process;
+ PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
+ PVOID UserBase = NULL;
+ SIZE_T ViewSize = 0;
+ LARGE_INTEGER Offset;
+ NTSTATUS Status;
+
+ CurrentWin32Process = PsGetCurrentProcessWin32Process();
+ PrevLink = &CurrentWin32Process->HeapMappings.Next;
+
+ /* find out if another thread already mapped the desktop heap */
+ HeapMapping = *PrevLink;
+ while (HeapMapping != NULL)
+ {
+ if (HeapMapping->KernelMapping == (PVOID)DesktopObject->pheapDesktop)
+ {
+ HeapMapping->Count++;
+ return STATUS_SUCCESS;
+ }
+
+ PrevLink = &HeapMapping->Next;
+ HeapMapping = HeapMapping->Next;
+ }
+
+ /* we're the first, map the heap */
+ DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject->pheapDesktop);
+ Offset.QuadPart = 0;
+ Status = MmMapViewOfSection(DesktopObject->hsectionDesktop,
+ PsGetCurrentProcess(),
+ &UserBase,
+ 0,
+ 0,
+ &Offset,
+ &ViewSize,
+ ViewUnmap,
+ SEC_NO_CHANGE,
+ PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to map desktop\n");
+ return Status;
+ }
+
+ /* add the mapping */
+ HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING));
+ if (HeapMapping == NULL)
+ {
+ MmUnmapViewOfSection(PsGetCurrentProcess(),
+ UserBase);
+ DPRINT1("UserHeapAlloc() failed!\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ HeapMapping->Next = NULL;
+ HeapMapping->KernelMapping = (PVOID)DesktopObject->pheapDesktop;
+ HeapMapping->UserMapping = UserBase;
+ HeapMapping->Limit = ViewSize;
+ HeapMapping->Count = 1;
+ *PrevLink = HeapMapping;
+
+ ObReferenceObject(DesktopObject);
+
+ /* create a W32THREADINFO structure if not already done, or update it */
+ ti = GetW32ThreadInfo();
+ GetWin32ClientInfo()->ulClientDelta = DesktopHeapGetUserDelta();
+ if (ti != NULL)
+ {
+ if (GetWin32ClientInfo()->pDeskInfo == NULL)
+ {
+ GetWin32ClientInfo()->pDeskInfo =
+ (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo -
+ GetWin32ClientInfo()->ulClientDelta);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+BOOL
+IntSetThreadDesktop(IN PDESKTOP DesktopObject,
+ IN BOOL FreeOnFailure)
+{
+ PDESKTOP OldDesktop;
+ PTHREADINFO W32Thread;
+ NTSTATUS Status;
+ BOOL MapHeap;
+
+ DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject, FreeOnFailure);
+ MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
+ W32Thread = PsGetCurrentThreadWin32Thread();
+
+ if (W32Thread->rpdesk != DesktopObject)
+ {
+ OldDesktop = W32Thread->rpdesk;
+
+ if (!IsListEmpty(&W32Thread->WindowListHead))
+ {
+ DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
+ SetLastWin32Error(ERROR_BUSY);
+ return FALSE;
+ }
+
+ W32Thread->rpdesk = DesktopObject;
+
+ if (MapHeap && DesktopObject != NULL)
+ {
+ Status = IntMapDesktopView(DesktopObject);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+ }
+
+ /* Hack for system threads */
+ if (NtCurrentTeb())
+ {
+ PCLIENTINFO pci = GetWin32ClientInfo();
+ pci->ulClientDelta = DesktopHeapGetUserDelta();
+ if (DesktopObject)
+ {
+ pci->pDeskInfo = (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo - pci->ulClientDelta);
+ }
+ }
+
+ if (OldDesktop != NULL &&
+ !IntCheckProcessDesktopClasses(OldDesktop,
+ FreeOnFailure))
+ {
+ DPRINT1("Failed to move process classes to shared heap!\n");
+
+ /* failed to move desktop classes to the shared heap,
+ unmap the view and return the error */
+ if (MapHeap && DesktopObject != NULL)
+ IntUnmapDesktopView(DesktopObject);
+
+ return FALSE;
+ }
+
+ /* Remove the thread from the old desktop's list */
+ RemoveEntryList(&W32Thread->PtiLink);
+
+ if (DesktopObject != NULL)
+ {
+ ObReferenceObject(DesktopObject);
+ /* Insert into new desktop's list */
+ InsertTailList(&DesktopObject->PtiList, &W32Thread->PtiLink);
+ }
+
+ if (OldDesktop != NULL)
+ {
+ if (MapHeap)
+ {
+ IntUnmapDesktopView(OldDesktop);
+ }
+
+ ObDereferenceObject(OldDesktop);
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * NtUserSetThreadDesktop
+ *
+ * Status
+ * @implemented
+ */
+
+BOOL APIENTRY
+NtUserSetThreadDesktop(HDESK hDesktop)
+{
+ PDESKTOP DesktopObject;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSetThreadDesktop\n");
+
+ /* Validate the new desktop. */
+ Status = IntValidateDesktopHandle(
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
+ RETURN(FALSE);
+ }
+
+ /* FIXME: Should check here to see if the thread has any windows. */
+
+ if (!IntSetThreadDesktop(DesktopObject,
+ FALSE))
+ {
+ RETURN(FALSE);
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/* EOF */
--- /dev/null
- safeHMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * listSize);
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Monitor support
+ * FILE: subsys/win32k/ntuser/monitor.c
+ * PROGRAMER: Anich Gregor (blight@blight.eu.org)
+ * REVISION HISTORY:
+ * 26-02-2004 Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <win32k.h>
+
+/* FIXME: find include file for these */
+#define MONITORINFOF_PRIMARY 1
+#define MONITOR_DEFAULTTONULL 0
+#define MONITOR_DEFAULTTOPRIMARY 1
+#define MONITOR_DEFAULTTONEAREST 2
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+/* list of monitors */
+static PMONITOR gMonitorList = NULL;
+
+/* INITALIZATION FUNCTIONS ****************************************************/
+
+NTSTATUS
+InitMonitorImpl()
+{
+ DPRINT("Initializing monitor implementation...\n");
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CleanupMonitorImpl()
+{
+ DPRINT("Cleaning up monitor implementation...\n");
+ /* FIXME: Destroy monitor objects? */
+
+ return STATUS_SUCCESS;
+}
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef ABS
+# define ABS(a) ((a) < (0) ? (-(a)) : (a))
+#endif
+
+/* IntCreateMonitorObject
+ *
+ * Creates a MONITOR
+ *
+ * Return value
+ * If the function succeeds a pointer to a MONITOR is returned. On failure
+ * NULL is returned.
+ */
+static
+PMONITOR
+IntCreateMonitorObject()
+{
+ HANDLE Handle;
+ PMONITOR Monitor;
+
+ Monitor = UserCreateObject(gHandleTable, NULL, &Handle, otMonitor, sizeof (MONITOR));
+ if (Monitor == NULL)
+ {
+ return NULL;
+ }
+
+ ExInitializeFastMutex(&Monitor->Lock);
+
+ return Monitor;
+}
+
+/* IntDestroyMonitorObject
+ *
+ * Destroys a MONITOR
+ * You have to be the owner of the monitors lock to safely destroy it.
+ *
+ * Arguments
+ *
+ * pMonitor
+ * Pointer to the MONITOR which shall be deleted
+ */
+static
+void
+IntDestroyMonitorObject(IN PMONITOR pMonitor)
+{
+ RtlFreeUnicodeString(&pMonitor->DeviceName);
+ UserDereferenceObject(pMonitor);
+}
+
+
+PMONITOR FASTCALL
+UserGetMonitorObject(IN HMONITOR hMonitor)
+{
+ PMONITOR Monitor;
+
+ if (!hMonitor)
+ {
+ SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);
+ return NULL;
+ }
+
+
+ Monitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor);
+ if (!Monitor)
+ {
+ SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);
+ return NULL;
+ }
+
+ ASSERT(Monitor->head.cLockObj >= 0);
+
+ return Monitor;
+}
+
+
+/* IntAttachMonitor
+ *
+ * Creates a new MONITOR and appends it to the list of monitors.
+ *
+ * Arguments
+ *
+ * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
+ * DisplayNumber Display Number (starting with 0)
+ *
+ * Return value
+ * Returns a NTSTATUS
+ */
+NTSTATUS
+IntAttachMonitor(IN PDEVOBJ *pGdiDevice,
+ IN ULONG DisplayNumber)
+{
+ PMONITOR Monitor;
+ WCHAR Buffer[CCHDEVICENAME];
+
+ DPRINT("Attaching monitor...\n");
+
+ /* create new monitor object */
+ Monitor = IntCreateMonitorObject();
+ if (Monitor == NULL)
+ {
+ DPRINT("Couldnt create monitor object\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ _snwprintf(Buffer, CCHDEVICENAME, L"\\\\.\\DISPLAY%d", DisplayNumber + 1);
+ if (!RtlCreateUnicodeString(&Monitor->DeviceName, Buffer))
+ {
+ DPRINT("Couldn't duplicate monitor name!\n");
+ UserDereferenceObject(Monitor);
+ UserDeleteObject(UserHMGetHandle(Monitor), otMonitor);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Monitor->GdiDevice = pGdiDevice;
+ Monitor->rcMonitor.left = 0;
+ Monitor->rcMonitor.top = 0;
+ Monitor->rcMonitor.right = Monitor->rcMonitor.left + pGdiDevice->gdiinfo.ulHorzRes;
+ Monitor->rcMonitor.bottom = Monitor->rcMonitor.top + pGdiDevice->gdiinfo.ulVertRes;
+ Monitor->rcWork = Monitor->rcMonitor;
+ Monitor->cWndStack = 0;
+
+ Monitor->hrgnMonitor = IntSysCreateRectRgnIndirect( &Monitor->rcMonitor );
+
+ IntGdiSetRegionOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);
+
+ if (gMonitorList == NULL)
+ {
+ DPRINT("Primary monitor is beeing attached\n");
+ Monitor->IsPrimary = TRUE;
+ gMonitorList = Monitor;
+ }
+ else
+ {
+ PMONITOR p;
+ DPRINT("Additional monitor is beeing attached\n");
+ for (p = gMonitorList; p->Next != NULL; p = p->Next)
+ {
+ p->Next = Monitor;
+ }
+ Monitor->Prev = p;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* IntDetachMonitor
+ *
+ * Deletes a MONITOR and removes it from the list of monitors.
+ *
+ * Arguments
+ *
+ * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
+ *
+ * Return value
+ * Returns a NTSTATUS
+ */
+NTSTATUS
+IntDetachMonitor(IN PDEVOBJ *pGdiDevice)
+{
+ PMONITOR Monitor;
+
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ if (Monitor->GdiDevice == pGdiDevice)
+ break;
+ }
+
+ if (Monitor == NULL)
+ {
+ /* no monitor for given device found */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (Monitor->IsPrimary && (Monitor->Next != NULL || Monitor->Prev != NULL))
+ {
+ PMONITOR NewPrimaryMonitor = (Monitor->Prev != NULL) ? (Monitor->Prev) : (Monitor->Next);
+
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor->Lock);
+ NewPrimaryMonitor->IsPrimary = TRUE;
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor->Lock);
+ }
+
+ if (gMonitorList == Monitor)
+ {
+ gMonitorList = Monitor->Next;
+ if (Monitor->Next != NULL)
+ Monitor->Next->Prev = NULL;
+ }
+ else
+ {
+ Monitor->Prev->Next = Monitor->Next;
+ if (Monitor->Next != NULL)
+ Monitor->Next->Prev = Monitor->Prev;
+ }
+
+ if (Monitor->hrgnMonitor)
+ REGION_FreeRgnByHandle(Monitor->hrgnMonitor);
+
+ IntDestroyMonitorObject(Monitor);
+
+ return STATUS_SUCCESS;
+}
+
+/* IntGetPrimaryMonitor
+ *
+ * Returns a PMONITOR for the primary monitor
+ *
+ * Return value
+ * PMONITOR
+ */
+PMONITOR
+FASTCALL
+IntGetPrimaryMonitor()
+{
+ PMONITOR Monitor;
+
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ /* FIXME: I guess locking the monitor is not neccessary to read 1 int */
+ if (Monitor->IsPrimary)
+ break;
+ }
+
+ return Monitor;
+}
+
+/* IntGetMonitorsFromRect
+ *
+ * Returns a list of monitor handles/rectangles. The rectangles in the list are
+ * the areas of intersection with the monitors.
+ *
+ * Arguments
+ *
+ * pRect
+ * Rectangle in desktop coordinates. If this is NULL all monitors are
+ * returned and the rect list is filled with the sizes of the monitors.
+ *
+ * hMonitorList
+ * Pointer to an array of HMONITOR which is filled with monitor handles.
+ * Can be NULL
+ *
+ * monitorRectList
+ * Pointer to an array of RECT which is filled with intersection rects in
+ * desktop coordinates.
+ * Can be NULL, will be ignored if no intersecting monitor is found and
+ * flags is MONITOR_DEFAULTTONEAREST
+ *
+ * listSize
+ * Size of the hMonitorList and monitorRectList arguments. If this is zero
+ * hMonitorList and monitorRectList are ignored.
+ *
+ * flags
+ * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
+ *
+ * Returns
+ * The number of monitors which intersect the specified region.
+ */
+static
+UINT
+IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
+ OPTIONAL OUT HMONITOR *hMonitorList,
+ OPTIONAL OUT PRECTL monitorRectList,
+ OPTIONAL IN DWORD listSize,
+ OPTIONAL IN DWORD flags)
+{
+ PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL;
+ UINT iCount = 0;
+ LONG iNearestDistanceX = 0x7fffffff, iNearestDistanceY = 0x7fffffff;
+
+ /* find monitors which intersect the rectangle */
+ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
+ {
+ RECTL MonitorRect, IntersectionRect;
+
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock);
+ MonitorRect = Monitor->rcMonitor;
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock);
+
+ DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
+ MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);
+
+ if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary)
+ {
+ PrimaryMonitor = Monitor;
+ }
+
+ if (pRect != NULL)
+ {
+ BOOL intersects = TRUE;
+
+ /* check if the rect intersects the monitor */
+ if ((pRect->right < MonitorRect.left) || (pRect->left > MonitorRect.right) ||
+ (pRect->bottom < MonitorRect.top) || (pRect->top > MonitorRect.bottom))
+ {
+ intersects = FALSE;
+ }
+
+ if (flags == MONITOR_DEFAULTTONEAREST && !intersects)
+ {
+ INT distanceX, distanceY;
+
+ distanceX = MIN(ABS(MonitorRect.left - pRect->right),
+ ABS(pRect->left - MonitorRect.right));
+ distanceY = MIN(ABS(MonitorRect.top - pRect->bottom),
+ ABS(pRect->top - MonitorRect.bottom));
+
+ if (((distanceX < iNearestDistanceX) && (distanceY <= iNearestDistanceY)) ||
+ ((distanceX <= iNearestDistanceX) && (distanceY < iNearestDistanceY)))
+ {
+ iNearestDistanceX = distanceX;
+ iNearestDistanceY = distanceY;
+ NearestMonitor = Monitor;
+ }
+ }
+
+ if (!intersects)
+ continue;
+
+ /* calculate intersection */
+ IntersectionRect.left = MAX(MonitorRect.left, pRect->left);
+ IntersectionRect.top = MAX(MonitorRect.top, pRect->top);
+ IntersectionRect.right = MIN(MonitorRect.right, pRect->right);
+ IntersectionRect.bottom = MIN(MonitorRect.bottom, pRect->bottom);
+ }
+ else
+ {
+ IntersectionRect = MonitorRect;
+ }
+
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(Monitor);
+ if (monitorRectList != NULL)
+ monitorRectList[iCount] = IntersectionRect;
+ }
+ iCount++;
+ }
+
+ if (iCount == 0 && flags == MONITOR_DEFAULTTONEAREST)
+ {
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(NearestMonitor);
+ }
+ iCount++;
+ }
+ else if (iCount == 0 && flags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ if (iCount < listSize)
+ {
+ if (hMonitorList != NULL)
+ hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor);
+ }
+ iCount++;
+ }
+ return iCount;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/* NtUserEnumDisplayMonitors
+ *
+ * Enumerates display monitors which intersect the given HDC/cliprect
+ *
+ * Arguments
+ *
+ * hDC
+ * Handle to a DC for which to enum intersecting monitors. If this is NULL
+ * it returns all monitors which are part of the current virtual screen.
+ *
+ * pRect
+ * Clipping rectangle with coordinate system origin at the DCs origin if the
+ * given HDC is not NULL or in virtual screen coordinated if it is NULL.
+ * Can be NULL
+ *
+ * hMonitorList
+ * Pointer to an array of HMONITOR which is filled with monitor handles.
+ * Can be NULL
+ *
+ * monitorRectList
+ * Pointer to an array of RECT which is filled with intersection rectangles.
+ * Can be NULL
+ *
+ * listSize
+ * Size of the hMonitorList and monitorRectList arguments. If this is zero
+ * hMonitorList and monitorRectList are ignored.
+ *
+ * Returns
+ * The number of monitors which intersect the specified region or -1 on failure.
+ */
+INT
+APIENTRY
+NtUserEnumDisplayMonitors(
+ OPTIONAL IN HDC hDC,
+ OPTIONAL IN LPCRECTL pRect,
+ OPTIONAL OUT HMONITOR *hMonitorList,
+ OPTIONAL OUT PRECTL monitorRectList,
+ OPTIONAL IN DWORD listSize)
+{
+ INT numMonitors, i;
+ HMONITOR *safeHMonitorList = NULL;
+ PRECTL safeRectList = NULL;
+ RECTL rect, *myRect;
+ RECTL dcRect;
+ NTSTATUS status;
+
+ /* get rect */
+ if (pRect != NULL)
+ {
+ status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
+ if (!NT_SUCCESS(status))
+ {
+ DPRINT("MmCopyFromCaller() failed!\n");
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+
+ if (hDC != NULL)
+ {
+ PDC dc;
+ HRGN dcVisRgn;
+ INT regionType;
+
+ /* get visible region bounding rect */
+ dc = DC_LockDc(hDC);
+ if (dc == NULL)
+ {
+ DPRINT("DC_LockDc() failed!\n");
+ /* FIXME: setlasterror? */
+ return -1;
+ }
+ dcVisRgn = dc->prgnVis->BaseObject.hHmgr;
+ DC_UnlockDc(dc);
+
+ regionType = NtGdiGetRgnBox(dcVisRgn, &dcRect);
+ if (regionType == 0)
+ {
+ DPRINT("NtGdiGetRgnBox() failed!\n");
+ return -1;
+ }
+ if (regionType == NULLREGION)
+ return 0;
+ if (regionType == COMPLEXREGION)
+ { /* TODO: warning */
+ }
+
+ /* if hDC and pRect are given the area of interest is pRect with
+ coordinate origin at the DC position */
+ if (pRect != NULL)
+ {
+ rect.left += dcRect.left;
+ rect.right += dcRect.left;
+ rect.top += dcRect.top;
+ rect.bottom += dcRect.top;
+ }
+ /* if hDC is given and pRect is not the area of interest is the
+ bounding rect of hDC */
+ else
+ {
+ rect = dcRect;
+ }
+ }
+
+ if (hDC == NULL && pRect == NULL)
+ myRect = NULL;
+ else
+ myRect = ▭
+
+ /* find intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(myRect, NULL, NULL, 0, 0);
+ if (numMonitors == 0 || listSize == 0 ||
+ (hMonitorList == NULL && monitorRectList == NULL))
+ {
+ DPRINT("numMonitors = %d\n", numMonitors);
+ return numMonitors;
+ }
+
+ if (hMonitorList != NULL && listSize != 0)
+ {
- safeRectList = ExAllocatePool(PagedPool, sizeof (RECT) * listSize);
++ safeHMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * listSize, USERTAG_MONITORRECTS);
+ if (safeHMonitorList == NULL)
+ {
+ /* FIXME: SetLastWin32Error? */
+ return -1;
+ }
+ }
+ if (monitorRectList != NULL && listSize != 0)
+ {
- ExFreePool(safeHMonitorList);
++ safeRectList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * listSize, USERTAG_MONITORRECTS);
+ if (safeRectList == NULL)
+ {
- ExFreePool(safeRectList);
++ ExFreePoolWithTag(safeHMonitorList, USERTAG_MONITORRECTS);
+ /* FIXME: SetLastWin32Error? */
+ return -1;
+ }
+ }
+
+ /* get intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(myRect, safeHMonitorList, safeRectList,
+ listSize, 0 );
+
+ if (hDC != NULL && pRect != NULL && safeRectList != NULL)
+ for (i = 0; i < numMonitors; i++)
+ {
+ safeRectList[i].left -= dcRect.left;
+ safeRectList[i].right -= dcRect.left;
+ safeRectList[i].top -= dcRect.top;
+ safeRectList[i].bottom -= dcRect.top;
+ }
+
+ /* output result */
+ if (hMonitorList != NULL && listSize != 0)
+ {
+ status = MmCopyToCaller(hMonitorList, safeHMonitorList, sizeof (HMONITOR) * listSize);
+ ExFreePool(safeHMonitorList);
+ if (!NT_SUCCESS(status))
+ {
- ExFreePool(safeRectList);
++ ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS);
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+ if (monitorRectList != NULL && listSize != 0)
+ {
+ status = MmCopyToCaller(monitorRectList, safeRectList, sizeof (RECT) * listSize);
- hMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * numMonitors);
++ ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS);
+ if (!NT_SUCCESS(status))
+ {
+ SetLastNtError(status);
+ return -1;
+ }
+ }
+
+ return numMonitors;
+}
+
+/* NtUserGetMonitorInfo
+ *
+ * Retrieves information about a given monitor
+ *
+ * Arguments
+ *
+ * hMonitor
+ * Handle to a monitor for which to get information
+ *
+ * pMonitorInfo
+ * Pointer to a MONITORINFO struct which is filled with the information.
+ * The cbSize member must be set to sizeof(MONITORINFO) or
+ * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
+ * from MONITORINFO will be filled.
+ *
+ * pDevice
+ * Pointer to a UNICODE_STRING which will recieve the device's name. The
+ * length should be CCHDEVICENAME
+ * Can be NULL
+ *
+ * Return value
+ * TRUE on success; FALSE on failure (calls SetLastNtError())
+ *
+ */
+BOOL
+APIENTRY
+NtUserGetMonitorInfo(
+ IN HMONITOR hMonitor,
+ OUT LPMONITORINFO pMonitorInfo)
+{
+ PMONITOR Monitor;
+ MONITORINFOEXW MonitorInfo;
+ NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserGetMonitorInfo\n");
+ UserEnterShared();
+
+ /* get monitor object */
+ if (!(Monitor = UserGetMonitorObject(hMonitor)))
+ {
+ DPRINT("Couldnt find monitor 0x%lx\n", hMonitor);
+ RETURN(FALSE);
+ }
+
+ if(pMonitorInfo == NULL)
+ {
+ SetLastNtError(STATUS_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+
+ /* get size of pMonitorInfo */
+ Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfo->cbSize, sizeof (MonitorInfo.cbSize));
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+ if ((MonitorInfo.cbSize != sizeof (MONITORINFO)) &&
+ (MonitorInfo.cbSize != sizeof (MONITORINFOEXW)))
+ {
+ SetLastNtError(STATUS_INVALID_PARAMETER);
+ RETURN(FALSE);
+ }
+
+ /* fill monitor info */
+ MonitorInfo.rcMonitor = Monitor->rcMonitor;
+ MonitorInfo.rcWork = Monitor->rcWork;
+ MonitorInfo.dwFlags = 0;
+
+ if (Monitor->IsPrimary)
+ MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
+
+ /* fill device name */
+ if (MonitorInfo.cbSize == sizeof (MONITORINFOEXW))
+ {
+ WCHAR nul = L'\0';
+ INT len = Monitor->DeviceName.Length;
+ if (len >= CCHDEVICENAME * sizeof (WCHAR))
+ len = (CCHDEVICENAME - 1) * sizeof (WCHAR);
+
+ memcpy(MonitorInfo.szDevice, Monitor->DeviceName.Buffer, len);
+ memcpy(MonitorInfo.szDevice + (len / sizeof (WCHAR)), &nul, sizeof (WCHAR));
+ }
+
+ /* output data */
+ Status = MmCopyToCaller(pMonitorInfo, &MonitorInfo, MonitorInfo.cbSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
+ SetLastNtError(Status);
+ RETURN(FALSE);
+ }
+
+ DPRINT("GetMonitorInfo: success\n");
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+/* NtUserMonitorFromPoint
+ *
+ * Returns a handle to the monitor containing the given point.
+ *
+ * Arguments
+ *
+ * point
+ * Point for which to find monitor
+ *
+ * dwFlags
+ * Specifies the behaviour if the point isn't on any of the monitors.
+ *
+ * Return value
+ * If the point is found a handle to the monitor is returned; if not the
+ * return value depends on dwFlags
+ */
+HMONITOR
+APIENTRY
+NtUserMonitorFromPoint(
+ IN POINT point,
+ IN DWORD dwFlags)
+{
+ INT NumMonitors;
+ RECTL InRect;
+ HMONITOR hMonitor = NULL;
+
+ /* fill inRect */
+ InRect.left = InRect.right = point.x;
+ InRect.top = InRect.bottom = point.y;
+
+ /* find intersecting monitor */
+ NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, 0);
+ if (NumMonitors < 0)
+ {
+ return (HMONITOR)NULL;
+ }
+
+ if (hMonitor == NULL)
+ {
+ if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ PMONITOR MonitorObj = IntGetPrimaryMonitor();
+ if (MonitorObj)
+ hMonitor = UserHMGetHandle(MonitorObj);
+ }
+ else if (dwFlags == MONITOR_DEFAULTTONEAREST)
+ {
+ NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL,
+ 1, MONITOR_DEFAULTTONEAREST);
+ /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
+ }
+ /* else flag is DEFAULTTONULL */
+ }
+
+ return hMonitor;
+}
+
+/* NtUserMonitorFromRect
+ *
+ * Returns a handle to the monitor having the largest intersection with a
+ * given rectangle
+ *
+ * Arguments
+ *
+ * pRect
+ * Pointer to a RECT for which to find monitor
+ *
+ * dwFlags
+ * Specifies the behaviour if no monitor intersects the given rect
+ *
+ * Return value
+ * If a monitor intersects the rect a handle to it is returned; if not the
+ * return value depends on dwFlags
+ */
+HMONITOR
+APIENTRY
+NtUserMonitorFromRect(
+ IN LPCRECTL pRect,
+ IN DWORD dwFlags)
+{
+ INT numMonitors, iLargestArea = -1, i;
+ PRECTL rectList;
+ HMONITOR *hMonitorList;
+ HMONITOR hMonitor = NULL;
+ RECTL rect;
+ NTSTATUS status;
+
+ /* get rect */
+ status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
+ if (!NT_SUCCESS(status))
+ {
+ SetLastNtError(status);
+ return (HMONITOR)NULL;
+ }
+
+ /* find intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(&rect, NULL, NULL, 0, 0);
+ if (numMonitors < 0)
+ {
+ return (HMONITOR)NULL;
+ }
+
+ if (numMonitors == 0)
+ {
+ if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
+ {
+ PMONITOR monitorObj = IntGetPrimaryMonitor();
+ if (monitorObj)
+ return UserHMGetHandle(monitorObj);
+ }
+ else if (dwFlags == MONITOR_DEFAULTTONEAREST)
+ {
+ numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL,
+ 1, MONITOR_DEFAULTTONEAREST);
+ if (numMonitors <= 0)
+ {
+ /* error? */
+ return (HMONITOR)NULL;
+ }
+
+ if (numMonitors > 0)
+ return hMonitor;
+ }
+ /* else flag is DEFAULTTONULL */
+ return (HMONITOR)NULL;
+ }
+
- rectList = ExAllocatePool(PagedPool, sizeof (RECT) * numMonitors);
++ hMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * numMonitors, USERTAG_MONITORRECTS);
+ if (hMonitorList == NULL)
+ {
+ /* FIXME: SetLastWin32Error? */
+ return (HMONITOR)NULL;
+ }
- ExFreePool(hMonitorList);
++ rectList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * numMonitors, USERTAG_MONITORRECTS);
+ if (rectList == NULL)
+ {
- ExFreePool(hMonitorList);
- ExFreePool(rectList);
++ ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS);
+ /* FIXME: SetLastWin32Error? */
+ return (HMONITOR)NULL;
+ }
+
+ /* get intersecting monitors */
+ numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList,
+ numMonitors, 0);
+ if (numMonitors <= 0)
+ {
- ExFreePool(hMonitorList);
- ExFreePool(rectList);
++ ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS);
++ ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS);
+ return (HMONITOR)NULL;
+ }
+
+ /* find largest intersection */
+ for (i = 0; i < numMonitors; i++)
+ {
+ INT area = (rectList[i].right - rectList[i].left) *
+ (rectList[i].bottom - rectList[i].top);
+ if (area > iLargestArea)
+ {
+ hMonitor = hMonitorList[i];
+ }
+ }
+
++ ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS);
++ ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS);
+
+ return hMonitor;
+}
+
+
+HMONITOR
+APIENTRY
+NtUserMonitorFromWindow(
+ IN HWND hWnd,
+ IN DWORD dwFlags)
+{
+ PWINDOW_OBJECT Window;
+ HMONITOR hMonitor = NULL;
+ RECTL Rect;
+ DECLARE_RETURN(HMONITOR);
+
+ DPRINT("Enter NtUserMonitorFromWindow\n");
+ UserEnterShared();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ if (dwFlags == MONITOR_DEFAULTTONULL)
+ {
+ RETURN(hMonitor);
+ }
+ IntGetMonitorsFromRect(NULL, &hMonitor, NULL, 1, dwFlags);
+ RETURN(hMonitor);
+ }
+
+ if (!Window->Wnd)
+ RETURN(hMonitor);
+
+ Rect.left = Rect.right = Window->Wnd->rcWindow.left;
+ Rect.top = Rect.bottom = Window->Wnd->rcWindow.bottom;
+
+ IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
+
+ RETURN(hMonitor);
+
+CLEANUP:
+ DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
--- /dev/null
- PDC_ATTR pdcattr;
+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <win32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+static const RGBQUAD EGAColorsQuads[16] = {
+/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x80, 0x00 },
+ { 0x00, 0x80, 0x00, 0x00 },
+ { 0x00, 0x80, 0x80, 0x00 },
+ { 0x80, 0x00, 0x00, 0x00 },
+ { 0x80, 0x00, 0x80, 0x00 },
+ { 0x80, 0x80, 0x00, 0x00 },
+ { 0x80, 0x80, 0x80, 0x00 },
+ { 0xc0, 0xc0, 0xc0, 0x00 },
+ { 0x00, 0x00, 0xff, 0x00 },
+ { 0x00, 0xff, 0x00, 0x00 },
+ { 0x00, 0xff, 0xff, 0x00 },
+ { 0xff, 0x00, 0x00, 0x00 },
+ { 0xff, 0x00, 0xff, 0x00 },
+ { 0xff, 0xff, 0x00, 0x00 },
+ { 0xff, 0xff, 0xff, 0x00 }
+};
+
+static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
+/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x80, 0x00 },
+ { 0x00, 0x80, 0x00, 0x00 },
+ { 0x00, 0x80, 0x80, 0x00 },
+ { 0x80, 0x00, 0x00, 0x00 },
+ { 0x80, 0x00, 0x80, 0x00 },
+ { 0x80, 0x80, 0x00, 0x00 },
+ { 0xc0, 0xc0, 0xc0, 0x00 },
+ { 0xc0, 0xdc, 0xc0, 0x00 },
+ { 0xf0, 0xca, 0xa6, 0x00 },
+ { 0xf0, 0xfb, 0xff, 0x00 },
+ { 0xa4, 0xa0, 0xa0, 0x00 },
+ { 0x80, 0x80, 0x80, 0x00 },
+ { 0x00, 0x00, 0xf0, 0x00 },
+ { 0x00, 0xff, 0x00, 0x00 },
+ { 0x00, 0xff, 0xff, 0x00 },
+ { 0xff, 0x00, 0x00, 0x00 },
+ { 0xff, 0x00, 0xff, 0x00 },
+ { 0xff, 0xff, 0x00, 0x00 },
+ { 0xff, 0xff, 0xff, 0x00 }
+};
+
+
+UINT
+APIENTRY
+IntSetDIBColorTable(
+ HDC hDC,
+ UINT StartIndex,
+ UINT Entries,
+ CONST RGBQUAD *Colors)
+{
+ PDC dc;
+ PSURFACE psurf;
+ PPALETTE PalGDI;
+ UINT Index;
<