From: Cameron Gutman Date: Sun, 12 Feb 2012 04:59:51 +0000 (+0000) Subject: [USB] X-Git-Tag: backups/c++-bringup@60583~503 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=022f4b2ce569305456ad2588a78ba88fe7694e1b [USB] - We proudly merge the first charge of the usb-bringup branch. We do want to stress hardware support is still under heavy development and testing in real hardware is experimental - Merge the Human Interface Device Stack(HID) which is used for mice / keyboards and other devices which use the USB interface, consisting of hidusb, hidparse, hidclass, mouhid, kbdhid - Merge the composite driver, supports USB composite devices, laid out in usbccgp - Merge the generic hub driver, which supports the USB root hub and in future USB hubs. Driver is usbhub - Merge the Open Host Controller Interface driver (ohci) - Merge the Enhanced Host Controller Interface driver (ehci) - Merge the many fixes in other areas of ReactOS needed for USB to work (ntoskrnl, pci, inf, umpnpmgr, usetup) - Special thanks goes the Haiku team, whose excellent code has provided a great base for the development of the new ReactOS USB / HID stack - The development of the USB stack has shown the great potential when ReactOS developers team up together to achieve a common goal. The involved developers are here, listed alphabetically: Alex Ionescu Amine Khaldi Cameron Gutman Johannes Anderwald Michel Martin Thomas Faber Thomas Lotz(Haiku) Let's start the ReactOS revolution svn path=/trunk/; revision=55555 --- 022f4b2ce569305456ad2588a78ba88fe7694e1b diff --cc reactos/boot/bootdata/packages/reactos.dff index 912a1c72b74,00000000000,512ead158e9..512ead158e9 mode 100644,000000,100644..100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@@@ -1,893 -1,0 -1,890 +1,890 @@@@ + ; 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\extrac32\extrac32.exe 1 + base\applications\findstr\findstr.exe 1 + base\applications\fontview\fontview.exe 1 + base\applications\iexplore\iexplore.exe 1 + base\applications\games\solitaire\sol.exe 1 + base\applications\games\spider\spider.exe 1 + base\applications\games\winmine\winmine.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\mscutils\devmgmt\devmgmt.exe 1 + base\applications\mscutils\eventvwr\eventvwr.exe 1 + base\applications\mscutils\servman\servman.exe 1 + base\applications\mspaint\mspaint.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\finger\finger.exe 1 + base\applications\network\ftp\ftp.exe 1 + base\applications\network\ipconfig\ipconfig.exe 1 + base\applications\network\net\net.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\route\route.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\network\wlanconf\wlanconf.exe 1 + base\applications\notepad\notepad.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\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\svchost\svchost.exe 1 + base\services\tcpsvcs\tcpsvcs.exe 1 + base\services\tcpsvcs\quotes 5 + base\services\telnetd\telnetd.exe 1 + base\services\thmsvc\thmsvc.exe 1 + base\services\umpnpmgr\umpnpmgr.exe 1 + base\services\wlansvc\wlansvc.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 optional + base\shell\explorer\explorer-cfg-template.xml 4 optional + base\shell\explorer\notifyhook\notifyhook.dll 1 optional + base\shell\explorer-new\explorer_new.exe 4 optional + + base\system\autochk\autochk.exe 1 + base\system\bootok\bootok.exe 1 + base\system\diskpart\diskpart.exe 1 + base\system\expand\expand.exe 1 + base\system\subst\subst.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\smss\smss.exe 1 + base\system\smss2\smss2.exe 1 + base\system\userinit\userinit.exe 1 + base\system\winlogon\winlogon.exe 1 + + ; Dynamic Link Libraries + dll\3rdparty\dxtn\dxtn.dll 1 optional + dll\3rdparty\libjpeg\libjpeg.dll 1 + dll\3rdparty\libpng\libpng.dll 1 + dll\3rdparty\libtiff\libtiff.dll 1 + dll\3rdparty\libxslt\libxslt.dll 1 + dll\3rdparty\mesa32\mesa32.dll 1 + + 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\inetcpl\inetcpl.cpl 1 + dll\cpl\intl\intl.cpl 1 + dll\cpl\joy\joy.cpl 1 + ;dll\cpl\liccpa\liccpa.cpl 1 + dll\cpl\main\main.cpl 1 + dll\cpl\mmsys\mmsys.cpl 1 + dll\cpl\ncpa\ncpa.cpl 1 + ;dll\cpl\odbccp32\odbccp32.cpl 1 + dll\cpl\powercfg\powercfg.cpl 1 + dll\cpl\sysdm\sysdm.cpl 1 + ;dll\cpl\telephon\telephon.cpl 1 + dll\cpl\timedate\timedate.cpl 1 + ;dll\cpl\usrmgr\usrmgr.cpl 1 + + dll\directx\amstream\amstream.dll 1 + ;dll\directx\bdaplgin\bdaplgin.ax 1 + dll\directx\d3d8thk\d3d8thk.dll 1 + dll\directx\devenum\devenum.dll 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\ksproxy\ksproxy.ax 1 + dll\directx\ksuser\ksuser.dll 1 + dll\directx\msdmo\msdmo.dll 1 + ;dll\directx\msdvbnp\msdvbnp.ax 1 + ;dll\directx\msvidctl\msvidctl.dll 1 + dll\directx\qedit\qedit.dll 1 + dll\directx\quartz\quartz.dll 1 + dll\directx\wine\ddraw\ddraw.dll 1 + dll\directx\wine\d3d8\d3d8.dll 1 + dll\directx\wine\d3d9\d3d9.dll 1 + dll\directx\wine\wined3d\wined3d.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\kbdbe\kbdbe.dll 1 + dll\keyboard\kbdbga\kbdbga.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\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\kbdgr\kbdgr.dll 1 + dll\keyboard\kbdgrist\kbdgrist.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\kbdko\kbdko.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\kbdpl\kbdpl.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\ntdll\ntdll.dll 1 + + dll\win32\acledit\acledit.dll 1 + dll\win32\aclui\aclui.dll 1 + dll\win32\activeds\activeds.dll 1 + dll\win32\actxprxy\actxprxy.dll 1 + dll\win32\advapi32\advapi32.dll 1 + dll\win32\advpack\advpack.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\devmgr\devmgr.dll 1 + dll\win32\dhcpcsvc\dhcpcsvc.dll 1 + dll\win32\dnsapi\dnsapi.dll 1 + dll\win32\dwmapi\dwmapi.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\lpk\lpk.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\msports\msports.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\netevent\netevent.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\rasman\rasman.dll 1 + dll\win32\resutils\resutils.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\sndblst\sndblst.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\unicows\unicows.dll 1 + 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\wdmaud.drv\wdmaud.drv 1 + dll\win32\wer\wer.dll 1 + dll\win32\windowscodecs\windowscodecs.dll 1 + dll\win32\winemp3.acm\winemp3.acm 1 + dll\win32\winfax\winfax.dll 1 + dll\win32\wing32\wing32.dll 1 + dll\win32\winhttp\winhttp.dll 1 + dll\win32\wininet\wininet.dll 1 + dll\win32\winmm\winmm.dll 1 + dll\win32\winmm\midimap\midimap.dll 1 + dll\win32\winspool\winspool.drv 1 + dll\win32\winsta\winsta.dll 1 + dll\win32\wintrust\wintrust.dll 1 + dll\win32\wlanapi\wlanapi.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 + + ; Shell Extensions + dll\shellext\deskadp\deskadp.dll 1 + dll\shellext\deskmon\deskmon.dll 1 + dll\shellext\devcpux\devcpux.dll 1 + dll\shellext\fontext\fontext.dll 1 + dll\shellext\slayer\slayer.dll 1 + + ; Drivers + drivers\base\beep\beep.sys 2 + drivers\base\bootvid\bootvid.dll 1 + drivers\base\nmidebug\nmidebug.sys 2 + drivers\base\null\null.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\network\ndisuio\ndisuio.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\hid\mouhid\mouhid.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\disk.inf 6 + media\inf\display.inf 6 + media\inf\font.inf 6 + media\inf\fdc.inf 6 + media\inf\hal.inf 6 + media\inf\hdc.inf 6 ++ media\inf\input.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\unknown.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 optional + subsystems\win32\win32k\win32k.sys 1 + + ; Optional/proprietary files + modules\optional\DroidSansFallback.ttf 3 optional + modules\optional\NOTICE_for_Droid_Font.txt 4 optional + modules\optional\netkvm2k.inf 6 optional + modules\optional\netkvm2k.cat 6 optional + modules\optional\netkvm.sys 2 optional + modules\optional\alcxwdm.inf 6 optional + modules\optional\alcxwdm.sys 2 optional + modules\optional\mfc42.dll 1 optional + modules\optional\mfc42u.dll 1 optional + modules\optional\mfc71.dll 1 optional + modules\optional\mfc71u.dll 1 optional + modules\optional\msvbvm50.dll 1 optional + modules\optional\msvbvm60.dll 1 optional + modules\optional\msvcirt.dll 1 optional + modules\optional\msvcp71.dll 1 optional + modules\optional\msvcr71.dll 1 optional + modules\optional\vmx_fb.dll 1 optional + modules\optional\vmx_mode.dll 1 optional + modules\optional\vmx_svga.inf 6 optional + modules\optional\vmx_svga.sys 2 optional + modules\optional\wine_gecko-1.0.0-x86.cab 4 optional + + ; Rosapps + modules\rosapps\applications\screensavers\cylfrac\cylfrac.scr 1 optional + modules\rosapps\applications\screensavers\matrix\matrix.scr 1 optional + modules\rosapps\applications\screensavers\blankscr\scrnsave.scr 1 optional + modules\rosapps\applications\screensavers\starfield\starfield.scr 1 optional + modules\rosapps\applications\screensavers\mazescr\mazescr.scr 1 optional + modules\rosapps\applications\screensavers\butterflies\butterflies.scr 1 optional + modules\rosapps\applications\cmdutils\comp\comp.exe 1 optional + modules\rosapps\applications\cmdutils\mode\mode.exe 1 optional + modules\rosapps\applications\cmdutils\sort\sort.exe 1 optional + modules\rosapps\applications\cmdutils\tee\tee.exe 1 optional + modules\rosapps\applications\cmdutils\touch\touch.exe 1 optional + modules\rosapps\applications\cmdutils\uptime\uptime.exe 1 optional + modules\rosapps\applications\cmdutils\y\y.exe 1 optional + modules\rosapps\applications\devutils\gdb2\gdb2.exe 1 optional + modules\rosapps\applications\devutils\gdihv\gdihv.exe 1 optional + modules\rosapps\applications\devutils\genguid\genguid.exe 1 optional + modules\rosapps\applications\sysutils\gettype\gettype.exe 1 optional + modules\rosapps\applications\net\ncftp\ncftp.exe 1 optional + modules\rosapps\applications\net\netreg\netreg.exe 1 optional + modules\rosapps\applications\net\niclist\niclist.exe 1 optional + modules\rosapps\applications\net\roshttpd\roshttpd.exe 1 optional + modules\rosapps\applications\notevil\notevil.exe 1 optional + modules\rosapps\applications\sysutils\chkdsk\chkdsk.exe 1 optional + modules\rosapps\applications\sysutils\systeminfo\systeminfo.exe 1 optional + modules\rosapps\applications\sysutils\chklib\chklib.exe 1 optional + modules\rosapps\applications\sysutils\ctm\ctm.exe 1 optional + modules\rosapps\applications\sysutils\kill\kill.exe 1 optional + modules\rosapps\applications\sysutils\lsdd\lsdd.exe 1 optional + modules\rosapps\applications\sysutils\man\man.exe 1 optional + modules\rosapps\applications\sysutils\pedump\pedump.exe 1 optional + modules\rosapps\applications\sysutils\regexpl\regexpl.exe 1 optional + modules\rosapps\applications\sysutils\tcat\tcat.exe 1 optional + modules\rosapps\applications\sysutils\tlist\tlist.exe 1 optional + modules\rosapps\applications\sysutils\screenshot\screenshot.exe 1 optional + modules\rosapps\applications\sysutils\utils\binpatch\binpatch.exe 1 optional + modules\rosapps\applications\sysutils\utils\cat\cat.exe 1 optional + modules\rosapps\applications\sysutils\utils\driver\load\load.exe 1 optional + modules\rosapps\applications\sysutils\utils\driver\unload\unload.exe 1 optional + modules\rosapps\applications\sysutils\utils\infinst\infinst.exe 1 optional + modules\rosapps\applications\sysutils\utils\nts2w32err\nts2w32err.exe 1 optional + modules\rosapps\applications\sysutils\utils\objdir\objdir.exe 1 optional + modules\rosapps\applications\sysutils\utils\partinfo\partinfo.exe 1 optional + modules\rosapps\applications\sysutils\utils\ps\ps.exe 1 optional + modules\rosapps\applications\sysutils\utils\rosperf\rosperf.exe 1 optional + modules\rosapps\applications\sysutils\utils\stats\stats.exe 1 optional + modules\rosapps\applications\sysutils\utils\tickcount\tickcount.exe 1 optional + modules\rosapps\applications\winfile\winfile.exe 1 optional + modules\rosapps\demos\maze\maze.exe 1 optional + modules\rosapps\drivers\green\green.sys 2 optional + + ; Rostests + modules\rostests\rosautotest\rosautotest.exe 1 optional + modules\rostests\tests\pseh2\pseh2_test.exe 7 optional + modules\rostests\winetests\advapi32\advapi32_winetest.exe 7 optional + modules\rostests\winetests\advpack\advpack_winetest.exe 7 optional + modules\rostests\winetests\amstream\amstream_winetest.exe 7 optional + modules\rostests\winetests\atl\atl_winetest.exe 7 optional + modules\rostests\winetests\avifil32\avifil32_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\credui\credui_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\cryptui\cryptui_winetest.exe 7 optional + modules\rostests\winetests\dnsapi\dnsapi_winetest.exe 7 optional + modules\rostests\winetests\dsound\dsound_winetest.exe 7 optional + modules\rostests\winetests\fusion\fusion_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\imagehlp\imagehlp_winetest.exe 7 optional + modules\rostests\winetests\imm32\imm32_winetest.exe 7 optional + modules\rostests\winetests\inetcomm\inetcomm_winetest.exe 7 optional + modules\rostests\winetests\inetmib1\inetmib1_winetest.exe 7 optional + modules\rostests\winetests\iphlpapi\iphlpapi_winetest.exe 7 optional + modules\rostests\winetests\itss\itss_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\localspl\localspl_winetest.exe 7 optional + modules\rostests\winetests\localui\localui_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\msacm32\msacm32_winetest.exe 7 optional + modules\rostests\winetests\mscms\mscms_winetest.exe 7 optional + modules\rostests\winetests\mscoree\mscoree_winetest.exe 7 optional + modules\rostests\winetests\msctf\msctf_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\msvcrtd\msvcrtd_winetest.exe 7 optional + modules\rostests\winetests\msvfw32\msvfw32_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\ntdsapi\ntdsapi_winetest.exe 7 optional + modules\rostests\winetests\ntprint\ntprint_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\oleacc\oleacc_winetest.exe 7 optional + modules\rostests\winetests\oleaut32\oleaut32_winetest.exe 7 optional + modules\rostests\winetests\opengl32\opengl32_winetest.exe 7 optional + modules\rostests\winetests\pdh\pdh_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\qmgr\qmgr_winetest.exe 7 optional + modules\rostests\winetests\quartz\quartz_winetest.exe 7 optional + modules\rostests\winetests\rasapi32\rasapi32_winetest.exe 7 optional + modules\rostests\winetests\riched20\riched20_winetest.exe 7 optional + modules\rostests\winetests\riched32\riched32_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\serialui\serialui_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\snmpapi\snmpapi_winetest.exe 7 optional + modules\rostests\winetests\spoolss\spoolss_winetest.exe 7 optional + modules\rostests\winetests\twain_32\twain_32_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\userenv\userenv_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\wldap32\wldap32_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\rostests\apitests\advapi32\advapi32_apitest.exe 7 optional + modules\rostests\apitests\dciman32\dciman32_apitest.exe 7 optional + modules\rostests\apitests\gdi32\gdi32_apitest.exe 7 optional + modules\rostests\apitests\kernel32\kernel32_apitest.exe 7 optional + modules\rostests\apitests\msvcrt\msvcrt_apitest.exe 7 optional + modules\rostests\apitests\ntdll\ntdll_apitest.exe 7 optional + modules\rostests\apitests\user32\user32_apitest.exe 7 optional + modules\rostests\apitests\ws2_32\ws2_32_apitest.exe 7 optional + + modules\rostests\kmtests\kmtest_.exe 7 optional + modules\rostests\kmtests\kmtest_drv.sys 7 optional + modules\rostests\kmtests\example\example_drv.sys 7 optional + modules\rostests\kmtests\ntos_io\iodeviceobject_drv.sys 7 optional + modules\rostests\kmtests\ntos_io\iohelper_drv.sys 7 optional + + modules\wallpaper\Angelus_02_ROSWP.bmp 4 optional diff --cc reactos/boot/bootdata/txtsetup.sif index 1b7f1c771c8,00000000000,59668ecedf4..59668ecedf4 mode 100644,000000,100644..100644 --- a/reactos/boot/bootdata/txtsetup.sif +++ b/reactos/boot/bootdata/txtsetup.sif @@@@ -1,477 -1,0 -1,510 +1,510 @@@@ + [Version] + Signature = "$ReactOS$" + + [Directories] + ; = + 1 = "\" + 2 = system32 + 3 = system32\config + 4 = system32\drivers + 5 = media + 6 = Fonts + 7 = bin + + [DiskSpaceRequirements] + ; Required free system partition disk space in MB + FreeSysPartDiskSpace=350 + + [SourceDisksFiles] + acpi.sys=,,,,,,,,,,,,4 + nmidebug.sys=,,,,,,x,,,,,,4 + uniata.sys=,,,,,,x,,,,,,4 + buslogic.sys=,,,,,,x,,,,,,4 + blue.sys=,,,,,,x,,,,,,4 + bootvid.dll=,,,,,,,,,,,,2 + c_437.nls=,,,,,,,,,,,,2 + c_1252.nls=,,,,,,,,,,,,2 + cdfs.sys=,,,,,,x,,,,,,4 + cdrom.sys=,,,,,,x,,,,,,4 + class2.sys=,,,,,,x,,,,,,4 + isapnp.sys=,,,,,,,,,,,,4 + kdcom.dll=,,,,,,,,,,,,2 + disk.sys=,,,,,,x,,,,,,4 + floppy.sys=,,,,,,x,,,,,,4 + i8042prt.sys=,,,,,,x,,,,,,4 - usbdrv.sys=,,,,,,,,,,,,4 ++ hidclass.sys=,,,,,,,,,,,,4 ++ hidparse.sys=,,,,,,,,,,,,4 ++ hidusb.sys=,,,,,,,,,,,,4 ++ usbccgp.sys=,,,,,,x,,,,,,4 ++ usbd.sys=,,,,,,x,,,,,,4 ++ usbhub.sys=,,,,,,x,,,,,,4 ++ ;usbuhci.sys=,,,,,,x,,,,,,4 ++ usbohci.sys=,,,,,,x,,,,,,4 ++ usbehci.sys=,,,,,,x,,,,,,4 ++ usbstor.sys=,,,,,,x,,,,,,4 ++ kbdhid.sys=,,,,,,,,,,,,4 + kbdclass.sys=,,,,,,x,,,,,,4 + l_intl.nls=,,,,,,,,,,,,2 + ntfs.sys=,,,,,,,,,,,,4 + pci.sys=,,,,,,,,,,,,4 + scsiport.sys=,,,,,,x,,,,,,4 + fastfat.sys=,,,,,,x,,,,,,4 + ramdisk.sys=,,,,,,x,,,,,,4 + ext2fs.sys=,,,,,,x,,,,,,4 + classpnp.sys=,,,,,,,,,,,,4 + pciide.sys=,,,,,,,,,,,,4 + pciidex.sys=,,,,,,,,,,,,4 + pcix.sys=,,,,,,,,,,,,4 + pcmcia.sys=,,,,,,,,,,,,4 + swenum.sys=,,,,,,,,,,,,4 + ntdll.dll=,,,,,,,,,,,,2 + smss2.exe=,,,,,,,,,,,,2 + + [HardwareIdsDatabase] + ;*PNP0A00 = isapnp + *PNP0A03 = pci + *PNP0C08 = acpi + ;PCI\CC_0601 = isapnp + PCI\CC_0604 = pci + PCI\VEN_104B&CC_0100 = buslogic + PCI\CC_0101 = pciide + PCI\CC_0104 = uniata + PCI\CC_0105 = uniata + PCI\CC_0106 = uniata + *PNP0600 = uniata ++ USB\CLASS_09 = usbhub ++ USB\ROOT_HUB = usbhub ++ USB\ROOT_HUB20 = usbhub ++ ;PCI\CC_0C0300 = usbuhci ++ PCI\CC_0C0310 = usbohci ++ PCI\CC_0C0320 = usbehci ++ USB\Class_08&SubClass_06&Prot_50 = usbstor ++ HID_DEVICE_SYSTEM_KEYBOARD = kbdhid ++ USB\COMPOSITE = usbccgp ++ GenDisk = disk ++ USB\Class_03 = hidusb ++ GENERIC_HID_DEVICE = hidusb + + [BootBusExtenders.Load] + acpi = acpi.sys + pci = pci.sys + isapnp = isapnp.sys + ++ [InputDevicesSupport.Load] ++ usbehci = usbehci.sys ++ usbohci = usbohci.sys ++ ;usbuhci = usbuhci.sys ++ usbhub = usbhub.sys ++ usbccgp = usbccgp.sys ++ hidusb = hidusb.sys ++ usbstor = usbstor.sys ++ kbdhid = kbdhid.sys ++ + [BusExtenders.Load] + pciide = pciide.sys + + [SCSI.Load] + uniata = uniata.sys + buslogic = buslogic.sys ++ disk = disk.sys + + [Cabinets] + Cabinet=reactos.cab + + [SetupData] + DefaultPath = \ReactOS + OsLoadOptions = "/NOGUIBOOT /NODEBUG" + DbgOsLoadOptions = "/NOGUIBOOT /DEBUGPORT=COM1 /FIRSTCHANCE" + ;OsLoadOptions = "/NOGUIBOOT /DEBUGPORT=SCREEN" + ;OsLoadOptions = "/NOGUIBOOT /DEBUGPORT=BOCHS" + + [NLS] + AnsiCodepage = c_1252.nls + OemCodepage = c_437.nls + UnicodeCasetable = l_intl.nls + DefaultLayout = 00000409 + DefaultLanguage = 00000409 + + [Computer] + pci_up = "Standard PC Uniprocessor" + pci_mp = "Standard PC Multiprocessor" + acpi_up = "ACPI PC Uniprocessor" + acpi_mp = "ACPI PC Multiprocessor" + + [Map.Computer] + ; = + pci_up = "PC UP" + pci_mp = "PC MP" + acpi_up = "ACPI UP" + acpi_mp = "ACPI MP" + + [Files.pci_up] + ntoskrnl.exe=,,,,,,,,,,,,2 + hal.dll=,,,,,,,,,,,,2 + + [Files.pci_mp] + ntkrnlmp.exe=,,,,,,,,,,ntoskrnl.exe,,2 + halmps.dll=,,,,,,,,,,hal.dll,,2 + + [Files.acpi_up] + ntoskrnl.exe=,,,,,,,,,,,,2 + halacpi.dll=,,,,,,,,,,hal.dll,,2 + + [Files.acpi_mp] + ntkrnlmp.exe=,,,,,,,,,,ntoskrnl.exe,,2 + halacpi.dll=,,,,,,,,,,hal.dll,,2 + + [Display] + ; = ,,,,, + vga = "VGA Display (640x480x4)",,Vga,640,480,4 + vbe_640x480x8 = "VESA Display (640x480x8)",,VBE,640,480,8 + vbe_640x480x16 = "VESA Display (640x480x16)",,VBE,640,480,16 + vbe_640x480x24 = "VESA Display (640x480x24)",,VBE,640,480,24 + vbe_640x480x32 = "VESA Display (640x480x32)",,VBE,640,480,32 + vbe_800x600x8 = "VESA Display (800x600x8)",,VBE,800,600,8 + vbe = "VESA Display (800x600x16)",,VBE,800,600,16 + vbe_800x600x24 = "VESA Display (800x600x24)",,VBE,800,600,24 + vbe_800x600x32 = "VESA Display (800x600x32)",,VBE,800,600,32 + vbe_1024x768x8 = "VESA Display (1024x768x8)",,VBE,1024,768,8 + vbe_1024x768x16 = "VESA Display (1024x768x16)",,VBE,1024,768,16 + vbe_1024x768x24 = "VESA Display (1024x768x24)",,VBE,1024,768,24 + vbe_1024x768x32 = "VESA Display (1024x768x32)",,VBE,1024,768,32 + vbe_1152x864x8 = "VESA Display (1152x864x8)",,VBE,1152,864,8 + vbe_1152x864x16 = "VESA Display (1152x864x16)",,VBE,1152,864,16 + vbe_1152x864x24 = "VESA Display (1152x864x24)",,VBE,1152,864,24 + vbe_1152x864x32 = "VESA Display (1152x864x32)",,VBE,1152,864,32 + vbe_1280x1024x8 = "VESA Display (1280x1024x8)",,VBE,1280,1024,8 + vbe_1280x1024x16 = "VESA Display (1280x1024x16)",,VBE,1280,1024,16 + vbe_1280x1024x24 = "VESA Display (1280x1024x24)",,VBE,1280,1024,24 + vbe_1280x1024x32 = "VESA Display (1280x1024x32)",,VBE,1280,1024,32 + vbe_1600x1200x8 = "VESA Display (1600x1200x8)",,VBE,1600,1200,8 + vbe_1600x1200x16 = "VESA Display (1600x1200x16)",,VBE,1600,1200,16 + vbe_1600x1200x24 = "VESA Display (1600x1200x24)",,VBE,1600,1200,24 + vbe_1600x1200x32 = "VESA Display (1600x1200x32)",,VBE,1600,1200,32 + + [Map.Display] + ; = + vga = "VGA Display" + vbe = "VBE Display" + + [Keyboard] + Default = "XT-, AT- or extended keyboard (83-105 keys)" + + [Language] + ;00000436 = "Afrikaans" + 0000041C = "Albanian" + 00000401 = "Arabic (Saudi Arabia)" + ;00000801 = "Arabic (Iraq)" + ;00000C01 = "Arabic (Egypt)" + ;00001001 = "Arabic (Libya)" + ;00001401 = "Arabic (Algeria)" + ;00001801 = "Arabic (Morocco)" + ;00001C01 = "Arabic (Tunisia)" + ;00002001 = "Arabic (Oman)" + ;00002401 = "Arabic (Yemen)" + ;00002801 = "Arabic (Syria)" + ;00002C01 = "Arabic (Jordan)" + ;00003001 = "Arabic (Lebanon)" + ;00003401 = "Arabic (Kuwait)" + ;00003801 = "Arabic (U.A.E.)" + ;00003C01 = "Arabic (Bahrain)" + ;00004001 = "Arabic (Qatar)" + 0000042B = "Armenian" + 0000082C = "Azeri (Cyrillic)" + 0000042C = "Azeri (Latin)" + 0000042D = "Basque" + 00000423 = "Belarusian" + ;00000445 = "Bengali" + 00000402 = "Bulgarian" + ;00000455 = "Burmese" + 00000403 = "Catalan" + 00000404 = "Chinese (Taiwan)" + 00000804 = "Chinese (PRC)" + 00000C04 = "Chinese (Hong Kong S.A.R.)" + 00001004 = "Chinese (Singapore)" + 00001404 = "Chinese (Macau S.A.R.)" + 0000041A = "Croatian" + 00000405 = "Czech" + 00000406 = "Danish" + ;00000465 = "Divehi (Maldives)" + 00000413 = "Dutch (Netherlands)" + 00000813 = "Dutch (Belgium)" + 00000409 = "English (United States)" + 00000809 = "English (United Kingdom)" + 00000C09 = "English (Australia)" + 00001009 = "English (Canada)" + 00001409 = "English (New Zealand)" + 00001809 = "English (Ireland)" + 00001C09 = "English (South Africa)" + 00002009 = "English (Jamaica)" + 00002409 = "English (Caribbean)" + 00002809 = "English (Belize)" + 00002C09 = "English (Trinidad)" + 00003009 = "English (Zimbabwe)" + 00003409 = "English (Philippines)" + 0000048F = "Esperanto" + 00000425 = "Estonian" + ;00000438 = "Faeroese" + ;00000429 = "Farsi" + 0000040B = "Finnish" + 00000C0C = "French (Canada)" + 0000040C = "French (France)" + 0000080C = "French (Belgium)" + 0000100C = "French (Switzerland)" + 0000140C = "French (Luxembourg)" + 0000180C = "French (Monaco)" + 00000456 = "Galician (Spain)" + ;00000437 = "Georgian" + 00000407 = "German (Germany)" + 00000807 = "German (Switzerland)" + 00000C07 = "German (Austria)" + 00001007 = "German (Luxembourg)" + 00001407 = "German (Liechtenstein)" + 00000408 = "Greek" + ;00000447 = "Gujarati (India)" + ;0000040D = "Hebrew" + ;00000439 = "Hindi" + 0000040E = "Hungarian" + 0000040F = "Icelandic" + 00000421 = "Indonesian" + 00000410 = "Italian (Italy)" + 00000810 = "Italian (Switzerland)" + 00000411 = "Japanese" + ;0000044B = "Kannada (India)" + 0000043F = "Kazakh" + ;00000457 = "Konkani" + 00000412 = "Korean" + 00000440 = "Kyrgyz (Kyrgyzstan)" + 00000426 = "Latvian" + 00000427 = "Lithuanian" + 0000042F = "FYRO Macedonian" + ;0000083E = "Malay (Brunei Darussalam)" + ;0000043E = "Malay (Malaysia)" + ;0000044E = "Marathi" + ;00000450 = "Mongolian (Mongolia)" + 00000414 = "Norwegian (Bokmal)" + 00000814 = "Norwegian (Nynorsk)" + 00000415 = "Polish" + 00000816 = "Portuguese (Portugal)" + 00000416 = "Portuguese (Brazil)" + ;00000446 = "Punjabi (India)" + 00000418 = "Romanian" + 00000417 = "Romansh" + 00000419 = "Russian" + ;0000044F = "Sanskrit" + 00000C1A = "Serbian (Cyrillic)" + 0000081A = "Serbian (Latin)" + 0000041B = "Slovak" + 00000424 = "Slovenian" + 0000040A = "Spanish (Traditional Sort)" + 0000080A = "Spanish (Mexico)" + 00000C0A = "Spanish (International Sort)" + 0000100A = "Spanish (Guatemala)" + 0000140A = "Spanish (Costa Rica)" + 0000180A = "Spanish (Panama)" + 00001C0A = "Spanish (Dominican Republic)" + 0000200A = "Spanish (Venezuela)" + 0000240A = "Spanish (Colombia)" + 0000280A = "Spanish (Peru)" + 00002C0A = "Spanish (Argentina)" + 0000300A = "Spanish (Ecuador)" + 0000340A = "Spanish (Chile)" + 0000380A = "Spanish (Uruguay)" + 00003C0A = "Spanish (Paraguay)" + 0000400A = "Spanish (Bolivia)" + 0000440A = "Spanish (El Salvador)" + 0000480A = "Spanish (Honduras)" + 00004C0A = "Spanish (Nicaragua)" + 0000500A = "Spanish (Puerto Rico)" + ;00000441 = "Swahili" + 0000041D = "Swedish" + 0000081D = "Swedish (Finland)" + ;0000045A = "Syriac (Syria)" + ;00000449 = "Tamil" + 00000444 = "Tatar" + ;0000044A = "Telugu (India)" + 0000041E = "Thai" + 0000041F = "Turkish" + 00000422 = "Ukrainian" + ;00000420 = "Urdu" + 00000443 = "Uzbek (Latin)" + 00000843 = "Uzbek (Cyrillic)" + ;0000042A = "Vietnamese" + 00000490 = "Walon" + ;00000435 = "Zulu" + + + [KeyboardLayout] + 0000041C = "Albanian" + 00000401 = "Arabic (101)" + 00010401 = "Arabic (102)" + 00020401 = "Arabic (102) AZERTY" + 0000042B = "Armenian Eastern" + 0001042B = "Armenian Western" + 0000044D = "Assamese (Inscript)" + 0000082C = "Azeri Cyrillic" + 0000042C = "Azeri Latin" + 00000423 = "Belarusian" + 00000445 = "Bengali" + 00000402 = "Bulgarian BDS 5237-1978" + 00020402 = "Bulgarian phonetic classic" + 00030402 = "Bulgarian phonetic BDS 5237-2006" + 00000455 = "Burmese" + 00000C0C = "Canadian French (Legacy)" + 00011009 = "Canadian Multilingual Standard" + 0000041A = "Croatian" + 00000405 = "Czech" + 00010405 = "Czech (QWERTY)" + 00000406 = "Danish (Denmark)" + 00000439 = "Devanagari - INSCRIPT" + 00000413 = "Dutch" + 00000813 = "Dutch (Belgium)" + 00000809 = "English (United Kingdom)" + 00000409 = "English (USA)" + 00010409 = "English (USA-Dvorak)" + 00000425 = "Estonian" + 0000040B = "Finnish" + 0000080C = "French (Belgium)" + 0000040C = "French (France)" + 00000437 = "Georgian" + 00000407 = "German (Germany)" + 00030407 = "German (de_ergo)" + 00020407 = "German (NEO-1.1)" + 00010407 = "German (Ristome)" + 00000807 = "German (Swiss)" + 00000408 = "Greek" + 00010408 = "Greek 220" + 00000447 = "Gujarati" + 0000040D = "Hebrew" + 0000040E = "Hungarian" + 0000040F = "Icelandic" + 00001809 = "Irish" + 00000410 = "Italian" + 00000411 = "Japanese" + 00000412 = "Korean" + 0000043F = "Kazakh" + 0000080A = "Latin American" + 00000426 = "Latvian" + 00010427 = "Lithuanian" + 0000042F = "Macedonian (FYRO)" + 0000044C = "Malayalam" + 00000414 = "Norwegian" + 00000415 = "Polish (programmer's)" + 00010415 = "Polish (214)" + 00010416 = "Portuguese (Brazilian ABNT2)" + 00000816 = "Portuguese (Portugal)" + 00000418 = "Romanian" + 00000419 = "Russian" + 00010419 = "Russian (Typewriter)" + 00000C1A = "Serbian (Cyrillic)" + 0000081A = "Serbian (Latin)" + 0000041B = "Slovak (QWERTZ)" + 0001041B = "Slovak (QWERTY)" + 0000040A = "Spanish (traditional short)" + 0000041D = "Swedish (Sweden)" + 00000444 = "Tatar" + 0000041E = "Thai Kedmanee" + 0001041E = "Thai Pattachote" + 0002041E = "Thai Kedmanee (non-ShiftLock)" + 0003041E = "Thai Pattachote (non-ShiftLock)" + 0000041F = "Turkish Q" + 0001041F = "Turkish F" + 00000422 = "Ukrainian" + 00010422 = "Ukrainian (Student)" + 00030409 = "US Dvorak for left hand" + 00040409 = "US Dvorak for right hand" + 00050409 = "US English (IBM Arabic 238_L)" + 00020409 = "US International" + 00000843 = "Uzbek (Cyrillic)" + 0000042A = "Vietnamese" + + [Files.KeyboardLayout] + 00000401 = kbda1.dll + 00010401 = kbda2.dll + 00020401 = kbda3.dll + 00020402 = kbdbgt.dll + 00030402 = kbdbga.dll + 00040402 = kbdbgm.dll + 00000405 = kbdcz.dll + 00010405 = kbdcz1.dll + 00000406 = kbdda.dll + 00000407 = kbdgr.dll + 00000807 = kbdsg.dll + 00010407 = kbdgrist.dll + 00020407 = kbdgneo.dll + 00030407 = kbdgerg.dll + 00000408 = kbdhe.dll + 00010408 = kbdhe.dll + 00000409 = kbdus.dll + 00000809 = kbduk.dll + 00001809 = kbdir.dll + 00010409 = kbddv.dll + 00011009 = kbdcan.dll + 00020409 = kbdusx.dll + 00030409 = kbdusl.dll + 00040409 = kbdusr.dll + 00050409 = kbdusa.dll + 0000040A = kbdes.dll + 0000080A = kbdla.dll + 0000040B = kbdfi.dll + 0000040C = kbdfr.dll + 0000080C = kbdbe.dll + 00000C0C = kbdfc.dll + 0000040D = kbdheb.dll + 0000040E = kbdhu.dll + 0000040F = kbdic.dll + 00000410 = kbdit.dll + 00000411 = kbdja.dll + 00000412 = kbdko.dll + 00000413 = kbdne.dll + 00000813 = kbdbe.dll + 00000414 = kbdno.dll + 00000415 = kbdpl1.dll + 00000816 = kbdpo.dll + 00010416 = kbdbr.dll + 00000418 = kbdro.dll + 00000419 = kbdru.dll + 00010419 = kbdru1.dll + 0000041A = kbdcr.dll + 0000081A = kbdycl.dll + 00000C1A = kbdycc.dll + 0000041B = kbdsk.dll + 0001041B = kbdsk1.dll + 0000041C = kbdal.dll + 0000041D = kbdsw.dll + 0000041E = kbdth0.dll + 0001041E = kbdth1.dll + 0002041E = kbdth2.dll + 0003041E = kbdth3.dll + 0000041F = kbdtuq.dll + 0001041F = kbdtuf.dll + 00000422 = kbdur.dll + 00010422 = kbdurs.dll + 00000423 = kbdblr.dll + 00000425 = kbdest.dll + 00000426 = kbdlv.dll + 00010427 = kbdlt1.dll + 0000042A = kbdvntc.dll + 0000042B = kbdarme.dll + 0001042B = kbdarmw.dll + 0000042C = kbdazel.dll + 0000082C = kbdaze.dll + 0000042F = kbdmac.dll + 00000437 = kbdgeo.dll + 00000439 = kbdindev.dll + 0000043F = kbdkaz.dll + 00000843 = kbduzb.dll + 00000444 = kbdtat.dll + 00000445 = kbdinben.dll + 00000447 = kbdinguj.dll + 0000044C = kbdinmal.dll + 0000044D = kbdinasa.dll + 00000455 = kbdbur.dll + + [HiveInfs.Install] + AddReg=hivecls.inf,AddReg + AddReg=hivedef.inf,AddReg + AddReg=hivesft.inf,AddReg + AddReg=hivesys.inf,AddReg + + ; EOF diff --cc reactos/drivers/drivers.rbuild index 4e3c60fa548,00000000000,15b36eaeead..15b36eaeead mode 100644,000000,100644..100644 --- a/reactos/drivers/drivers.rbuild +++ b/reactos/drivers/drivers.rbuild @@@@ -1,61 -1,0 -1,67 +1,67 @@@@ + + + + + + + + + + + + + + + + + + + + + ++ ++ ++ ++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --cc reactos/drivers/filters/CMakeLists.txt index 00000000000,6e279b484dc,6e279b484dc..6e279b484dc mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/CMakeLists.txt +++ b/reactos/drivers/filters/CMakeLists.txt diff --cc reactos/drivers/filters/directory.rbuild index 00000000000,b3b19c440f4,b3b19c440f4..b3b19c440f4 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/directory.rbuild +++ b/reactos/drivers/filters/directory.rbuild diff --cc reactos/drivers/filters/mountmgr/CMakeLists.txt index 00000000000,00000000000,4a99868931c..4a99868931c mode 000000,000000,100644..100644 --- a/reactos/drivers/filters/mountmgr/CMakeLists.txt +++ b/reactos/drivers/filters/mountmgr/CMakeLists.txt diff --cc reactos/drivers/filters/mountmgr/database.c index 00000000000,badab174b4c,badab174b4c..badab174b4c mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/database.c +++ b/reactos/drivers/filters/mountmgr/database.c diff --cc reactos/drivers/filters/mountmgr/device.c index 00000000000,6bc7d819da2,6bc7d819da2..6bc7d819da2 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/device.c +++ b/reactos/drivers/filters/mountmgr/device.c diff --cc reactos/drivers/filters/mountmgr/mntmgr.h index 00000000000,00000000000,00000000000..06c61192be2 new file mode 100644 --- /dev/null +++ b/reactos/drivers/filters/mountmgr/mntmgr.h @@@@ -1,0 -1,0 -1,0 +1,453 @@@@ +++#ifndef _MNTMGR_H_ +++#define _MNTMGR_H_ +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++/* Enter FIXME */ +++#ifdef IsEqualGUID +++#undef IsEqualGUID +++#endif +++ +++#define IsEqualGUID(rguid1, rguid2) (!RtlCompareMemory(rguid1, rguid2, sizeof(GUID))) +++ +++#define FILE_READ_PROPERTIES 0x00000008 +++#define FILE_WRITE_PROPERTIES 0x00000010 +++ +++#define GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER 0x80000000 +++/* Leave FIXME */ +++ +++typedef struct _DEVICE_EXTENSION +++{ +++ PDEVICE_OBJECT DeviceObject; // 0x0 +++ PDRIVER_OBJECT DriverObject; // 0x4 +++ LIST_ENTRY DeviceListHead; // 0x8 +++ LIST_ENTRY OfflineDeviceListHead; // 0x10 +++ PVOID NotificationEntry; // 0x18 +++ KSEMAPHORE DeviceLock; // 0x1C +++ KSEMAPHORE RemoteDatabaseLock; // 0x30 +++ ULONG AutomaticDriveLetter; // 0x44 +++ LIST_ENTRY IrpListHead; // 0x48 +++ ULONG EpicNumber; // 0x50 +++ LIST_ENTRY SavedLinksListHead; // 0x54 +++ BOOLEAN ProcessedSuggestions; // 0x5C +++ BOOLEAN NoAutoMount; // 0x5D +++ LIST_ENTRY WorkerQueueListHead; // 0x60 +++ KSEMAPHORE WorkerSemaphore; // 0x68 +++ LONG WorkerReferences; // 0x7C +++ KSPIN_LOCK WorkerLock; // 0x80 +++ LIST_ENTRY UniqueIdWorkerItemListHead; // 0x84 +++ PMOUNTDEV_UNIQUE_ID DriveLetterData; // 0x8C +++ UNICODE_STRING RegistryPath; // 0x90 +++ LONG WorkerThreadStatus; // 0x98 +++ LIST_ENTRY OnlineNotificationListHead; // 0x9C +++ ULONG OnlineNotificationWorkerActive; // 0xA4 +++ ULONG OnlineNotificationCount; // 0xA8 +++ KEVENT OnlineNotificationEvent; // 0xAC +++} DEVICE_EXTENSION, *PDEVICE_EXTENSION; // 0xBC +++ +++typedef struct _DEVICE_INFORMATION +++{ +++ LIST_ENTRY DeviceListEntry; // 0x00 +++ LIST_ENTRY SymbolicLinksListHead; // 0x08 +++ LIST_ENTRY ReplicatedUniqueIdsListHead; // 0x10 +++ LIST_ENTRY AssociatedDevicesHead; // 0x18 +++ UNICODE_STRING SymbolicName; // 0x20 +++ PMOUNTDEV_UNIQUE_ID UniqueId; // 0x28 +++ UNICODE_STRING DeviceName; // 0x2C +++ BOOLEAN KeepLinks; // 0x34 +++ UCHAR SuggestedDriveLetter; // 0x35 +++ BOOLEAN Volume; // 0x36 +++ BOOLEAN Removable; // 0x37 +++ BOOLEAN LetterAssigned; // 0x38 +++ BOOLEAN NeedsReconcile; // 0x39 +++ BOOLEAN NoDatabase; // 0x3A +++ BOOLEAN SkipNotifications; // 0x3B +++ ULONG Migrated; // 0x3C +++ LONG MountState; // 0x40 +++ PVOID TargetDeviceNotificationEntry; // 0x44 +++ PDEVICE_EXTENSION DeviceExtension; // 0x48 +++} DEVICE_INFORMATION, *PDEVICE_INFORMATION; // 0x4C +++ +++typedef struct _SYMLINK_INFORMATION +++{ +++ LIST_ENTRY SymbolicLinksListEntry; // 0x00 +++ UNICODE_STRING Name; // 0x08 +++ BOOLEAN Online; // 0x10 +++} SYMLINK_INFORMATION, *PSYMLINK_INFORMATION; // 0x14 +++ +++typedef struct _SAVED_LINK_INFORMATION +++{ +++ LIST_ENTRY SavedLinksListEntry; // 0x0 +++ LIST_ENTRY SymbolicLinksListHead; // 0x8 +++ PMOUNTDEV_UNIQUE_ID UniqueId; // 0x10 +++} SAVED_LINK_INFORMATION, *PSAVED_LINK_INFORMATION; // 0x14 +++ +++typedef struct _UNIQUE_ID_REPLICATE +++{ +++ LIST_ENTRY ReplicatedUniqueIdsListEntry; // 0x0 +++ PMOUNTDEV_UNIQUE_ID UniqueId; // 0x8 +++} UNIQUE_ID_REPLICATE, *PUNIQUE_ID_REPLICATE; // 0xC +++ +++typedef struct _DATABASE_ENTRY +++{ +++ ULONG EntrySize; // 0x00 +++ ULONG DatabaseOffset; // 0x04 +++ USHORT SymbolicNameOffset; // 0x08 +++ USHORT SymbolicNameLength; // 0x0A +++ USHORT UniqueIdOffset; // 0x0C +++ USHORT UniqueIdLength; // 0x0E +++} DATABASE_ENTRY, *PDATABASE_ENTRY; // 0x10 +++ +++typedef struct _ASSOCIATED_DEVICE_ENTRY +++{ +++ LIST_ENTRY AssociatedDevicesEntry; // 0x00 +++ PDEVICE_INFORMATION DeviceInformation; // 0x08 +++ UNICODE_STRING String; // 0x0C +++} ASSOCIATED_DEVICE_ENTRY, *PASSOCIATED_DEVICE_ENTRY; // 0x14 +++ +++typedef struct _ONLINE_NOTIFICATION_WORK_ITEM +++{ +++ WORK_QUEUE_ITEM; // 0x00 +++ PDEVICE_EXTENSION DeviceExtension; // 0x10 +++ UNICODE_STRING SymbolicName; // 0x14 +++} ONLINE_NOTIFICATION_WORK_ITEM, *PONLINE_NOTIFICATION_WORK_ITEM; // 0x1C +++ +++typedef struct _RECONCILE_WORK_ITEM +++{ +++ LIST_ENTRY WorkerQueueListEntry; // 0x00 +++ PIO_WORKITEM WorkItem; // 0x08 +++ PWORKER_THREAD_ROUTINE WorkerRoutine; // 0x0C +++ PVOID Context; // 0x10 +++ PDEVICE_EXTENSION DeviceExtension; // 0x14 +++ PDEVICE_INFORMATION DeviceInformation; // 0x18 +++} RECONCILE_WORK_ITEM, *PRECONCILE_WORK_ITEM; // 0x1C +++ +++typedef struct _MIGRATE_WORK_ITEM +++{ +++ PIO_WORKITEM WorkItem; // 0x0 +++ PDEVICE_INFORMATION DeviceInformation; // 0x4 +++ PKEVENT Event; // 0x8 +++ NTSTATUS Status; // 0x0C +++ HANDLE Database; // 0x10 +++} MIGRATE_WORK_ITEM, *PMIGRATE_WORK_ITEM; // 0x14 +++ +++typedef struct _UNIQUE_ID_WORK_ITEM +++{ +++ LIST_ENTRY UniqueIdWorkerItemListEntry; // 0x0 +++ PIO_WORKITEM WorkItem; // 0x8 +++ PDEVICE_EXTENSION DeviceExtension; // 0xC +++ PIRP Irp; // 0x10 +++ PVOID IrpBuffer; // 0x14 +++ PKEVENT Event; // 0x1C +++ UNICODE_STRING DeviceName; // 0x20 +++ ULONG IrpBufferLength; // 0x28 +++ ULONG StackSize; // 0x2C +++} UNIQUE_ID_WORK_ITEM, *PUNIQUE_ID_WORK_ITEM; // 0x30 +++ +++PDEVICE_OBJECT gdeviceObject; +++ +++/* Memory allocation helpers */ +++#define AllocatePool(Size) ExAllocatePoolWithTag(PagedPool, Size, 'AtnM') +++#define FreePool(P) ExFreePoolWithTag(P, 'AtnM') +++ +++/* Misc macros */ +++#define MAX(a, b) ((a > b) ? a : b) +++ +++#define LETTER_POSITION 0xC +++#define COLON_POSITION 0xD +++#define DRIVE_LETTER_LENGTH 0x1C +++ +++/* mountmgr.c */ +++ +++extern UNICODE_STRING DosDevicesMount; +++extern UNICODE_STRING ReparseIndex; +++extern UNICODE_STRING DeviceFloppy; +++extern UNICODE_STRING DeviceMount; +++extern UNICODE_STRING DeviceCdRom; +++extern UNICODE_STRING SafeVolumes; +++extern UNICODE_STRING DosDevices; +++extern UNICODE_STRING DosGlobal; +++extern UNICODE_STRING Global; +++extern UNICODE_STRING Volume; +++extern KEVENT UnloadEvent; +++extern LONG Unloading; +++ +++DRIVER_INITIALIZE DriverEntry; +++ +++VOID +++NTAPI +++MountMgrCancel( +++ IN PDEVICE_OBJECT DeviceObject, +++ IN PIRP Irp +++); +++ +++NTSTATUS +++MountMgrMountedDeviceArrival( +++ IN PDEVICE_EXTENSION Extension, +++ IN PUNICODE_STRING SymbolicName, +++ IN BOOLEAN FromVolume +++); +++ +++VOID +++MountMgrMountedDeviceRemoval( +++ IN PDEVICE_EXTENSION Extension, +++ IN PUNICODE_STRING DeviceName +++); +++ +++NTSTATUS +++FindDeviceInfo( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicName, +++ IN BOOLEAN DeviceNameGiven, +++ OUT PDEVICE_INFORMATION * DeviceInformation +++); +++ +++VOID +++MountMgrFreeDeadDeviceInfo( +++ IN PDEVICE_INFORMATION DeviceInformation +++); +++ +++NTSTATUS +++QueryDeviceInformation( +++ IN PUNICODE_STRING SymbolicName, +++ OUT PUNICODE_STRING DeviceName OPTIONAL, +++ OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL, +++ OUT PBOOLEAN Removable OPTIONAL, +++ OUT PBOOLEAN GptDriveLetter OPTIONAL, +++ OUT PBOOLEAN HasGuid OPTIONAL, +++ IN OUT LPGUID StableGuid OPTIONAL, +++ OUT PBOOLEAN Valid OPTIONAL +++); +++ +++BOOLEAN +++HasDriveLetter( +++ IN PDEVICE_INFORMATION DeviceInformation +++); +++ +++/* database.c */ +++ +++extern PWSTR DatabasePath; +++extern PWSTR OfflinePath; +++ +++VOID +++ReconcileThisDatabaseWithMaster( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PDEVICE_INFORMATION DeviceInformation +++); +++ +++NTSTATUS +++WaitForRemoteDatabaseSemaphore( +++ IN PDEVICE_EXTENSION DeviceExtension +++); +++ +++VOID +++ReleaseRemoteDatabaseSemaphore( +++ IN PDEVICE_EXTENSION DeviceExtension +++); +++ +++VOID +++ChangeRemoteDatabaseUniqueId( +++ IN PDEVICE_INFORMATION DeviceInformation, +++ IN PMOUNTDEV_UNIQUE_ID OldUniqueId, +++ IN PMOUNTDEV_UNIQUE_ID NewUniqueId +++); +++ +++VOID +++ReconcileAllDatabasesWithMaster( +++ IN PDEVICE_EXTENSION DeviceExtension +++); +++ +++VOID +++DeleteFromLocalDatabase( +++ IN PUNICODE_STRING SymbolicLink, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++VOID +++DeleteRegistryDriveLetter( +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++VOID +++DeleteNoDriveLetterEntry( +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++NTSTATUS +++QueryVolumeName( +++ IN HANDLE RootDirectory, +++ IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, +++ IN PUNICODE_STRING FileName OPTIONAL, +++ OUT PUNICODE_STRING SymbolicName, +++ OUT PUNICODE_STRING VolumeName +++); +++ +++/* device.c */ +++ +++DRIVER_DISPATCH MountMgrDeviceControl; +++ +++/* notify.c */ +++VOID +++IssueUniqueIdChangeNotifyWorker( +++ IN PUNIQUE_ID_WORK_ITEM WorkItem, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++VOID +++WaitForOnlinesToComplete( +++ IN PDEVICE_EXTENSION DeviceExtension +++); +++ +++VOID +++RegisterForTargetDeviceNotification( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PDEVICE_INFORMATION DeviceInformation +++); +++ +++VOID +++SendOnlineNotification( +++ IN PUNICODE_STRING SymbolicName +++); +++ +++VOID +++IssueUniqueIdChangeNotify( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING DeviceName, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++VOID +++PostOnlineNotification( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicName +++); +++ +++VOID +++MountMgrNotify( +++ IN PDEVICE_EXTENSION DeviceExtension +++); +++ +++VOID +++MountMgrNotifyNameChange( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING DeviceName, +++ IN BOOLEAN ValidateVolume +++); +++ +++/* uniqueid.c */ +++VOID +++MountMgrUniqueIdChangeRoutine( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PMOUNTDEV_UNIQUE_ID OldUniqueId, +++ IN PMOUNTDEV_UNIQUE_ID NewUniqueId +++); +++ +++VOID +++CreateNoDriveLetterEntry( +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++BOOLEAN +++HasNoDriveLetterEntry( +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++/* point.c */ +++NTSTATUS +++MountMgrCreatePointWorker( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicLinkName, +++ IN PUNICODE_STRING DeviceName +++); +++ +++NTSTATUS +++QueryPointsFromSymbolicLinkName( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicName, +++ IN PIRP Irp +++); +++ +++NTSTATUS +++QueryPointsFromMemory( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PIRP Irp, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL, +++ IN PUNICODE_STRING SymbolicName OPTIONAL +++); +++ +++/* symlink.c */ +++NTSTATUS +++GlobalCreateSymbolicLink( +++ IN PUNICODE_STRING DosName, +++ IN PUNICODE_STRING DeviceName +++); +++ +++NTSTATUS +++GlobalDeleteSymbolicLink( +++ IN PUNICODE_STRING DosName +++); +++ +++NTSTATUS +++QuerySuggestedLinkName( +++ IN PUNICODE_STRING SymbolicName, +++ OUT PUNICODE_STRING SuggestedLinkName, +++ OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks +++); +++ +++NTSTATUS +++QuerySymbolicLinkNamesFromStorage( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PDEVICE_INFORMATION DeviceInformation, +++ IN PUNICODE_STRING SuggestedLinkName, +++ IN BOOLEAN UseOnlyIfThereAreNoOtherLinks, +++ OUT PUNICODE_STRING * SymLinks, +++ OUT PULONG SymLinkCount, +++ IN BOOLEAN HasGuid, +++ IN LPGUID Guid +++); +++ +++PSAVED_LINK_INFORMATION +++RemoveSavedLinks( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId +++); +++ +++BOOLEAN +++RedirectSavedLink( +++ IN PSAVED_LINK_INFORMATION SavedLinkInformation, +++ IN PUNICODE_STRING DosName, +++ IN PUNICODE_STRING NewLink +++); +++ +++VOID +++SendLinkCreated( +++ IN PUNICODE_STRING SymbolicName +++); +++ +++NTSTATUS +++CreateNewVolumeName( +++ OUT PUNICODE_STRING VolumeName, +++ IN PGUID VolumeGuid OPTIONAL +++); +++ +++BOOLEAN +++IsDriveLetter( +++ PUNICODE_STRING SymbolicName +++); +++ +++VOID +++DeleteSymbolicLinkNameFromMemory( +++ IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicLink, +++ IN BOOLEAN MarkOffline +++); +++ +++#endif /* _MNTMGR_H_ */ diff --cc reactos/drivers/filters/mountmgr/mountmgr.c index 00000000000,00000000000,00000000000..b805a2076ea new file mode 100644 --- /dev/null +++ b/reactos/drivers/filters/mountmgr/mountmgr.c @@@@ -1,0 -1,0 -1,0 +1,1896 @@@@ +++/* +++ * ReactOS kernel +++ * Copyright (C) 2011 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 St, Fifth Floor, Boston, MA 02110-1301, USA. +++ * +++ * COPYRIGHT: See COPYING in the top level directory +++ * PROJECT: ReactOS kernel +++ * FILE: drivers/filesystem/mountmgr/mountmgr.c +++ * PURPOSE: Mount Manager +++ * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org) +++ * Alex Ionescu (alex.ionescu@reactos.org) +++ */ +++ +++/* INCLUDES *****************************************************************/ +++ +++#include "mntmgr.h" +++ +++#define NDEBUG +++#include +++ +++/* FIXME */ +++GUID MountedDevicesGuid = {0x53F5630D, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B}}; +++ +++KEVENT UnloadEvent; +++LONG Unloading; +++ +++PWSTR Cunc = L"\\??\\C:"; +++ +++/* +++ * TODO: +++ * - MountMgrQueryDosVolumePath +++ * - MountMgrQueryDosVolumePaths +++ * - MountMgrQueryVolumePaths +++ * - MountMgrValidateBackPointer +++ * - MountMgrVolumeMountPointCreated +++ * - MountMgrVolumeMountPointDeleted +++ * - ReconcileThisDatabaseWithMasterWorker +++ */ +++ +++/* +++ * @implemented +++ */ +++BOOLEAN +++IsOffline(PUNICODE_STRING SymbolicName) +++{ +++ NTSTATUS Status; +++ ULONG IsOffline, Default; +++ RTL_QUERY_REGISTRY_TABLE QueryTable[2]; +++ +++ /* Prepare to look in the registry to see if +++ * given volume is offline +++ */ +++ RtlZeroMemory(QueryTable, sizeof(QueryTable)); +++ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; +++ QueryTable[0].Name = SymbolicName->Buffer; +++ QueryTable[0].EntryContext = &IsOffline; +++ QueryTable[0].DefaultType = REG_DWORD; +++ QueryTable[0].DefaultLength = sizeof(ULONG); +++ QueryTable[0].DefaultData = &Default; +++ +++ Default = 0; +++ +++ /* Query status */ +++ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, +++ OfflinePath, +++ QueryTable, +++ NULL, +++ NULL); +++ if (!NT_SUCCESS(Status)) +++ { +++ IsOffline = 0; +++ } +++ +++ return (IsOffline != 0); +++} +++ +++/* +++ * @implemented +++ */ +++BOOLEAN +++HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation) +++{ +++ PLIST_ENTRY NextEntry; +++ PSYMLINK_INFORMATION SymlinkInfo; +++ +++ /* To have a drive letter, a device must have symbolic links */ +++ if (IsListEmpty(&(DeviceInformation->SymbolicLinksListHead))) +++ { +++ return FALSE; +++ } +++ +++ /* Browse all the links untill a drive letter is found */ +++ NextEntry = &(DeviceInformation->SymbolicLinksListHead); +++ do +++ { +++ SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry); +++ +++ if (SymlinkInfo->Online) +++ { +++ if (IsDriveLetter(&(SymlinkInfo->Name))) +++ { +++ return TRUE; +++ } +++ } +++ +++ NextEntry = NextEntry->Flink; +++ } while (NextEntry != &(DeviceInformation->SymbolicLinksListHead)); +++ +++ return FALSE; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter, +++ IN PUNICODE_STRING DeviceName, +++ IN UCHAR Letter, +++ IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL) +++{ +++ NTSTATUS Status; +++ +++ /* Allocate a big enough buffer to contain the symbolic link */ +++ DriveLetter->MaximumLength = sizeof(DosDevices.Buffer) + 3 * sizeof(WCHAR); +++ DriveLetter->Buffer = AllocatePool(sizeof(DosDevices.Buffer) + 3 * sizeof(WCHAR)); +++ if (!DriveLetter->Buffer) +++ { +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Copy prefix */ +++ RtlCopyUnicodeString(DriveLetter, &DosDevices); +++ +++ /* Update string to reflect real contents */ +++ DriveLetter->Length = sizeof(DosDevices.Buffer) + 2 * sizeof(WCHAR); +++ DriveLetter->Buffer[(sizeof(DosDevices.Buffer) + 2 * sizeof(WCHAR)) / sizeof (WCHAR)] = UNICODE_NULL; +++ DriveLetter->Buffer[(sizeof(DosDevices.Buffer) + sizeof(WCHAR)) / sizeof (WCHAR)] = L':'; +++ +++ /* If caller wants a no drive entry */ +++ if (Letter == (UCHAR)-1) +++ { +++ /* Then, create a no letter entry */ +++ CreateNoDriveLetterEntry(UniqueId); +++ FreePool(DriveLetter->Buffer); +++ return STATUS_UNSUCCESSFUL; +++ } +++ else if (Letter) +++ { +++ /* Use the letter given by the caller */ +++ DriveLetter->Buffer[sizeof(DosDevices.Buffer) / sizeof(WCHAR)] = (WCHAR)Letter; +++ Status = GlobalCreateSymbolicLink(DriveLetter, DeviceName); +++ if (NT_SUCCESS(Status)) +++ { +++ return Status; +++ } +++ } +++ +++ /* If caller didn't provide a letter, let's find one for him. +++ * If device is a floppy, start with letter A +++ */ +++ if (RtlPrefixUnicodeString(&DeviceFloppy, DeviceName, TRUE)) +++ { +++ Letter = 'A'; +++ } +++ else +++ { +++ /* Otherwise, if device is a cd rom, then, start with D. +++ * Finally, if a disk, use C +++ */ +++ Letter = RtlPrefixUnicodeString(&DeviceCdRom, DeviceName, TRUE) + 'C'; +++ } +++ +++ /* Try to affect a letter (up to Z, ofc) until it's possible */ +++ for (; Letter <= 'Z'; Letter++) +++ { +++ DriveLetter->Buffer[sizeof(DosDevices.Buffer) / sizeof(WCHAR)] = (WCHAR)Letter; +++ Status = GlobalCreateSymbolicLink(DriveLetter, DeviceName); +++ if (NT_SUCCESS(Status)) +++ { +++ return Status; +++ } +++ } +++ +++ /* We failed to allocate a letter */ +++ FreePool(DriveLetter->Buffer); +++ return Status; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, +++ OUT PUNICODE_STRING DeviceName OPTIONAL, +++ OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL, +++ OUT PBOOLEAN Removable OPTIONAL, +++ OUT PBOOLEAN GptDriveLetter OPTIONAL, +++ OUT PBOOLEAN HasGuid OPTIONAL, +++ IN OUT LPGUID StableGuid OPTIONAL, +++ OUT PBOOLEAN Valid OPTIONAL) +++{ +++ PIRP Irp; +++ USHORT Size; +++ KEVENT Event; +++ NTSTATUS Status; +++ BOOLEAN IsRemovable; +++ PMOUNTDEV_NAME Name; +++ PMOUNTDEV_UNIQUE_ID Id; +++ PFILE_OBJECT FileObject; +++ PIO_STACK_LOCATION Stack; +++ PDEVICE_OBJECT DeviceObject; +++ IO_STATUS_BLOCK IoStatusBlock; +++ PARTITION_INFORMATION_EX PartitionInfo; +++ STORAGE_DEVICE_NUMBER StorageDeviceNumber; +++ VOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptAttributes; +++ +++ /* Get device associated with the symbolic name */ +++ Status = IoGetDeviceObjectPointer(SymbolicName, +++ FILE_READ_ATTRIBUTES, +++ &FileObject, +++ &DeviceObject); +++ if (!NT_SUCCESS(Status)) +++ { +++ return Status; +++ } +++ +++ /* The associate FO can't have a file name */ +++ if (FileObject->FileName.Length) +++ { +++ ObfDereferenceObject(FileObject); +++ return STATUS_OBJECT_NAME_NOT_FOUND; +++ } +++ +++ /* Check if it's removable & return to the user (if asked to) */ +++ IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA); +++ if (Removable) +++ { +++ *Removable = IsRemovable; +++ } +++ +++ /* Get the attached device */ +++ DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject); +++ +++ /* If we've been asked for a GPT drive letter */ +++ if (GptDriveLetter) +++ { +++ /* Consider it has one */ +++ *GptDriveLetter = TRUE; +++ +++ if (!IsRemovable) +++ { +++ /* Query the GPT attributes */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_GPT_ATTRIBUTES, +++ DeviceObject, +++ NULL, +++ 0, +++ &GptAttributes, +++ sizeof(GptAttributes), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ /* In case of failure, don't fail, that's no vital */ +++ if (!NT_SUCCESS(Status)) +++ { +++ Status = STATUS_SUCCESS; +++ } +++ /* Check if it has a drive letter */ +++ else if (!(GptAttributes.GptAttributes & +++ GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER)) +++ { +++ *GptDriveLetter = FALSE; +++ } +++ } +++ } +++ +++ /* If caller wants to know if there's valid contents */ +++ if (Valid) +++ { +++ /* Suppose it's not OK */ +++ *Valid = FALSE; +++ +++ if (!IsRemovable) +++ { +++ /* Query partitions information */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX, +++ DeviceObject, +++ NULL, +++ 0, +++ &PartitionInfo, +++ sizeof(PartitionInfo), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ /* Once again here, failure isn't major */ +++ if (!NT_SUCCESS(Status)) +++ { +++ Status = STATUS_SUCCESS; +++ } +++ /* Verify we know something in */ +++ else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR && +++ IsRecognizedPartition(PartitionInfo.Mbr.PartitionType)) +++ { +++ *Valid = TRUE; +++ } +++ +++ /* It looks correct, ensure it is & query device number */ +++ if (*Valid) +++ { +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, +++ DeviceObject, +++ NULL, +++ 0, +++ &StorageDeviceNumber, +++ sizeof(StorageDeviceNumber), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ if (!NT_SUCCESS(Status)) +++ { +++ Status = STATUS_SUCCESS; +++ } +++ else +++ { +++ *Valid = FALSE; +++ } +++ } +++ } +++ } +++ +++ /* If caller needs device name */ +++ if (DeviceName) +++ { +++ /* Allocate a buffer just to request length */ +++ Name = AllocatePool(sizeof(MOUNTDEV_NAME)); +++ if (!Name) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Query device name */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, +++ DeviceObject, +++ NULL, +++ 0, +++ Name, +++ sizeof(MOUNTDEV_NAME), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ FreePool(Name); +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Stack = IoGetNextIrpStackLocation(Irp); +++ Stack->FileObject = FileObject; +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ /* Now, we've got the correct length */ +++ if (Status == STATUS_BUFFER_OVERFLOW) +++ { +++ Size = Name->NameLength + sizeof(MOUNTDEV_NAME); +++ +++ FreePool(Name); +++ +++ /* Allocate proper size */ +++ Name = AllocatePool(Size); +++ if (!Name) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* And query name (for real that time) */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, +++ DeviceObject, +++ NULL, +++ 0, +++ Name, +++ Size, +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ FreePool(Name); +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Stack = IoGetNextIrpStackLocation(Irp); +++ Stack->FileObject = FileObject; +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ } +++ +++ /* Here we can't fail and assume default value */ +++ if (!NT_SUCCESS(Status)) +++ { +++ FreePool(Name); +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return Status; +++ } +++ +++ /* Copy back found name to the caller */ +++ DeviceName->Length = Name->NameLength; +++ DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR); +++ DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength); +++ if (!DeviceName->Buffer) +++ { +++ FreePool(Name); +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength); +++ DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL; +++ FreePool(Name); +++ } +++ +++ /* If caller wants device unique ID */ +++ if (UniqueId) +++ { +++ /* Prepare buffer to probe length */ +++ Id = AllocatePool(sizeof(MOUNTDEV_UNIQUE_ID)); +++ if (!Id) +++ { +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Query unique ID length */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID, +++ DeviceObject, +++ NULL, +++ 0, +++ Id, +++ sizeof(MOUNTDEV_UNIQUE_ID), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ FreePool(Id); +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Stack = IoGetNextIrpStackLocation(Irp); +++ Stack->FileObject = FileObject; +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ /* Retry with appropriate length */ +++ if (Status == STATUS_BUFFER_OVERFLOW) +++ { +++ Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID); +++ +++ FreePool(Id); +++ +++ /* Allocate the correct buffer */ +++ Id = AllocatePool(Size); +++ if (!Id) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Query unique ID */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, +++ DeviceObject, +++ NULL, +++ 0, +++ Id, +++ Size, +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ FreePool(Id); +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Stack = IoGetNextIrpStackLocation(Irp); +++ Stack->FileObject = FileObject; +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ } +++ +++ /* Hands back unique ID */ +++ if (NT_SUCCESS(Status)) +++ { +++ *UniqueId = Id; +++ } +++ else +++ { +++ /* In case of failure, also free the rest */ +++ FreePool(Id); +++ if (DeviceName->Length) +++ { +++ FreePool(DeviceName->Buffer); +++ } +++ +++ ObDereferenceObject(DeviceObject); +++ ObDereferenceObject(FileObject); +++ +++ return Status; +++ } +++ } +++ +++ /* If user wants to know about GUID */ +++ if (HasGuid) +++ { +++ /* Query device stable GUID */ +++ KeInitializeEvent(&Event, NotificationEvent, FALSE); +++ Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTDEV_QUERY_STABLE_GUID, +++ DeviceObject, +++ NULL, +++ 0, +++ StableGuid, +++ sizeof(GUID), +++ FALSE, +++ &Event, +++ &IoStatusBlock); +++ if (!Irp) +++ { +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ Stack = IoGetNextIrpStackLocation(Irp); +++ Stack->FileObject = FileObject; +++ +++ Status = IofCallDriver(DeviceObject, Irp); +++ if (Status == STATUS_PENDING) +++ { +++ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); +++ Status = IoStatusBlock.Status; +++ } +++ +++ *HasGuid = NT_SUCCESS(Status); +++ } +++ +++ ObfDereferenceObject(DeviceObject); +++ ObfDereferenceObject(FileObject); +++ return Status; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicName, +++ IN BOOLEAN DeviceNameGiven, +++ OUT PDEVICE_INFORMATION * DeviceInformation) +++{ +++ NTSTATUS Status; +++ PLIST_ENTRY NextEntry; +++ UNICODE_STRING DeviceName; +++ PDEVICE_INFORMATION DeviceInfo = NULL; +++ +++ /* If a device name was given, use it */ +++ if (DeviceNameGiven) +++ { +++ DeviceName.Length = SymbolicName->Length; +++ DeviceName.Buffer = SymbolicName->Buffer; +++ } +++ else +++ { +++ /* Otherwise, query it */ +++ Status = QueryDeviceInformation(SymbolicName, +++ &DeviceName, +++ NULL, NULL, +++ NULL, NULL, +++ NULL, NULL); +++ if (!NT_SUCCESS(Status)) +++ { +++ return Status; +++ } +++ } +++ +++ /* Look for device information matching devive */ +++ for (NextEntry = DeviceExtension->DeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->DeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ DeviceInfo = CONTAINING_RECORD(NextEntry, +++ DEVICE_INFORMATION, +++ DeviceListEntry); +++ +++ if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE)) +++ { +++ break; +++ } +++ } +++ +++ /* Release our buffer if required */ +++ if (!DeviceNameGiven) +++ { +++ FreePool(DeviceName.Buffer); +++ } +++ +++ /* Return found intormation */ +++ if (NextEntry == &(DeviceExtension->DeviceListHead)) +++ { +++ return STATUS_OBJECT_NAME_NOT_FOUND; +++ } +++ +++ *DeviceInformation = DeviceInfo; +++ return STATUS_SUCCESS; +++} +++ +++/* +++ * @implemented +++ */ +++VOID +++MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation) +++{ +++ FreePool(DeviceInformation->SymbolicName.Buffer); +++ FreePool(DeviceInformation); +++} +++ +++/* +++ * @implemented +++ */ +++VOID +++MountMgrFreeMountedDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation) +++{ +++ PLIST_ENTRY NextEntry; +++ PSYMLINK_INFORMATION SymLink; +++ PUNIQUE_ID_REPLICATE UniqueId; +++ PASSOCIATED_DEVICE_ENTRY AssociatedDevice; +++ +++ /* Purge symbolic links list */ +++ while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead)); +++ SymLink = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry); +++ +++ GlobalDeleteSymbolicLink(&(SymLink->Name)); +++ FreePool(SymLink->Name.Buffer); +++ } +++ +++ /* Purge replicated unique IDs list */ +++ while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead)); +++ UniqueId = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry); +++ +++ FreePool(UniqueId->UniqueId); +++ FreePool(UniqueId); +++ } +++ +++ while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead)); +++ AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry); +++ +++ FreePool(AssociatedDevice->String.Buffer); +++ FreePool(AssociatedDevice); +++ } +++ +++ /* Free the rest of the buffers */ +++ FreePool(DeviceInformation->SymbolicName.Buffer); +++ if (DeviceInformation->KeepLinks) +++ { +++ FreePool(DeviceInformation->UniqueId); +++ } +++ FreePool(DeviceInformation->DeviceName.Buffer); +++ +++ /* Finally, stop waiting for notifications for this device */ +++ if (DeviceInformation->TargetDeviceNotificationEntry) +++ { +++ IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry); +++ } +++} +++ +++/* +++ * @implemented +++ */ +++VOID +++MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation) +++{ +++ PLIST_ENTRY NextEntry; +++ PSYMLINK_INFORMATION SymlinkInformation; +++ +++ /* For all the saved links */ +++ while (!IsListEmpty(&(SavedLinkInformation->SymbolicLinksListHead))) +++ { +++ NextEntry = RemoveHeadList(&(SavedLinkInformation->SymbolicLinksListHead)); +++ SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry); +++ +++ /* Remove from system & free */ +++ GlobalDeleteSymbolicLink(&(SymlinkInformation->Name)); +++ FreePool(SymlinkInformation->Name.Buffer); +++ FreePool(SymlinkInformation); +++ } +++ +++ /* And free unique ID & entry */ +++ FreePool(SavedLinkInformation->UniqueId); +++ FreePool(SavedLinkInformation); +++} +++ +++ +++/* +++ * @implemented +++ */ +++VOID +++NTAPI +++MountMgrUnload(IN struct _DRIVER_OBJECT *DriverObject) +++{ +++ PLIST_ENTRY NextEntry; +++ PUNIQUE_ID_WORK_ITEM WorkItem; +++ PDEVICE_EXTENSION DeviceExtension; +++ PDEVICE_INFORMATION DeviceInformation; +++ PSAVED_LINK_INFORMATION SavedLinkInformation; +++ +++ /* Don't get notification any longer */ +++ IoUnregisterShutdownNotification(gdeviceObject); +++ +++ /* Free registry buffer */ +++ DeviceExtension = gdeviceObject->DeviceExtension; +++ if (DeviceExtension->RegistryPath.Buffer) +++ { +++ FreePool(DeviceExtension->RegistryPath.Buffer); +++ DeviceExtension->RegistryPath.Buffer = NULL; +++ } +++ +++ InterlockedExchange(&Unloading, TRUE); +++ +++ KeInitializeEvent(&UnloadEvent, NotificationEvent, FALSE); +++ +++ /* Wait for workers to finish */ +++ if (InterlockedIncrement(&DeviceExtension->WorkerReferences)) +++ { +++ KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore), +++ IO_NO_INCREMENT, 1, FALSE); +++ +++ KeWaitForSingleObject(&UnloadEvent, Executive, KernelMode, FALSE, NULL); +++ } +++ else +++ { +++ InterlockedDecrement(&(DeviceExtension->WorkerReferences)); +++ } +++ +++ /* Don't get any notification any longer² */ +++ IoUnregisterPlugPlayNotification(DeviceExtension->NotificationEntry); +++ +++ /* Acquire the driver exclusively */ +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, +++ FALSE, NULL); +++ +++ /* Clear offline devices list */ +++ while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead)); +++ DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ MountMgrFreeDeadDeviceInfo(DeviceInformation); +++ } +++ +++ /* Clear saved links list */ +++ while (!IsListEmpty(&(DeviceExtension->SavedLinksListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceExtension->SavedLinksListHead)); +++ SavedLinkInformation = CONTAINING_RECORD(NextEntry, SAVED_LINK_INFORMATION, SavedLinksListEntry); +++ MountMgrFreeSavedLink(SavedLinkInformation); +++ } +++ +++ /* Clear workers list */ +++ while (!IsListEmpty(&(DeviceExtension->UniqueIdWorkerItemListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead)); +++ WorkItem = CONTAINING_RECORD(NextEntry, UNIQUE_ID_WORK_ITEM, UniqueIdWorkerItemListEntry); +++ +++ KeResetEvent(&UnloadEvent); +++ WorkItem->Event = &UnloadEvent; +++ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, +++ 1, FALSE); +++ +++ IoCancelIrp(WorkItem->Irp); +++ KeWaitForSingleObject(&UnloadEvent, Executive, KernelMode, FALSE, NULL); +++ +++ IoFreeIrp(WorkItem->Irp); +++ FreePool(WorkItem->DeviceName.Buffer); +++ FreePool(WorkItem->IrpBuffer); +++ FreePool(WorkItem); +++ +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, +++ FALSE, NULL); +++ } +++ +++ /* If we have drive letter data, release */ +++ if (DeviceExtension->DriveLetterData) +++ { +++ FreePool(DeviceExtension->DriveLetterData); +++ DeviceExtension->DriveLetterData = NULL; +++ } +++ +++ /* Release driver & quit */ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++ +++ GlobalDeleteSymbolicLink(&DosDevicesMount); +++ IoDeleteDevice(gdeviceObject); +++} +++ +++/* +++ * @implemented +++ */ +++ULONG +++MountmgrReadNoAutoMount(IN PUNICODE_STRING RegistryPath) +++{ +++ NTSTATUS Status; +++ ULONG Result, Default = 0; +++ RTL_QUERY_REGISTRY_TABLE QueryTable[2]; +++ +++ RtlZeroMemory(QueryTable, sizeof(QueryTable)); +++ +++ /* Simply read data from register */ +++ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; +++ QueryTable[0].Name = L"NoAutoMount"; +++ QueryTable[0].EntryContext = &Result; +++ QueryTable[0].DefaultType = REG_NONE; +++ QueryTable[0].DefaultData = &Default; +++ QueryTable[0].DefaultLength = sizeof(ULONG); +++ +++ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, +++ RegistryPath->Buffer, +++ QueryTable, +++ NULL, +++ NULL); +++ if (!NT_SUCCESS(Status)) +++ { +++ return Default; +++ } +++ +++ return Result; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++MountMgrMountedDeviceArrival(IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING SymbolicName, +++ IN BOOLEAN FromVolume) +++{ +++ WCHAR Letter; +++ GUID StableGuid; +++ HANDLE LinkHandle; +++ ULONG SymLinkCount, i; +++ PLIST_ENTRY NextEntry; +++ PUNICODE_STRING SymLinks; +++ NTSTATUS Status, IntStatus; +++ OBJECT_ATTRIBUTES ObjectAttributes; +++ PSYMLINK_INFORMATION SymlinkInformation; +++ PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId; +++ PSAVED_LINK_INFORMATION SavedLinkInformation; +++ PDEVICE_INFORMATION DeviceInformation, CurrentDevice; +++ WCHAR CSymLinkBuffer[MAX_PATH], LinkTargetBuffer[MAX_PATH]; +++ UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink; +++ BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError; +++ +++ /* New device = new structure to represent it */ +++ DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION)); +++ if (!DeviceInformation) +++ { +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Initialise device structure */ +++ RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION)); +++ InitializeListHead(&(DeviceInformation->SymbolicLinksListHead)); +++ InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead)); +++ InitializeListHead(&(DeviceInformation->AssociatedDevicesHead)); +++ DeviceInformation->SymbolicName.Length = SymbolicName->Length; +++ DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL); +++ DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength); +++ if (!DeviceInformation->SymbolicName.Buffer) +++ { +++ FreePool(DeviceInformation); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ /* Copy symbolic name */ +++ RtlCopyMemory(DeviceInformation->SymbolicName.Buffer, SymbolicName->Buffer, SymbolicName->Length); +++ DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL; +++ DeviceInformation->Volume = FromVolume; +++ DeviceInformation->DeviceExtension = DeviceExtension; +++ +++ /* Query as much data as possible about device */ +++ Status = QueryDeviceInformation(SymbolicName, +++ &TargetDeviceName, +++ &UniqueId, +++ &(DeviceInformation->Removable), +++ &HasGptDriveLetter, +++ &HasGuid, +++ &StableGuid, +++ &Valid); +++ if (!NT_SUCCESS(Status)) +++ { +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL); +++ +++ for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->OfflineDeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ +++ if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE)) +++ { +++ break; +++ } +++ } +++ +++ if (NextEntry != &(DeviceExtension->OfflineDeviceListHead)) +++ { +++ MountMgrFreeDeadDeviceInfo(DeviceInformation); +++ } +++ else +++ { +++ InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry)); +++ } +++ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++ +++ return Status; +++ } +++ +++ /* Save gathered data */ +++ DeviceInformation->UniqueId = UniqueId; +++ DeviceInformation->DeviceName = TargetDeviceName; +++ DeviceInformation->KeepLinks = FALSE; +++ +++ /* If we found system partition, mark it */ +++ if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength) +++ { +++ if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength) +++ == UniqueId->UniqueIdLength) +++ { +++ IoSetSystemPartition(&TargetDeviceName); +++ } +++ } +++ +++ /* Check suggested link name */ +++ Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName), +++ &SuggestedLinkName, +++ &UseOnlyIfThereAreNoOtherLinks); +++ if (!NT_SUCCESS(Status)) +++ { +++ SuggestedLinkName.Buffer = NULL; +++ } +++ +++ /* If it's OK, set it and save its letter (if any) */ +++ if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName)) +++ { +++ DeviceInformation->SuggestedDriveLetter = SuggestedLinkName.Buffer[LETTER_POSITION]; +++ } +++ +++ /* Acquire driver exclusively */ +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL); +++ +++ /* Check if we already have device in to prevent double registration */ +++ for (NextEntry = DeviceExtension->DeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->DeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ +++ if (RtlEqualUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE)) +++ { +++ break; +++ } +++ } +++ +++ /* If we found it, clear ours, and return success, all correct */ +++ if (NextEntry != &(DeviceExtension->DeviceListHead)) +++ { +++ if (SuggestedLinkName.Buffer) +++ { +++ FreePool(SuggestedLinkName.Buffer); +++ } +++ +++ FreePool(UniqueId); +++ FreePool(TargetDeviceName.Buffer); +++ FreePool(DeviceInformation->DeviceName.Buffer); +++ FreePool(DeviceInformation); +++ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++ +++ return STATUS_SUCCESS; +++ } +++ +++ /* Check if there are symlinks associated with our device in registry */ +++ Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension, +++ DeviceInformation, +++ (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL, +++ UseOnlyIfThereAreNoOtherLinks, +++ &SymLinks, +++ &SymLinkCount, +++ HasGuid, +++ &StableGuid); +++ +++ /* If our device is a CD-ROM */ +++ if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE)) +++ { +++ LinkTarget.Length = 0; +++ LinkTarget.MaximumLength = sizeof(LinkTargetBuffer); +++ LinkTarget.Buffer = LinkTargetBuffer; +++ +++ RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc)); +++ RtlInitUnicodeString(&CSymLink, CSymLinkBuffer); +++ +++ /* Start checking all letters that could have been associated */ +++ for (Letter = L'D'; Letter <= L'Z'; Letter++) +++ { +++ CSymLink.Buffer[LETTER_POSITION] = Letter; +++ +++ InitializeObjectAttributes(&ObjectAttributes, +++ &CSymLink, +++ OBJ_CASE_INSENSITIVE, +++ NULL, +++ NULL); +++ +++ /* Try to open the associated symlink */ +++ Status = ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); +++ if (!NT_SUCCESS(Status)) +++ { +++ continue; +++ } +++ +++ /* And query its target */ +++ Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL); +++ ZwClose(LinkHandle); +++ +++ if (!NT_SUCCESS(Status)) +++ { +++ continue; +++ } +++ +++ IntStatus = STATUS_UNSUCCESSFUL; +++ if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE)) +++ { +++ continue; +++ } +++ +++ /* This link is matching our device, whereas it's not supposed to have any +++ * symlink associated. +++ * Delete it +++ */ +++ if (!SymLinkCount) +++ { +++ IoDeleteSymbolicLink(&CSymLink); +++ continue; +++ } +++ +++ /* Now, for all the symlinks, check for ours */ +++ for (i = 0; i < SymLinkCount; i++) +++ { +++ if (IsDriveLetter(&(SymLinks[i]))) +++ { +++ /* If it exists, that's correct */ +++ if (SymLinks[i].Buffer[LETTER_POSITION] == Letter) +++ { +++ IntStatus = STATUS_SUCCESS; +++ } +++ } +++ } +++ +++ /* Useless link, delete it */ +++ if (IntStatus == STATUS_UNSUCCESSFUL) +++ { +++ IoDeleteSymbolicLink(&CSymLink); +++ } +++ } +++ } +++ +++ /* Suggested name is no longer required */ +++ if (SuggestedLinkName.Buffer) +++ { +++ FreePool(SuggestedLinkName.Buffer); +++ } +++ +++ /* If if failed, ensure we don't take symlinks into account */ +++ if (!NT_SUCCESS(Status)) +++ { +++ SymLinks = NULL; +++ SymLinkCount = 0; +++ } +++ +++ /* Now we queried them, remove the symlinks */ +++ SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId); +++ +++ IsDrvLetter = FALSE; +++ IsOff = FALSE; +++ IsVolumeName = FALSE; +++ /* For all the symlinks */ +++ for (i = 0; i < SymLinkCount; i++) +++ { +++ /* Check if our device is a volume */ +++ if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i]))) +++ { +++ IsVolumeName = TRUE; +++ } +++ /* If it has a drive letter */ +++ else if (IsDriveLetter(&(SymLinks[i]))) +++ { +++ if (IsDrvLetter) +++ { +++ DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId); +++ continue; +++ } +++ else +++ { +++ IsDrvLetter = TRUE; +++ } +++ } +++ +++ /* And recreate the symlink to our device */ +++ Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName); +++ if (!NT_SUCCESS(Status)) +++ { +++ LinkError = TRUE; +++ +++ if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) || +++ !SavedLinkInformation) +++ { +++ Status = QueryDeviceInformation(&(SymLinks[i]), &DeviceName, NULL, NULL, NULL, NULL, NULL, NULL); +++ if (NT_SUCCESS(Status)) +++ { +++ LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE); +++ FreePool(DeviceName.Buffer); +++ } +++ +++ if (!LinkError) +++ { +++ if (IsDriveLetter(&(SymLinks[i]))) +++ { +++ IsDrvLetter = FALSE; +++ DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId); +++ } +++ +++ FreePool(SymLinks[i].Buffer); +++ continue; +++ } +++ } +++ } +++ +++ /* Check if was offline */ +++ if (IsOffline(&(SymLinks[i]))) +++ { +++ IsOff = TRUE; +++ } +++ +++ /* Finally, associate this symlink with the device */ +++ SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION)); +++ if (!SymlinkInformation) +++ { +++ GlobalDeleteSymbolicLink(&(SymLinks[i])); +++ FreePool(SymLinks[i].Buffer); +++ continue; +++ } +++ +++ SymlinkInformation->Name = SymLinks[i]; +++ SymlinkInformation->Online = TRUE; +++ +++ InsertTailList(&(DeviceInformation->SymbolicLinksListHead), +++ &(SymlinkInformation->SymbolicLinksListEntry)); +++ } +++ +++ /* Now, for all the recreated symlinks, notify their recreation */ +++ for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink; +++ NextEntry != &(DeviceInformation->SymbolicLinksListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry); +++ +++ SendLinkCreated(&(SymlinkInformation->Name)); +++ } +++ +++ /* If we had saved links, it's time to free them */ +++ if (SavedLinkInformation) +++ { +++ MountMgrFreeSavedLink(SavedLinkInformation); +++ } +++ +++ /* If our device doesn't have a volume name */ +++ if (!IsVolumeName) +++ { +++ /* It's time to create one */ +++ Status = CreateNewVolumeName(&VolumeName, NULL); +++ if (NT_SUCCESS(Status)) +++ { +++ /* Write it to global database */ +++ RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, +++ DatabasePath, +++ VolumeName.Buffer, +++ REG_BINARY, +++ UniqueId->UniqueId, +++ UniqueId->UniqueIdLength); +++ +++ /* And create the symlink */ +++ GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName); +++ +++ SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION)); +++ if (!SymlinkInformation) +++ { +++ FreePool(VolumeName.Buffer); +++ } +++ /* Finally, associate it with the device and notify creation */ +++ else +++ { +++ SymlinkInformation->Name = VolumeName; +++ SymlinkInformation->Online = TRUE; +++ InsertTailList(&(DeviceInformation->SymbolicLinksListHead), +++ &(SymlinkInformation->SymbolicLinksListEntry)); +++ +++ SendLinkCreated(&VolumeName); +++ } +++ } +++ } +++ +++ /* If we found a drive letter, then, ignore the suggested one */ +++ if (IsDrvLetter) +++ { +++ DeviceInformation->SuggestedDriveLetter = 0; +++ } +++ /* Else, it's time to set up one */ +++ else if (!DeviceExtension->NoAutoMount && !DeviceInformation->Removable && +++ DeviceExtension->AutomaticDriveLetter && HasGptDriveLetter && +++ DeviceInformation->SuggestedDriveLetter && +++ !HasNoDriveLetterEntry(UniqueId)) +++ { +++ /* Create a new drive letter */ +++ Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName, +++ DeviceInformation->SuggestedDriveLetter, +++ NULL); +++ if (!NT_SUCCESS(Status)) +++ { +++ CreateNoDriveLetterEntry(UniqueId); +++ } +++ else +++ { +++ /* Save it to global database */ +++ RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, +++ DatabasePath, +++ DriveLetter.Buffer, +++ REG_BINARY, +++ UniqueId->UniqueId, +++ UniqueId->UniqueIdLength); +++ +++ /* Associate it with the device and notify creation */ +++ SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION)); +++ if (!SymlinkInformation) +++ { +++ FreePool(DriveLetter.Buffer); +++ } +++ else +++ { +++ SymlinkInformation->Name = DriveLetter; +++ SymlinkInformation->Online = TRUE; +++ InsertTailList(&(DeviceInformation->SymbolicLinksListHead), +++ &(SymlinkInformation->SymbolicLinksListEntry)); +++ +++ SendLinkCreated(&DriveLetter); +++ } +++ } +++ } +++ +++ /* If required, register for notifications about the device */ +++ if (!FromVolume) +++ { +++ RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation); +++ } +++ +++ /* Finally, insert the device into our devices list */ +++ InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry)); +++ +++ /* Copy device unique ID */ +++ NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID)); +++ if (NewUniqueId) +++ { +++ NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength; +++ RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength); +++ } +++ +++ /* If device's offline or valid, skip its notifications */ +++ if (IsOff || Valid) +++ { +++ DeviceInformation->SkipNotifications = TRUE; +++ } +++ +++ /* In case device is valid and is set to no automount, +++ * set it offline. +++ */ +++ if (DeviceExtension->NoAutoMount || IsDrvLetter) +++ { +++ IsOff = !DeviceInformation->SkipNotifications; +++ } +++ else +++ { +++ IsOff = FALSE; +++ } +++ +++ /* Finally, release the exclusive lock */ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++ +++ /* If device is not offline, notify its arrival */ +++ if (!IsOff) +++ { +++ SendOnlineNotification(SymbolicName); +++ } +++ +++ /* If we had symlinks (from storage), free them */ +++ if (SymLinks) +++ { +++ FreePool(SymLinks); +++ } +++ +++ /* Notify about unique id change */ +++ if (NewUniqueId) +++ { +++ IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId); +++ FreePool(NewUniqueId); +++ } +++ +++ /* If this drive was set to have a drive letter automatically +++ * Now it's back, local databases sync will be required +++ */ +++ if (DeviceExtension->AutomaticDriveLetter) +++ { +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL); +++ +++ ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation); +++ +++ NextEntry = DeviceExtension->DeviceListHead.Flink; +++ CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ while (CurrentDevice != DeviceInformation) +++ { +++ if (!CurrentDevice->NoDatabase) +++ { +++ ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice); +++ } +++ +++ NextEntry = NextEntry->Flink; +++ CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ } +++ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++ } +++ +++ return STATUS_SUCCESS; +++} +++ +++/* +++ * @implemented +++ */ +++VOID +++MountMgrMountedDeviceRemoval(IN PDEVICE_EXTENSION DeviceExtension, +++ IN PUNICODE_STRING DeviceName) +++{ +++ PLIST_ENTRY NextEntry, DeviceEntry; +++ PUNIQUE_ID_REPLICATE UniqueIdReplicate; +++ PSYMLINK_INFORMATION SymlinkInformation; +++ PASSOCIATED_DEVICE_ENTRY AssociatedDevice; +++ PSAVED_LINK_INFORMATION SavedLinkInformation = NULL; +++ PDEVICE_INFORMATION DeviceInformation, CurrentDevice; +++ +++ /* Acquire device exclusively */ +++ KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL); +++ +++ /* Look for the leaving device */ +++ for (NextEntry = DeviceExtension->DeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->DeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ +++ if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE)) +++ { +++ break; +++ } +++ } +++ +++ /* If we found it */ +++ if (NextEntry != &(DeviceExtension->DeviceListHead)) +++ { +++ /* If it's asked to keep links, then, prepare to save them */ +++ if (DeviceInformation->KeepLinks) +++ { +++ SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION)); +++ if (!SavedLinkInformation) +++ { +++ DeviceInformation->KeepLinks = FALSE; +++ } +++ } +++ +++ /* If it's possible (and asked), start to save them */ +++ if (DeviceInformation->KeepLinks) +++ { +++ InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry)); +++ InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead)); +++ SavedLinkInformation->UniqueId = DeviceInformation->UniqueId; +++ } +++ +++ /* For all the symlinks */ +++ while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead)); +++ SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry); +++ +++ /* If we have to, save the link */ +++ if (DeviceInformation->KeepLinks) +++ { +++ InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry)); +++ } +++ /* Otherwise, just release it */ +++ else +++ { +++ GlobalDeleteSymbolicLink(&(SymlinkInformation->Name)); +++ FreePool(SymlinkInformation->Name.Buffer); +++ FreePool(SymlinkInformation); +++ } +++ } +++ +++ /* Free all the replicated unique IDs */ +++ while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead)); +++ UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry); +++ +++ +++ FreePool(UniqueIdReplicate->UniqueId); +++ FreePool(UniqueIdReplicate); +++ } +++ +++ while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead))) +++ { +++ NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead)); +++ AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry); +++ +++ DeviceInformation->NoDatabase = TRUE; +++ FreePool(AssociatedDevice->String.Buffer); +++ FreePool(AssociatedDevice); +++ } +++ +++ /* Remove device from the device list */ +++ RemoveEntryList(&(DeviceInformation->DeviceListEntry)); +++ +++ /* If there are still devices, check if some were associated with ours */ +++ if (!IsListEmpty(&(DeviceInformation->DeviceListEntry))) +++ { +++ for (NextEntry = DeviceExtension->DeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->DeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ +++ /* And then, remove them */ +++ DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink; +++ while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead)) +++ { +++ AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry); +++ DeviceEntry = DeviceEntry->Flink; +++ +++ if (AssociatedDevice->DeviceInformation != DeviceInformation) +++ { +++ continue; +++ } +++ +++ RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry)); +++ FreePool(AssociatedDevice->String.Buffer); +++ FreePool(AssociatedDevice); +++ } +++ } +++ } +++ +++ /* Finally, clean up device name, symbolic name */ +++ FreePool(DeviceInformation->SymbolicName.Buffer); +++ if (!DeviceInformation->KeepLinks) +++ { +++ FreePool(DeviceInformation->UniqueId); +++ } +++ FreePool(DeviceInformation->DeviceName.Buffer); +++ +++ /* Unregister notifications */ +++ if (DeviceInformation->TargetDeviceNotificationEntry) +++ { +++ IoUnregisterPlugPlayNotification(DeviceInformation->TargetDeviceNotificationEntry); +++ } +++ +++ /* And leave */ +++ FreePool(DeviceInformation); +++ } +++ else +++ { +++ /* We didn't find device, perhaps because it was offline */ +++ for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink; +++ NextEntry != &(DeviceExtension->OfflineDeviceListHead); +++ NextEntry = NextEntry->Flink) +++ { +++ DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry); +++ +++ /* It was, remove it */ +++ if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0) +++ { +++ RemoveEntryList(&(DeviceInformation->DeviceListEntry)); +++ MountMgrFreeDeadDeviceInfo(DeviceInformation); +++ break; +++ } +++ } +++ } +++ +++ /* Releave driver */ +++ KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE); +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++NTAPI +++MountMgrMountedDeviceNotification(IN PVOID NotificationStructure, +++ IN PVOID Context) +++{ +++ BOOLEAN OldState; +++ PDEVICE_EXTENSION DeviceExtension; +++ PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification; +++ +++ /* Notification for a device arrived */ +++ /* Disable hard errors */ +++ OldState = PsGetThreadHardErrorsAreDisabled(PsGetCurrentThread()); +++ PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), TRUE); +++ +++ DeviceExtension = Context; +++ Notification = NotificationStructure; +++ +++ /* Dispatch according to the event */ +++ if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_ARRIVAL)) +++ { +++ MountMgrMountedDeviceArrival(DeviceExtension, Notification->SymbolicLinkName, FALSE); +++ } +++ else if (IsEqualGUID(&(Notification->Event), &GUID_DEVICE_INTERFACE_REMOVAL)) +++ { +++ MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName); +++ } +++ +++ /* Reset hard errors */ +++ PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), OldState); +++ +++ return STATUS_SUCCESS; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++NTAPI +++MountMgrCreateClose(IN PDEVICE_OBJECT DeviceObject, +++ IN PIRP Irp) +++{ +++ PIO_STACK_LOCATION Stack; +++ NTSTATUS Status = STATUS_SUCCESS; +++ +++ Stack = IoGetCurrentIrpStackLocation(Irp); +++ +++ /* Allow driver opening for communication +++ * as long as it's not taken for a directory +++ */ +++ if (Stack->MajorFunction == IRP_MJ_CREATE && +++ Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE) +++ { +++ Status = STATUS_NOT_A_DIRECTORY; +++ } +++ +++ Irp->IoStatus.Status = Status; +++ Irp->IoStatus.Information = 0; +++ IoCompleteRequest(Irp, IO_NO_INCREMENT); +++ return Status; +++} +++ +++/* +++ * @implemented +++ */ +++VOID +++NTAPI +++MountMgrCancel(IN PDEVICE_OBJECT DeviceObject, +++ IN PIRP Irp) +++{ +++ RemoveEntryList(&(Irp->Tail.Overlay.ListEntry)); +++ +++ IoReleaseCancelSpinLock(Irp->CancelIrql); +++ +++ Irp->IoStatus.Information = 0; +++ Irp->IoStatus.Status = STATUS_CANCELLED; +++ IofCompleteRequest(Irp, IO_NO_INCREMENT); +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++NTAPI +++MountMgrCleanup(IN PDEVICE_OBJECT DeviceObject, +++ IN PIRP Irp) +++{ +++ PIRP ListIrp; +++ KIRQL OldIrql; +++ PLIST_ENTRY NextEntry; +++ PFILE_OBJECT FileObject; +++ PIO_STACK_LOCATION Stack; +++ PDEVICE_EXTENSION DeviceExtension; +++ +++ DeviceExtension = DeviceObject->DeviceExtension; +++ Stack = IoGetCurrentIrpStackLocation(Irp); +++ FileObject = Stack->FileObject; +++ +++ IoAcquireCancelSpinLock(&OldIrql); +++ +++ /* If IRP list if empty, it's OK */ +++ if (IsListEmpty(&(DeviceExtension->IrpListHead))) +++ { +++ IoReleaseCancelSpinLock(OldIrql); +++ +++ Irp->IoStatus.Status = STATUS_SUCCESS; +++ Irp->IoStatus.Information = 0; +++ IoCompleteRequest(Irp, IO_NO_INCREMENT); +++ +++ return STATUS_SUCCESS; +++ } +++ +++ /* Otherwise, cancel all the IRPs */ +++ NextEntry = &(DeviceExtension->IrpListHead); +++ do +++ { +++ ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); +++ if (IoGetCurrentIrpStackLocation(ListIrp)->FileObject == FileObject) +++ { +++ ListIrp->Cancel = TRUE; +++ ListIrp->CancelIrql = OldIrql; +++ ListIrp->CancelRoutine = NULL; +++ MountMgrCancel(DeviceObject, ListIrp); +++ +++ IoAcquireCancelSpinLock(&OldIrql); +++ } +++ +++ NextEntry = NextEntry->Flink; +++ } +++ while (NextEntry != &(DeviceExtension->IrpListHead)); +++ +++ IoReleaseCancelSpinLock(OldIrql); +++ +++ Irp->IoStatus.Status = STATUS_SUCCESS; +++ Irp->IoStatus.Information = 0; +++ IoCompleteRequest(Irp, IO_NO_INCREMENT); +++ +++ return STATUS_SUCCESS; +++} +++ +++/* +++ * @implemented +++ */ +++NTSTATUS +++NTAPI +++MountMgrShutdown(IN PDEVICE_OBJECT DeviceObject, +++ IN PIRP Irp) +++{ +++ PDEVICE_EXTENSION DeviceExtension; +++ +++ DeviceExtension = DeviceObject->DeviceExtension; +++ +++ InterlockedExchange(&Unloading, TRUE); +++ +++ KeInitializeEvent(&UnloadEvent, NotificationEvent, FALSE); +++ +++ /* Wait for workers */ +++ if (InterlockedIncrement(&(DeviceExtension->WorkerReferences))) +++ { +++ KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore), +++ IO_NO_INCREMENT, +++ 1, +++ FALSE); +++ KeWaitForSingleObject(&UnloadEvent, Executive, KernelMode, FALSE, NULL); +++ } +++ else +++ { +++ InterlockedDecrement(&(DeviceExtension->WorkerReferences)); +++ } +++ +++ Irp->IoStatus.Status = STATUS_SUCCESS; +++ Irp->IoStatus.Information = 0; +++ IoCompleteRequest(Irp, IO_NO_INCREMENT); +++ +++ return STATUS_SUCCESS; +++} +++ +++/* FUNCTIONS ****************************************************************/ +++ +++NTSTATUS +++NTAPI +++DriverEntry(IN PDRIVER_OBJECT DriverObject, +++ IN PUNICODE_STRING RegistryPath) +++{ +++ NTSTATUS Status; +++ PDEVICE_OBJECT DeviceObject; +++ PDEVICE_EXTENSION DeviceExtension; +++ +++ RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, DatabasePath); +++ +++ Status = IoCreateDevice(DriverObject, +++ sizeof(DEVICE_EXTENSION), +++ &DeviceMount, +++ FILE_DEVICE_NETWORK, +++ FILE_DEVICE_SECURE_OPEN, +++ FALSE, +++ &DeviceObject); +++ if (!NT_SUCCESS(Status)) +++ { +++ return Status; +++ } +++ +++ DriverObject->DriverUnload = MountMgrUnload; +++ +++ DeviceExtension = DeviceObject->DeviceExtension; +++ RtlZeroMemory(DeviceExtension, sizeof(DEVICE_EXTENSION)); +++ DeviceExtension->DeviceObject = DeviceObject; +++ DeviceExtension->DriverObject = DriverObject; +++ +++ InitializeListHead(&(DeviceExtension->DeviceListHead)); +++ InitializeListHead(&(DeviceExtension->OfflineDeviceListHead)); +++ +++ KeInitializeSemaphore(&(DeviceExtension->DeviceLock), 1, 1); +++ KeInitializeSemaphore(&(DeviceExtension->RemoteDatabaseLock), 1, 1); +++ +++ InitializeListHead(&(DeviceExtension->IrpListHead)); +++ DeviceExtension->EpicNumber = 1; +++ +++ InitializeListHead(&(DeviceExtension->SavedLinksListHead)); +++ +++ InitializeListHead(&(DeviceExtension->WorkerQueueListHead)); +++ KeInitializeSemaphore(&(DeviceExtension->WorkerSemaphore), 0, MAXLONG); +++ DeviceExtension->WorkerReferences = -1; +++ KeInitializeSpinLock(&(DeviceExtension->WorkerLock)); +++ +++ InitializeListHead(&(DeviceExtension->UniqueIdWorkerItemListHead)); +++ InitializeListHead(&(DeviceExtension->OnlineNotificationListHead)); +++ DeviceExtension->OnlineNotificationCount = 1; +++ +++ DeviceExtension->RegistryPath.Length = RegistryPath->Length; +++ DeviceExtension->RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR); +++ DeviceExtension->RegistryPath.Buffer = AllocatePool(DeviceExtension->RegistryPath.MaximumLength); +++ if (!DeviceExtension->RegistryPath.Buffer) +++ { +++ IoDeleteDevice(DeviceObject); +++ return STATUS_INSUFFICIENT_RESOURCES; +++ } +++ +++ RtlCopyUnicodeString(&(DeviceExtension->RegistryPath), RegistryPath); +++ +++ DeviceExtension->NoAutoMount = MountmgrReadNoAutoMount(&(DeviceExtension->RegistryPath)); +++ +++ GlobalCreateSymbolicLink(&DosDevicesMount, &DeviceMount); +++ +++ /* Register for device arrival & removal. Ask to be notified for already +++ * present devices +++ */ +++ Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, +++ PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, +++ &MountedDevicesGuid, +++ DriverObject, +++ MountMgrMountedDeviceNotification, +++ DeviceObject, +++ &(DeviceExtension->NotificationEntry)); +++ +++ if (!NT_SUCCESS(Status)) +++ { +++ IoDeleteDevice(DeviceObject); +++ return Status; +++ } +++ +++ DriverObject->MajorFunction[IRP_MJ_CREATE] = +++ DriverObject->MajorFunction[IRP_MJ_CLOSE] = MountMgrCreateClose; +++ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MountMgrDeviceControl; +++ DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MountMgrCleanup; +++ DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = MountMgrShutdown; +++ +++ gdeviceObject = DeviceObject; +++ +++ Status = IoRegisterShutdownNotification(DeviceObject); +++ if (!NT_SUCCESS(Status)) +++ { +++ IoDeleteDevice(DeviceObject); +++ } +++ +++ return Status; +++} diff --cc reactos/drivers/filters/mountmgr/mountmgr.rbuild index 00000000000,00000000000,52aa848418f..52aa848418f mode 000000,000000,100644..100644 --- a/reactos/drivers/filters/mountmgr/mountmgr.rbuild +++ b/reactos/drivers/filters/mountmgr/mountmgr.rbuild diff --cc reactos/drivers/filters/mountmgr/mountmgr.rc index 00000000000,cf38d598d2f,cf38d598d2f..cf38d598d2f mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/mountmgr.rc +++ b/reactos/drivers/filters/mountmgr/mountmgr.rc diff --cc reactos/drivers/filters/mountmgr/notify.c index 00000000000,2b2acbc2aa4,2b2acbc2aa4..2b2acbc2aa4 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/notify.c +++ b/reactos/drivers/filters/mountmgr/notify.c diff --cc reactos/drivers/filters/mountmgr/point.c index 00000000000,5f8d33f2bc3,5f8d33f2bc3..5f8d33f2bc3 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/point.c +++ b/reactos/drivers/filters/mountmgr/point.c diff --cc reactos/drivers/filters/mountmgr/symlink.c index 00000000000,68a3980a648,68a3980a648..68a3980a648 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/symlink.c +++ b/reactos/drivers/filters/mountmgr/symlink.c diff --cc reactos/drivers/filters/mountmgr/uniqueid.c index 00000000000,66160ffb534,66160ffb534..66160ffb534 mode 000000,100644,100644..100644 --- a/reactos/drivers/filters/mountmgr/uniqueid.c +++ b/reactos/drivers/filters/mountmgr/uniqueid.c diff --cc reactos/drivers/hid/CMakeLists.txt index 00000000000,6051356e048,6051356e048..6051356e048 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/CMakeLists.txt +++ b/reactos/drivers/hid/CMakeLists.txt diff --cc reactos/drivers/hid/directory.rbuild index 00000000000,00000000000,4fa5c649c5f..4fa5c649c5f mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/directory.rbuild +++ b/reactos/drivers/hid/directory.rbuild diff --cc reactos/drivers/hid/hidclass/CMakeLists.txt index 00000000000,00000000000,f5f69220a3a..f5f69220a3a mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidclass/CMakeLists.txt +++ b/reactos/drivers/hid/hidclass/CMakeLists.txt diff --cc reactos/drivers/hid/hidclass/fdo.c index 00000000000,00000000000,27df9041161..27df9041161 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidclass/fdo.c +++ b/reactos/drivers/hid/hidclass/fdo.c diff --cc reactos/drivers/hid/hidclass/hidclass.c index 00000000000,00000000000,deb67f496e0..deb67f496e0 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidclass/hidclass.c +++ b/reactos/drivers/hid/hidclass/hidclass.c diff --cc reactos/drivers/hid/hidclass/hidclass.rbuild index 00000000000,00000000000,c5419c63b93..c5419c63b93 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidclass/hidclass.rbuild +++ b/reactos/drivers/hid/hidclass/hidclass.rbuild diff --cc reactos/drivers/hid/hidclass/hidclass.rc index 00000000000,a700199fb14,a700199fb14..a700199fb14 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidclass/hidclass.rc +++ b/reactos/drivers/hid/hidclass/hidclass.rc diff --cc reactos/drivers/hid/hidclass/hidclass.spec index 00000000000,3539f1f6aea,3539f1f6aea..3539f1f6aea mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidclass/hidclass.spec +++ b/reactos/drivers/hid/hidclass/hidclass.spec diff --cc reactos/drivers/hid/hidclass/pdo.c index 00000000000,00000000000,cfaadc6e9d7..cfaadc6e9d7 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidclass/pdo.c +++ b/reactos/drivers/hid/hidclass/pdo.c diff --cc reactos/drivers/hid/hidclass/precomp.h index 00000000000,23820e6938a,23820e6938a..23820e6938a mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidclass/precomp.h +++ b/reactos/drivers/hid/hidclass/precomp.h diff --cc reactos/drivers/hid/hidparse/CMakeLists.txt index 00000000000,52f388da794,52f388da794..52f388da794 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidparse/CMakeLists.txt +++ b/reactos/drivers/hid/hidparse/CMakeLists.txt diff --cc reactos/drivers/hid/hidparse/hidparse.c index 00000000000,00000000000,d44310630d8..d44310630d8 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidparse/hidparse.c +++ b/reactos/drivers/hid/hidparse/hidparse.c diff --cc reactos/drivers/hid/hidparse/hidparse.h index 00000000000,45202cb0014,45202cb0014..45202cb0014 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidparse/hidparse.h +++ b/reactos/drivers/hid/hidparse/hidparse.h diff --cc reactos/drivers/hid/hidparse/hidparse.rbuild index 00000000000,00000000000,6cc8ed3677a..6cc8ed3677a mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidparse/hidparse.rbuild +++ b/reactos/drivers/hid/hidparse/hidparse.rbuild diff --cc reactos/drivers/hid/hidparse/hidparse.rc index 00000000000,3da21c341f6,3da21c341f6..3da21c341f6 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidparse/hidparse.rc +++ b/reactos/drivers/hid/hidparse/hidparse.rc diff --cc reactos/drivers/hid/hidparse/hidparse.spec index 00000000000,73afdfa3d6c,73afdfa3d6c..73afdfa3d6c mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidparse/hidparse.spec +++ b/reactos/drivers/hid/hidparse/hidparse.spec diff --cc reactos/drivers/hid/hidusb/CMakeLists.txt index 00000000000,88e3700d556,88e3700d556..88e3700d556 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidusb/CMakeLists.txt +++ b/reactos/drivers/hid/hidusb/CMakeLists.txt diff --cc reactos/drivers/hid/hidusb/hidusb.c index 00000000000,00000000000,a862045525b..a862045525b mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidusb/hidusb.c +++ b/reactos/drivers/hid/hidusb/hidusb.c diff --cc reactos/drivers/hid/hidusb/hidusb.h index 00000000000,816afb8ed33,816afb8ed33..816afb8ed33 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidusb/hidusb.h +++ b/reactos/drivers/hid/hidusb/hidusb.h diff --cc reactos/drivers/hid/hidusb/hidusb.rbuild index 00000000000,00000000000,fd9c46de598..fd9c46de598 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/hidusb/hidusb.rbuild +++ b/reactos/drivers/hid/hidusb/hidusb.rbuild diff --cc reactos/drivers/hid/hidusb/hidusb.rc index 00000000000,4ad02a08141,4ad02a08141..4ad02a08141 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/hidusb/hidusb.rc +++ b/reactos/drivers/hid/hidusb/hidusb.rc diff --cc reactos/drivers/hid/kbdhid/CMakeLists.txt index 00000000000,f8667efae35,f8667efae35..f8667efae35 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/kbdhid/CMakeLists.txt +++ b/reactos/drivers/hid/kbdhid/CMakeLists.txt diff --cc reactos/drivers/hid/kbdhid/kbdhid.c index 00000000000,00000000000,ce9f62665da..ce9f62665da mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/kbdhid/kbdhid.c +++ b/reactos/drivers/hid/kbdhid/kbdhid.c diff --cc reactos/drivers/hid/kbdhid/kbdhid.h index 00000000000,00000000000,bc606bb2f82..bc606bb2f82 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/kbdhid/kbdhid.h +++ b/reactos/drivers/hid/kbdhid/kbdhid.h diff --cc reactos/drivers/hid/kbdhid/kbdhid.rbuild index 00000000000,00000000000,904f6d2324c..904f6d2324c mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/kbdhid/kbdhid.rbuild +++ b/reactos/drivers/hid/kbdhid/kbdhid.rbuild diff --cc reactos/drivers/hid/kbdhid/kbdhid.rc index 00000000000,317d71e2932,317d71e2932..317d71e2932 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/kbdhid/kbdhid.rc +++ b/reactos/drivers/hid/kbdhid/kbdhid.rc diff --cc reactos/drivers/hid/mouhid/CMakeLists.txt index 00000000000,77d9c10d7f5,77d9c10d7f5..77d9c10d7f5 mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/mouhid/CMakeLists.txt +++ b/reactos/drivers/hid/mouhid/CMakeLists.txt diff --cc reactos/drivers/hid/mouhid/mouhid.c index 00000000000,00000000000,b713b70f3dc..b713b70f3dc mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/mouhid/mouhid.c +++ b/reactos/drivers/hid/mouhid/mouhid.c diff --cc reactos/drivers/hid/mouhid/mouhid.h index 00000000000,00000000000,78048fdce5d..78048fdce5d mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/mouhid/mouhid.h +++ b/reactos/drivers/hid/mouhid/mouhid.h diff --cc reactos/drivers/hid/mouhid/mouhid.rbuild index 00000000000,00000000000,cfb1f95bfa0..cfb1f95bfa0 mode 000000,000000,100644..100644 --- a/reactos/drivers/hid/mouhid/mouhid.rbuild +++ b/reactos/drivers/hid/mouhid/mouhid.rbuild diff --cc reactos/drivers/hid/mouhid/mouhid.rc index 00000000000,ae82d18f99b,ae82d18f99b..ae82d18f99b mode 000000,100644,100644..100644 --- a/reactos/drivers/hid/mouhid/mouhid.rc +++ b/reactos/drivers/hid/mouhid/mouhid.rc diff --cc reactos/drivers/input/kbdclass/kbdclass.c index 3cf6c9511af,00000000000,e1bbe5830a9..e1bbe5830a9 mode 100644,000000,100644..100644 --- a/reactos/drivers/input/kbdclass/kbdclass.c +++ b/reactos/drivers/input/kbdclass/kbdclass.c @@@@ -1,1035 -1,0 -1,1102 +1,1102 @@@@ + /* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Keyboard class driver + * FILE: drivers/kbdclass/kbdclass.c + * PURPOSE: Keyboard class driver + * + * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org) + */ + + #define INITGUID + #include "kbdclass.h" + + static DRIVER_UNLOAD DriverUnload; + static DRIVER_DISPATCH ClassCreate; + static DRIVER_DISPATCH ClassClose; + static DRIVER_DISPATCH ClassCleanup; + static DRIVER_DISPATCH ClassRead; + static DRIVER_DISPATCH ClassDeviceControl; + static DRIVER_DISPATCH IrpStub; + static DRIVER_ADD_DEVICE ClassAddDevice; + static DRIVER_STARTIO ClassStartIo; + static DRIVER_CANCEL ClassCancelRoutine; + static NTSTATUS + HandleReadIrp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + BOOLEAN IsInStartIo); + + static VOID NTAPI + DriverUnload(IN PDRIVER_OBJECT DriverObject) + { + // nothing to do here yet + } + + static NTSTATUS NTAPI + ClassCreate( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + TRACE_(CLASS_NAME, "IRP_MJ_CREATE\n"); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + /* FIXME: open all associated Port devices */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + static NTSTATUS NTAPI + ClassClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + TRACE_(CLASS_NAME, "IRP_MJ_CLOSE\n"); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + /* FIXME: close all associated Port devices */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + static NTSTATUS NTAPI + ClassCleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + TRACE_(CLASS_NAME, "IRP_MJ_CLEANUP\n"); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + /* FIXME: cleanup all associated Port devices */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + static NTSTATUS NTAPI + ClassRead( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + KIRQL OldIrql; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "IRP_MJ_READ\n"); + + ASSERT(DeviceExtension->Common.IsClassDO); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(KEYBOARD_INPUT_DATA)) + { + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_BUFFER_TOO_SMALL; + } + + KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql); + Status = HandleReadIrp(DeviceObject, Irp, FALSE); + KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql); + return Status; + } + + static NTSTATUS NTAPI + ClassDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + //PCLASS_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status = STATUS_NOT_SUPPORTED; + + TRACE_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL\n"); + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + //DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: + case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: + case IOCTL_KEYBOARD_QUERY_INDICATORS: + case IOCTL_KEYBOARD_QUERY_TYPEMATIC: + { + /* FIXME: We hope that all devices will return the same result. + * Ask only the first one */ + PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead; + if (Head->Flink != Head) + { + /* We have at least one device */ + PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry); + IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(DevExt->DeviceObject, Irp); + } + break; + } + case IOCTL_KEYBOARD_SET_INDICATORS: + case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */ + { + /* Send it to all associated Port devices */ + PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead; + PLIST_ENTRY Entry = Head->Flink; + Status = STATUS_SUCCESS; + while (Entry != Head) + { + PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry); + NTSTATUS IntermediateStatus; + + IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp); + if (!NT_SUCCESS(IntermediateStatus)) + Status = IntermediateStatus; + Entry = Entry->Flink; + } + break; + } + default: + WARN_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; + } + + static NTSTATUS NTAPI + IrpStub( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + NTSTATUS Status = STATUS_NOT_SUPPORTED; + + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + { + /* Forward some IRPs to lower device */ + switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) + { + case IRP_MJ_PNP: + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + return ForwardIrpAndForget(DeviceObject, Irp); + default: + { + ERR_(CLASS_NAME, "Port DO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + ASSERT(FALSE); + } + } + } + else + { + ERR_(CLASS_NAME, "Class DO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + ASSERT(FALSE); + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + + static NTSTATUS + ReadRegistryEntries( + IN PUNICODE_STRING RegistryPath, + IN PCLASS_DRIVER_EXTENSION DriverExtension) + { + UNICODE_STRING ParametersRegistryKey; + RTL_QUERY_REGISTRY_TABLE Parameters[4]; + NTSTATUS Status; + + /* HACK: We don't support multiple devices with this disabled */ + ULONG DefaultConnectMultiplePorts = 1; + ULONG DefaultDataQueueSize = 0x64; + PCWSTR DefaultDeviceBaseName = L"KeyboardClass"; + + ParametersRegistryKey.Length = 0; + ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL); + ParametersRegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool, ParametersRegistryKey.MaximumLength, CLASS_TAG); + if (!ParametersRegistryKey.Buffer) + { + WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n"); + return STATUS_NO_MEMORY; + } + RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath); + RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters"); + ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL; + + RtlZeroMemory(Parameters, sizeof(Parameters)); + + Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[0].Name = L"ConnectMultiplePorts"; + Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts; + Parameters[0].DefaultType = REG_DWORD; + Parameters[0].DefaultData = &DefaultConnectMultiplePorts; + Parameters[0].DefaultLength = sizeof(ULONG); + + Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[1].Name = L"KeyboardDataQueueSize"; + Parameters[1].EntryContext = &DriverExtension->DataQueueSize; + Parameters[1].DefaultType = REG_DWORD; + Parameters[1].DefaultData = &DefaultDataQueueSize; + Parameters[1].DefaultLength = sizeof(ULONG); + + Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[2].Name = L"KeyboardDeviceBaseName"; + Parameters[2].EntryContext = &DriverExtension->DeviceBaseName; + Parameters[2].DefaultType = REG_SZ; + Parameters[2].DefaultData = (PVOID)DefaultDeviceBaseName; + Parameters[2].DefaultLength = 0; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + ParametersRegistryKey.Buffer, + Parameters, + NULL, + NULL); + + if (NT_SUCCESS(Status)) + { + /* Check values */ + if (DriverExtension->ConnectMultiplePorts != 0 + && DriverExtension->ConnectMultiplePorts != 1) + { + DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts; + } + if (DriverExtension->DataQueueSize == 0) + { + DriverExtension->DataQueueSize = DefaultDataQueueSize; + } + } + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* Registry path doesn't exist. Set defaults */ + DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts; + DriverExtension->DataQueueSize = DefaultDataQueueSize; + if (RtlCreateUnicodeString(&DriverExtension->DeviceBaseName, DefaultDeviceBaseName)) + Status = STATUS_SUCCESS; + else + Status = STATUS_NO_MEMORY; + } + + ExFreePoolWithTag(ParametersRegistryKey.Buffer, CLASS_TAG); + return Status; + } + + static NTSTATUS + CreateClassDeviceObject( + IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *ClassDO OPTIONAL) + { + PCLASS_DRIVER_EXTENSION DriverExtension; + ULONG DeviceId = 0; + ULONG PrefixLength; + UNICODE_STRING DeviceNameU; + PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */ + PDEVICE_OBJECT Fdo; + PCLASS_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "CreateClassDeviceObject(0x%p)\n", DriverObject); + + /* Create new device object */ + DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); + DeviceNameU.Length = 0; + DeviceNameU.MaximumLength = + wcslen(L"\\Device\\") * sizeof(WCHAR) /* "\Device\" */ + + DriverExtension->DeviceBaseName.Length /* "KeyboardClass" */ + + 4 * sizeof(WCHAR) /* Id between 0 and 9999 */ + + sizeof(UNICODE_NULL); /* Final NULL char */ + DeviceNameU.Buffer = ExAllocatePoolWithTag(PagedPool, DeviceNameU.MaximumLength, CLASS_TAG); + if (!DeviceNameU.Buffer) + { + WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n"); + return STATUS_NO_MEMORY; + } + Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\"); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->DeviceBaseName); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL); + DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)]; + while (DeviceId < 9999) + { + DeviceNameU.Length = (USHORT)(PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR)); + Status = IoCreateDevice( + DriverObject, + sizeof(CLASS_DEVICE_EXTENSION), + &DeviceNameU, + FILE_DEVICE_KEYBOARD, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &Fdo); + if (NT_SUCCESS(Status)) + goto cleanup; + else if (Status != STATUS_OBJECT_NAME_COLLISION) + { + WARN_(CLASS_NAME, "IoCreateDevice() failed with status 0x%08lx\n", Status); + goto cleanup; + } + DeviceId++; + } + WARN_(CLASS_NAME, "Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension->DeviceBaseName); + Status = STATUS_TOO_MANY_NAMES; + cleanup: + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(DeviceNameU.Buffer, CLASS_TAG); + return Status; + } + + DeviceExtension = (PCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION)); + DeviceExtension->Common.IsClassDO = TRUE; + DeviceExtension->DriverExtension = DriverExtension; + InitializeListHead(&DeviceExtension->ListHead); + KeInitializeSpinLock(&DeviceExtension->ListSpinLock); + KeInitializeSpinLock(&DeviceExtension->SpinLock); + DeviceExtension->InputCount = 0; + DeviceExtension->PortData = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA), CLASS_TAG); + if (!DeviceExtension->PortData) + { + ExFreePoolWithTag(DeviceNameU.Buffer, CLASS_TAG); + return STATUS_NO_MEMORY; + } + DeviceExtension->DeviceName = DeviceNameU.Buffer; + Fdo->Flags |= DO_POWER_PAGABLE; + Fdo->Flags |= DO_BUFFERED_IO; /* FIXME: Why is it needed for 1st stage setup? */ + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + /* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */ + RtlWriteRegistryValue( + RTL_REGISTRY_DEVICEMAP, + DriverExtension->DeviceBaseName.Buffer, + DeviceExtension->DeviceName, + REG_SZ, + DriverExtension->RegistryPath.Buffer, + DriverExtension->RegistryPath.MaximumLength); + + if (ClassDO) + *ClassDO = Fdo; + + return STATUS_SUCCESS; + } + + static NTSTATUS + FillEntries( + IN PDEVICE_OBJECT ClassDeviceObject, + IN PIRP Irp, + IN PKEYBOARD_INPUT_DATA DataStart, + IN SIZE_T NumberOfEntries) + { + NTSTATUS Status = STATUS_SUCCESS; + + if (ClassDeviceObject->Flags & DO_BUFFERED_IO) + { + RtlCopyMemory( + Irp->AssociatedIrp.SystemBuffer, + DataStart, + NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA)); + } + else if (ClassDeviceObject->Flags & DO_DIRECT_IO) + { + PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); + if (DestAddress) + { + RtlCopyMemory( + DestAddress, + DataStart, + NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA)); + } + else + Status = STATUS_UNSUCCESSFUL; + } + else + { + _SEH2_TRY + { + RtlCopyMemory( + Irp->UserBuffer, + DataStart, + NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + + return Status; + } + + static BOOLEAN NTAPI + ClassCallback( + IN PDEVICE_OBJECT ClassDeviceObject, + IN OUT PKEYBOARD_INPUT_DATA DataStart, + IN PKEYBOARD_INPUT_DATA DataEnd, + IN OUT PULONG ConsumedCount) + { + PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension; + KIRQL OldIrql; + SIZE_T InputCount = DataEnd - DataStart; + SIZE_T ReadSize; + + TRACE_(CLASS_NAME, "ClassCallback()\n"); + + ASSERT(ClassDeviceExtension->Common.IsClassDO); + + KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql); + if (InputCount > 0) + { + if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize) + { + /* + * We're exceeding the buffer, and data will be thrown away... + * FIXME: What could we do, as we are at DISPATCH_LEVEL? + */ + ReadSize = ClassDeviceExtension->DriverExtension->DataQueueSize - ClassDeviceExtension->InputCount; + } + else + ReadSize = InputCount; + + /* + * Move the input data from the port data queue to our class data + * queue. + */ + RtlCopyMemory( + &ClassDeviceExtension->PortData[ClassDeviceExtension->InputCount], + (PCHAR)DataStart, + sizeof(KEYBOARD_INPUT_DATA) * ReadSize); + + /* Move the counter up */ + ClassDeviceExtension->InputCount += ReadSize; + + (*ConsumedCount) += (ULONG)ReadSize; + + /* Complete pending IRP (if any) */ + if (ClassDeviceExtension->PendingIrp) + HandleReadIrp(ClassDeviceObject, ClassDeviceExtension->PendingIrp, FALSE); + } + KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql); + + TRACE_(CLASS_NAME, "Leaving ClassCallback()\n"); + return TRUE; + } + + /* Send IOCTL_INTERNAL_*_CONNECT to port */ + static NTSTATUS + ConnectPortDriver( + IN PDEVICE_OBJECT PortDO, + IN PDEVICE_OBJECT ClassDO) + { + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + CONNECT_DATA ConnectData; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "Connecting PortDO %p to ClassDO %p\n", PortDO, ClassDO); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + ConnectData.ClassDeviceObject = ClassDO; + ConnectData.ClassService = ClassCallback; + + Irp = IoBuildDeviceIoControlRequest( + IOCTL_INTERNAL_KEYBOARD_CONNECT, + PortDO, + &ConnectData, sizeof(CONNECT_DATA), + NULL, 0, + TRUE, &Event, &IoStatus); + if (!Irp) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = IoCallDriver(PortDO, Irp); + + if (Status == STATUS_PENDING) + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + else + IoStatus.Status = Status; + + if (NT_SUCCESS(IoStatus.Status)) + { + ObReferenceObject(PortDO); + ExInterlockedInsertTailList( + &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead, + &((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry, + &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock); + if (ClassDO->StackSize <= PortDO->StackSize) + { + /* Increase the stack size, in case we have to + * forward some IRPs to the port device object + */ + ClassDO->StackSize = PortDO->StackSize + 1; + } + } + + return IoStatus.Status; + } + + /* Send IOCTL_INTERNAL_*_DISCONNECT to port + destroy the Port DO */ + static VOID + DestroyPortDriver( + IN PDEVICE_OBJECT PortDO) + { + PPORT_DEVICE_EXTENSION DeviceExtension; + PCLASS_DEVICE_EXTENSION ClassDeviceExtension; + PCLASS_DRIVER_EXTENSION DriverExtension; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + KIRQL OldIrql; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "Destroying PortDO %p\n", PortDO); + + DeviceExtension = (PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension; + ClassDeviceExtension = DeviceExtension->ClassDO->DeviceExtension; + DriverExtension = IoGetDriverObjectExtension(PortDO->DriverObject, PortDO->DriverObject); + + /* Send IOCTL_INTERNAL_*_DISCONNECT */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest( + IOCTL_INTERNAL_KEYBOARD_DISCONNECT, + PortDO, + NULL, 0, + NULL, 0, + TRUE, &Event, &IoStatus); + if (Irp) + { + Status = IoCallDriver(PortDO, Irp); + if (Status == STATUS_PENDING) + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + } + + /* Remove from ClassDeviceExtension->ListHead list */ + KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql); + RemoveHeadList(DeviceExtension->ListEntry.Blink); + KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql); + + /* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */ + RtlDeleteRegistryValue( + RTL_REGISTRY_DEVICEMAP, + DriverExtension->DeviceBaseName.Buffer, + ClassDeviceExtension->DeviceName); + + if (DeviceExtension->LowerDevice) + IoDetachDevice(DeviceExtension->LowerDevice); + ObDereferenceObject(PortDO); + + if (!DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO) + { + ExFreePoolWithTag(ClassDeviceExtension->PortData, CLASS_TAG); + ExFreePoolWithTag((PVOID)ClassDeviceExtension->DeviceName, CLASS_TAG); + IoDeleteDevice(DeviceExtension->ClassDO); + } + + IoDeleteDevice(PortDO); + } + + static NTSTATUS NTAPI + ClassAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo) + { + PCLASS_DRIVER_EXTENSION DriverExtension; + PDEVICE_OBJECT Fdo = NULL; + PPORT_DEVICE_EXTENSION DeviceExtension = NULL; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "ClassAddDevice called. Pdo = 0x%p\n", Pdo); + + DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); + + if (Pdo == NULL) + /* We may get a NULL Pdo at the first call as we're a legacy driver. Ignore it */ + return STATUS_SUCCESS; + + /* Create new device object */ + Status = IoCreateDevice( + DriverObject, + sizeof(PORT_DEVICE_EXTENSION), + NULL, + Pdo->DeviceType, + Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0, + FALSE, + &Fdo); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "IoCreateDevice() failed with status 0x%08lx\n", Status); + goto cleanup; + } + IoSetStartIoAttributes(Fdo, TRUE, TRUE); + + DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, sizeof(PORT_DEVICE_EXTENSION)); + DeviceExtension->Common.IsClassDO = FALSE; + DeviceExtension->DeviceObject = Fdo; + DeviceExtension->PnpState = dsStopped; + Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); + goto cleanup; + } + if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE) + Fdo->Flags |= DO_POWER_PAGABLE; + if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO) + Fdo->Flags |= DO_BUFFERED_IO; + if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO) + Fdo->Flags |= DO_DIRECT_IO; + + if (DriverExtension->ConnectMultiplePorts) + DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject; + else + { + /* We need a new class device object for this Fdo */ + Status = CreateClassDeviceObject( + DriverObject, + &DeviceExtension->ClassDO); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "CreateClassDeviceObject() failed with status 0x%08lx\n", Status); + goto cleanup; + } + } + Status = ConnectPortDriver(Fdo, DeviceExtension->ClassDO); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "ConnectPortDriver() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + /* Register interface ; ignore the error (if any) as having + * a registred interface is not so important... */ + Status = IoRegisterDeviceInterface( + Pdo, + &GUID_DEVINTERFACE_KEYBOARD, + NULL, + &DeviceExtension->InterfaceName); + if (!NT_SUCCESS(Status)) + DeviceExtension->InterfaceName.Length = 0; + + return STATUS_SUCCESS; + + cleanup: + if (Fdo) + DestroyPortDriver(Fdo); + return Status; + } + + static VOID NTAPI + ClassCancelRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + PCLASS_DEVICE_EXTENSION ClassDeviceExtension = DeviceObject->DeviceExtension; + KIRQL OldIrql; + BOOLEAN wasQueued = FALSE; + + TRACE_(CLASS_NAME, "ClassCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp); + + ASSERT(ClassDeviceExtension->Common.IsClassDO); + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql); + + if (ClassDeviceExtension->PendingIrp == Irp) + { + ClassDeviceExtension->PendingIrp = NULL; + wasQueued = TRUE; + } + KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql); + + if (wasQueued) + { + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + { + /* Hm, this shouldn't happen */ + ASSERT(FALSE); + } + } + + static NTSTATUS + HandleReadIrp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + BOOLEAN IsInStartIo) + { + PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + KIRQL OldIrql; + + TRACE_(CLASS_NAME, "HandleReadIrp(DeviceObject %p, Irp %p)\n", DeviceObject, Irp); + + ASSERT(DeviceExtension->Common.IsClassDO); + + if (DeviceExtension->InputCount > 0) + { + SIZE_T NumberOfEntries; + + NumberOfEntries = MIN( + DeviceExtension->InputCount, + IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA)); + + Status = FillEntries( + DeviceObject, + Irp, + DeviceExtension->PortData, + NumberOfEntries); + + if (NT_SUCCESS(Status)) + { + if (DeviceExtension->InputCount > NumberOfEntries) + { + RtlMoveMemory( + &DeviceExtension->PortData[0], + &DeviceExtension->PortData[NumberOfEntries], + (DeviceExtension->InputCount - NumberOfEntries) * sizeof(KEYBOARD_INPUT_DATA)); + } + + DeviceExtension->InputCount -= NumberOfEntries; + + Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA); + } + + /* Go to next packet and complete this request */ + Irp->IoStatus.Status = Status; + + (VOID)IoSetCancelRoutine(Irp, NULL); + IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT); + DeviceExtension->PendingIrp = NULL; + } + else + { + IoAcquireCancelSpinLock(&OldIrql); + if (Irp->Cancel) + { + DeviceExtension->PendingIrp = NULL; + Status = STATUS_CANCELLED; + } + else + { + IoMarkIrpPending(Irp); + DeviceExtension->PendingIrp = Irp; + (VOID)IoSetCancelRoutine(Irp, ClassCancelRoutine); + Status = STATUS_PENDING; + } + IoReleaseCancelSpinLock(OldIrql); + } + return Status; + } + ++ static NTSTATUS NTAPI ++ ClassPnp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ PPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; ++ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); ++ OBJECT_ATTRIBUTES ObjectAttributes; ++ IO_STATUS_BLOCK Iosb; ++ NTSTATUS Status; ++ ++ switch (IrpSp->MinorFunction) ++ { ++ case IRP_MN_START_DEVICE: ++ Status = ForwardIrpAndWait(DeviceObject, Irp); ++ if (NT_SUCCESS(Status)) ++ { ++ InitializeObjectAttributes(&ObjectAttributes, ++ &DeviceExtension->InterfaceName, ++ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ++ NULL, ++ NULL); ++ ++ Status = ZwOpenFile(&DeviceExtension->FileHandle, ++ FILE_READ_DATA, ++ &ObjectAttributes, ++ &Iosb, ++ 0, ++ 0); ++ if (!NT_SUCCESS(Status)) ++ DeviceExtension->FileHandle = NULL; ++ } ++ else ++ DeviceExtension->FileHandle = NULL; ++ Irp->IoStatus.Status = Status; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return Status; ++ ++ case IRP_MN_REMOVE_DEVICE: ++ case IRP_MN_STOP_DEVICE: ++ if (DeviceExtension->FileHandle) ++ { ++ ZwClose(DeviceExtension->FileHandle); ++ DeviceExtension->FileHandle = NULL; ++ } ++ Status = STATUS_SUCCESS; ++ break; ++ ++ default: ++ Status = Irp->IoStatus.Status; ++ break; ++ } ++ ++ Irp->IoStatus.Status = Status; ++ if (NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED) ++ { ++ IoSkipCurrentIrpStackLocation(Irp); ++ return IoCallDriver(DeviceExtension->LowerDevice, Irp); ++ } ++ else ++ { ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return Status; ++ } ++ } ++ + static VOID NTAPI + ClassStartIo( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + KIRQL OldIrql; + + TRACE_(CLASS_NAME, "ClassStartIo(DeviceObject %p, Irp %p)\n", DeviceObject, Irp); + + ASSERT(DeviceExtension->Common.IsClassDO); + + KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql); + HandleReadIrp(DeviceObject, Irp, TRUE); + KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql); + } + + static VOID NTAPI + SearchForLegacyDrivers( + IN PDRIVER_OBJECT DriverObject, + IN PVOID Context, /* PCLASS_DRIVER_EXTENSION */ + IN ULONG Count) + { + UNICODE_STRING DeviceMapKeyU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP"); + PCLASS_DRIVER_EXTENSION DriverExtension; + UNICODE_STRING PortBaseName = { 0, 0, NULL }; + PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hDeviceMapKey = (HANDLE)-1; + HANDLE hPortKey = (HANDLE)-1; + ULONG Index = 0; + ULONG Size, ResultLength; + NTSTATUS Status; + + TRACE_(CLASS_NAME, "SearchForLegacyDrivers(%p %p %lu)\n", + DriverObject, Context, Count); + + if (Count != 1) + return; + DriverExtension = (PCLASS_DRIVER_EXTENSION)Context; + + /* Create port base name, by replacing Class by Port at the end of the class base name */ + Status = DuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DriverExtension->DeviceBaseName, + &PortBaseName); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "DuplicateUnicodeString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + PortBaseName.Length -= (sizeof(L"Class") - sizeof(UNICODE_NULL)); + RtlAppendUnicodeToString(&PortBaseName, L"Port"); + + /* Allocate memory */ + Size = sizeof(KEY_VALUE_BASIC_INFORMATION) + MAX_PATH; + KeyValueInformation = ExAllocatePoolWithTag(PagedPool, Size, CLASS_TAG); + if (!KeyValueInformation) + { + WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n"); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */ + InitializeObjectAttributes(&ObjectAttributes, &DeviceMapKeyU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + INFO_(CLASS_NAME, "HKLM\\HARDWARE\\DEVICEMAP is non-existent\n"); + Status = STATUS_SUCCESS; + goto cleanup; + } + else if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* Open sub key */ + InitializeObjectAttributes(&ObjectAttributes, &PortBaseName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceMapKey, NULL); + Status = ZwOpenKey(&hPortKey, KEY_QUERY_VALUE, &ObjectAttributes); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + INFO_(CLASS_NAME, "HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName); + Status = STATUS_SUCCESS; + goto cleanup; + } + else if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* Read each value name */ + while (ZwEnumerateValueKey(hPortKey, Index++, KeyValueBasicInformation, KeyValueInformation, Size, &ResultLength) == STATUS_SUCCESS) + { + UNICODE_STRING PortName; + PDEVICE_OBJECT PortDeviceObject = NULL; + PFILE_OBJECT FileObject = NULL; + + PortName.Length = PortName.MaximumLength = (USHORT)KeyValueInformation->NameLength; + PortName.Buffer = KeyValueInformation->Name; + + /* Open the device object pointer */ + Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", &PortName, Status); + continue; + } + INFO_(CLASS_NAME, "Legacy driver found\n"); + + Status = ClassAddDevice(DriverObject, PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + WARN_(CLASS_NAME, "ClassAddDevice() failed with status 0x%08lx\n", Status); + } + + /* A special hack for 1st stage setup: manually send start device to i8042prt */ + if (IsFirstStageSetup()) + Send8042StartDevice(DriverObject, PortDeviceObject); + } + + cleanup: + if (KeyValueInformation != NULL) + ExFreePoolWithTag(KeyValueInformation, CLASS_TAG); + if (hDeviceMapKey != (HANDLE)-1) + ZwClose(hDeviceMapKey); + if (hPortKey != (HANDLE)-1) + ZwClose(hPortKey); + } + + /* + * Standard DriverEntry method. + */ + NTSTATUS NTAPI + DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) + { + PCLASS_DRIVER_EXTENSION DriverExtension; + ULONG i; + NTSTATUS Status; + + Status = IoAllocateDriverObjectExtension( + DriverObject, + DriverObject, + sizeof(CLASS_DRIVER_EXTENSION), + (PVOID*)&DriverExtension); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status); + return Status; + } + RtlZeroMemory(DriverExtension, sizeof(CLASS_DRIVER_EXTENSION)); + + Status = DuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + RegistryPath, + &DriverExtension->RegistryPath); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "DuplicateUnicodeString() failed with status 0x%08lx\n", Status); + return Status; + } + + Status = ReadRegistryEntries(RegistryPath, DriverExtension); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "ReadRegistryEntries() failed with status 0x%08lx\n", Status); + return Status; + } + + if (DriverExtension->ConnectMultiplePorts == 1) + { + Status = CreateClassDeviceObject( + DriverObject, + &DriverExtension->MainClassDeviceObject); + if (!NT_SUCCESS(Status)) + { + WARN_(CLASS_NAME, "CreateClassDeviceObject() failed with status 0x%08lx\n", Status); + return Status; + } + } + + DriverObject->DriverExtension->AddDevice = ClassAddDevice; + DriverObject->DriverUnload = DriverUnload; + + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + DriverObject->MajorFunction[i] = IrpStub; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = ClassCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ClassClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup; + DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead; ++ DriverObject->MajorFunction[IRP_MJ_PNP] = ClassPnp; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget; + DriverObject->DriverStartIo = ClassStartIo; + + /* We will detect the legacy devices later */ + IoRegisterDriverReinitialization( + DriverObject, + SearchForLegacyDrivers, + DriverExtension); + + return STATUS_SUCCESS; + } diff --cc reactos/drivers/storage/class/class2/class2.c index 60268748ab9,00000000000,e6528c061f2..e6528c061f2 mode 100644,000000,100644..100644 --- a/reactos/drivers/storage/class/class2/class2.c +++ b/reactos/drivers/storage/class/class2/class2.c @@@@ -1,4839 -1,0 -1,5122 +1,5122 @@@@ + /* + * PROJECT: ReactOS Storage Stack + * LICENSE: DDK - see license.txt in the root dir + * FILE: drivers/storage/class2/class2.c + * PURPOSE: SCSI Class driver routines + * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK + */ + + #include + #include + #include + #include + #include + ++ /* Part of the drive letter hack */ ++ #include ++ #include ++ + //#define NDEBUG + #include + + #ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, ScsiClassGetInquiryData) + #pragma alloc_text(PAGE, ScsiClassInitialize) + #pragma alloc_text(PAGE, ScsiClassGetCapabilities) + #pragma alloc_text(PAGE, ScsiClassSendSrbSynchronous) + #pragma alloc_text(PAGE, ScsiClassClaimDevice) + #pragma alloc_text(PAGE, ScsiClassSendSrbAsynchronous) + #endif + + + #define INQUIRY_DATA_SIZE 2048 + #define START_UNIT_TIMEOUT 30 + + /* Disk layout used by Windows NT4 and earlier versions. */ + //#define DEFAULT_SECTORS_PER_TRACK 32 + //#define DEFAULT_TRACKS_PER_CYLINDER 64 + + /* Disk layout used by Windows 2000 and later versions. */ + #define DEFAULT_SECTORS_PER_TRACK 63 + #define DEFAULT_TRACKS_PER_CYLINDER 255 + + NTSTATUS + NTAPI + ScsiClassCreateClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + NTSTATUS + NTAPI + ScsiClassReadWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + NTSTATUS + NTAPI + ScsiClassDeviceControlDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ); + + NTSTATUS + NTAPI + ScsiClassDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ); + + NTSTATUS + NTAPI + ScsiClassInternalIoControl ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + NTSTATUS + NTAPI + ScsiClassShutdownFlush( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + NTSTATUS + NTAPI + DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ); + + // + // Class internal routines + // + + + VOID + NTAPI + RetryRequest( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PSCSI_REQUEST_BLOCK Srb, + BOOLEAN Associated + ); + + VOID + NTAPI + StartUnit( + IN PDEVICE_OBJECT DeviceObject + ); + + NTSTATUS + NTAPI + ClassIoCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ); + + NTSTATUS + NTAPI + ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + + + NTSTATUS + NTAPI + DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) + { + return STATUS_SUCCESS; + } + ++ /* The following hack to assign drive letters with a non-PnP storage stack */ ++ ++ typedef struct _CLASS_DEVICE_INFO { ++ ULONG Partitions; ++ ULONG DeviceNumber; ++ ULONG DriveNumber; ++ PDEVICE_OBJECT LowerDevice; ++ } CLASS_DEVICE_INFO, *PCLASS_DEVICE_INFO; ++ ++ typedef struct _CLASS_DRIVER_EXTENSION { ++ ULONG PortNumber; ++ CLASS_INIT_DATA InitializationData; ++ } CLASS_DRIVER_EXTENSION, *PCLASS_DRIVER_EXTENSION; ++ ++ VOID ++ NTAPI ++ ScsiClassRemoveDriveLetter(PCLASS_DEVICE_INFO DeviceInfo) ++ { ++ WCHAR Buffer1[100]; ++ UNICODE_STRING DriveLetterU; ++ ULONG Index; ++ ++ DriveLetterU.Buffer = Buffer1; ++ DriveLetterU.MaximumLength = sizeof(Buffer1); ++ ++ /* Delete the symbolic link to PhysicalDriveX */ ++ DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DeviceInfo->DriveNumber) * sizeof(WCHAR); ++ IoDeleteSymbolicLink(&DriveLetterU); ++ ++ DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU); ++ ++ for (Index = 0; Index < sizeof(ULONG) * 8; Index++) ++ { ++ if (DeviceInfo->Partitions & (1 << Index)) ++ { ++ DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR); ++ IoDeleteSymbolicLink(&DriveLetterU); ++ DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU); ++ } ++ } ++ } ++ ++ NTSTATUS ++ NTAPI ++ ScsiClassAssignDriveLetter(PCLASS_DEVICE_INFO DeviceInfo) ++ { ++ WCHAR Buffer1[100]; ++ WCHAR Buffer2[100]; ++ UNICODE_STRING DriveLetterU, PartitionU; ++ NTSTATUS Status; ++ ULONG Index, PartitionNumber, DeviceNumber, DriveNumber; ++ OBJECT_ATTRIBUTES ObjectAttributes; ++ IO_STATUS_BLOCK Iosb; ++ HANDLE PartitionHandle; ++ ++ /* We assume this device does not current have a drive letter */ ++ ++ Index = 0; ++ DeviceNumber = 0; ++ DriveNumber = 0; ++ PartitionNumber = 1; ++ DriveLetterU.Buffer = Buffer1; ++ DriveLetterU.MaximumLength = sizeof(Buffer1); ++ PartitionU.Buffer = Buffer2; ++ PartitionU.MaximumLength = sizeof(Buffer2); ++ ++ /* Determine the correct disk number */ ++ do ++ { ++ /* Check that the disk exists */ ++ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\HardDisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR); ++ InitializeObjectAttributes(&ObjectAttributes, ++ &PartitionU, ++ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ++ NULL, ++ NULL); ++ Status = ZwOpenFile(&PartitionHandle, ++ FILE_READ_ATTRIBUTES, ++ &ObjectAttributes, ++ &Iosb, ++ 0, ++ 0); ++ if (!NT_SUCCESS(Status)) ++ { ++ /* Return the last one that worked */ ++ DeviceNumber--; ++ } ++ else ++ { ++ ZwClose(PartitionHandle); ++ DeviceNumber++; ++ } ++ } while (Status == STATUS_SUCCESS); ++ ++ /* Determine the correct drive number */ ++ do ++ { ++ /* Check that the drive exists */ ++ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR); ++ InitializeObjectAttributes(&ObjectAttributes, ++ &PartitionU, ++ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ++ NULL, ++ NULL); ++ Status = ZwOpenFile(&PartitionHandle, ++ FILE_READ_ATTRIBUTES, ++ &ObjectAttributes, ++ &Iosb, ++ 0, ++ 0); ++ if (NT_SUCCESS(Status)) ++ { ++ ZwClose(PartitionHandle); ++ DriveNumber++; ++ } ++ } while (Status == STATUS_SUCCESS); ++ ++ /* Create the symbolic link to PhysicalDriveX */ ++ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR); ++ DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR); ++ ++ Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU); ++ if (!NT_SUCCESS(Status)) ++ { ++ /* Failed to create symbolic link */ ++ return Status; ++ } ++ ++ DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU); ++ ++ while (TRUE) ++ { ++ /* Check that the disk exists */ ++ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition%d", DeviceNumber, PartitionNumber) * sizeof(WCHAR); ++ InitializeObjectAttributes(&ObjectAttributes, ++ &PartitionU, ++ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ++ NULL, ++ NULL); ++ Status = ZwOpenFile(&PartitionHandle, ++ FILE_READ_ATTRIBUTES, ++ &ObjectAttributes, ++ &Iosb, ++ 0, ++ 0); ++ if (!NT_SUCCESS(Status)) ++ break; ++ else ++ { ++ ZwClose(PartitionHandle); ++ ++ /* Assign it a drive letter */ ++ do ++ { ++ DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR); ++ ++ Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU); ++ ++ Index++; ++ } while (Status != STATUS_SUCCESS); ++ ++ DeviceInfo->Partitions |= (1 << (Index - 1)); ++ ++ DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU); ++ PartitionNumber++; ++ } ++ } ++ ++ DeviceInfo->DeviceNumber = DeviceNumber; ++ DeviceInfo->DriveNumber = DriveNumber; ++ ++ return STATUS_SUCCESS; ++ } ++ ++ NTSTATUS ++ NTAPI ++ ScsiClassPlugPlay( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); ++ ++ if (IrpSp->MinorFunction == IRP_MN_START_DEVICE) ++ { ++ IoSkipCurrentIrpStackLocation(Irp); ++ return STATUS_SUCCESS; ++ } ++ else if (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE) ++ { ++ PCLASS_DEVICE_INFO DeviceInfo = DeviceObject->DeviceExtension; ++ ++ ScsiClassRemoveDriveLetter(DeviceInfo); ++ ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ ++ IoDetachDevice(DeviceInfo->LowerDevice); ++ IoDeleteDevice(DeviceObject); ++ return STATUS_SUCCESS; ++ } ++ else ++ { ++ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_NOT_SUPPORTED; ++ } ++ } ++ ++ NTSTATUS ++ NTAPI ++ ScsiClassAddDevice( ++ IN PDRIVER_OBJECT DriverObject, ++ IN PDEVICE_OBJECT PhysicalDeviceObject) ++ { ++ PCLASS_DRIVER_EXTENSION DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); ++ PCLASS_DEVICE_INFO DeviceInfo; ++ PDEVICE_OBJECT DeviceObject; ++ NTSTATUS Status; ++ ++ if (DriverExtension->InitializationData.ClassFindDevices(DriverObject, NULL, &DriverExtension->InitializationData, ++ PhysicalDeviceObject, DriverExtension->PortNumber)) ++ { ++ /* Create a device object */ ++ Status = IoCreateDevice(DriverObject, ++ sizeof(CLASS_DEVICE_INFO), ++ NULL, ++ FILE_DEVICE_DISK, ++ 0, ++ FALSE, ++ &DeviceObject); ++ if (!NT_SUCCESS(Status)) ++ { ++ return Status; ++ } ++ ++ DeviceInfo = DeviceObject->DeviceExtension; ++ RtlZeroMemory(DeviceInfo, sizeof(CLASS_DEVICE_INFO)); ++ ++ /* Attach it to the PDO */ ++ DeviceInfo->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); ++ ++ /* Check that the kernel has already assigned drive letters */ ++ if (KeLoaderBlock == NULL) ++ { ++ /* Assign a drive letter */ ++ ScsiClassAssignDriveLetter(DeviceInfo); ++ } ++ else ++ { ++ /* The kernel will handle it */ ++ } ++ ++ /* Move to the next port number */ ++ DriverExtension->PortNumber++; ++ } ++ else ++ { ++ /* Failed to find device */ ++ DbgPrint("FAILED TO FIND DEVICE!\n"); ++ } ++ ++ return STATUS_SUCCESS; ++ } ++ /* ---- End hack ---- */ ++ ++ + + ULONG + NTAPI + ScsiClassInitialize( + IN PVOID Argument1, + IN PVOID Argument2, + IN PCLASS_INIT_DATA InitializationData + ) + + /*++ + + Routine Description: + + This routine is called by a class driver during its + DriverEntry routine to initialize the driver. + + Arguments: + + Argument1 - Driver Object. + Argument2 - Registry Path. + InitializationData - Device-specific driver's initialization data. + + Return Value: + + A valid return code for a DriverEntry routine. + + --*/ + + { + + + PDRIVER_OBJECT DriverObject = Argument1; - ULONG portNumber = 0; + PDEVICE_OBJECT portDeviceObject; + NTSTATUS status; + STRING deviceNameString; + UNICODE_STRING unicodeDeviceName; + PFILE_OBJECT fileObject; + CCHAR deviceNameBuffer[256]; + BOOLEAN deviceFound = FALSE; ++ PCLASS_DRIVER_EXTENSION DriverExtension; + + DebugPrint((3,"\n\nSCSI Class Driver\n")); + + // + // Validate the length of this structure. This is effectively a + // version check. + // + + if (InitializationData->InitializationDataSize > sizeof(CLASS_INIT_DATA)) { + + DebugPrint((0,"ScsiClassInitialize: Class driver wrong version\n")); + return (ULONG) STATUS_REVISION_MISMATCH; + } + + // + // Check that each required entry is not NULL. Note that Shutdown, Flush and Error + // are not required entry points. + // + + if ((!InitializationData->ClassFindDevices) || + (!InitializationData->ClassDeviceControl) || + (!((InitializationData->ClassReadWriteVerification) || + (InitializationData->ClassStartIo)))) { + + DebugPrint((0, + "ScsiClassInitialize: Class device-specific driver missing required entry\n")); + + return (ULONG) STATUS_REVISION_MISMATCH; + } + ++ status = IoAllocateDriverObjectExtension(DriverObject, ++ DriverObject, ++ sizeof(CLASS_DRIVER_EXTENSION), ++ (PVOID *)&DriverExtension); ++ if (!NT_SUCCESS(status)) ++ return status; ++ ++ RtlCopyMemory(&DriverExtension->InitializationData, InitializationData, sizeof(CLASS_INIT_DATA)); ++ DriverExtension->PortNumber = 0; ++ + // + // Update driver object with entry points. + // + + DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose; + DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite; ++ DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiClassPlugPlay; + DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceControlDispatch; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush; + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush; ++ DriverObject->DriverExtension->AddDevice = ScsiClassAddDevice; + + if (InitializationData->ClassStartIo) { + DriverObject->DriverStartIo = InitializationData->ClassStartIo; + } + + // + // Open port driver controller device objects by name. + // + + do { + - sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber); ++ sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", DriverExtension->PortNumber); + + DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer)); + + RtlInitString(&deviceNameString, deviceNameBuffer); + + status = RtlAnsiStringToUnicodeString(&unicodeDeviceName, + &deviceNameString, + TRUE); + + if (!NT_SUCCESS(status)){ + break; + } + + status = IoGetDeviceObjectPointer(&unicodeDeviceName, + FILE_READ_ATTRIBUTES, + &fileObject, + &portDeviceObject); + + if (NT_SUCCESS(status)) { + + // + // Call the device-specific driver's FindDevice routine. + // + + if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData, - portDeviceObject, portNumber)) { ++ portDeviceObject, DriverExtension->PortNumber)) { + + deviceFound = TRUE; + } + } + + // + // Check next SCSI adapter. + // + - portNumber++; ++ DriverExtension->PortNumber++; + + } while(NT_SUCCESS(status)); + - return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE; ++ /* We don't want to fail init just because we don't have devices right now */ ++ return STATUS_SUCCESS; /*deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;*/ + } + + + NTSTATUS + NTAPI + ScsiClassCreateClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + + /*++ + + Routine Description: + + SCSI class driver create and close routine. This is called by the I/O system + when the device is opened or closed. + + Arguments: + + DriverObject - Pointer to driver object created by system. + + Irp - IRP involved. + + Return Value: + + Device-specific drivers return value or STATUS_SUCCESS. + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + + // + // Invoke the device-specific routine, if one exists. Otherwise complete + // with SUCCESS + // + + if (deviceExtension->ClassCreateClose) { + + return deviceExtension->ClassCreateClose(DeviceObject, Irp); + + } else { + Irp->IoStatus.Status = STATUS_SUCCESS; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(STATUS_SUCCESS); + } + } + + + + NTSTATUS + NTAPI + ScsiClassReadWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + + /*++ + + Routine Description: + + This is the system entry point for read and write requests. The device-specific handler is invoked + to perform any validation necessary. The number of bytes in the request are + checked against the maximum byte counts that the adapter supports and requests are broken up into + smaller sizes if necessary. + + Arguments: + + DeviceObject + Irp - IO request + + Return Value: + + NT Status + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + ULONG transferPages; + ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; + ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; + NTSTATUS status; + + if (DeviceObject->Flags & DO_VERIFY_VOLUME && + !(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { + + // + // if DO_VERIFY_VOLUME bit is set + // in device object flags, fail request. + // + + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + + Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, 0); + return STATUS_VERIFY_REQUIRED; + } + + // + // Invoke the device specific routine to do whatever it needs to verify + // this request. + // + + ASSERT(deviceExtension->ClassReadWriteVerification); + + status = deviceExtension->ClassReadWriteVerification(DeviceObject,Irp); + + if (!NT_SUCCESS(status)) { + + // + // It is up to the device specific driver to set the Irp status. + // + + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return status; + } else if (status == STATUS_PENDING) { + + IoMarkIrpPending(Irp); + return STATUS_PENDING; + } + + // + // Check for a zero length IO, as several macros will turn this into + // seemingly a 0xffffffff length request. + // + + if (transferByteCount == 0) { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + + } + + if (deviceExtension->ClassStartIo) { + + IoMarkIrpPending(Irp); + + IoStartPacket(DeviceObject, + Irp, + NULL, + NULL); + + return STATUS_PENDING; + } + + // + // Mark IRP with status pending. + // + + IoMarkIrpPending(Irp); + + // + // Add partition byte offset to make starting byte relative to + // beginning of disk. In addition, add in skew for DM Driver, if any. + // + + currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart + + deviceExtension->DMByteSkew); + + // + // Calculate number of pages in this transfer. + // + + transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), + currentIrpStack->Parameters.Read.Length); + + // + // Check if request length is greater than the maximum number of + // bytes that the hardware can transfer. + // + + if (currentIrpStack->Parameters.Read.Length > maximumTransferLength || + transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { + + DebugPrint((2,"ScsiClassReadWrite: Request greater than maximum\n")); + DebugPrint((2,"ScsiClassReadWrite: Maximum is %lx\n", + maximumTransferLength)); + DebugPrint((2,"ScsiClassReadWrite: Byte count is %lx\n", + currentIrpStack->Parameters.Read.Length)); + + transferPages = + deviceExtension->PortCapabilities->MaximumPhysicalPages - 1; + + if (maximumTransferLength > transferPages << PAGE_SHIFT ) { + maximumTransferLength = transferPages << PAGE_SHIFT; + } + + // + // Check that maximum transfer size is not zero. + // + + if (maximumTransferLength == 0) { + maximumTransferLength = PAGE_SIZE; + } + + // + // Mark IRP with status pending. + // + + IoMarkIrpPending(Irp); + + // + // Request greater than port driver maximum. + // Break up into smaller routines. + // + + ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength); + + + return STATUS_PENDING; + } + + // + // Build SRB and CDB for this IRP. + // + + ScsiClassBuildRequest(DeviceObject, Irp); + + // + // Return the results of the call to the port driver. + // + + return IoCallDriver(deviceExtension->PortDeviceObject, Irp); + + } // end ScsiClassReadWrite() + + + NTSTATUS + NTAPI + ScsiClassGetCapabilities( + IN PDEVICE_OBJECT PortDeviceObject, + OUT PIO_SCSI_CAPABILITIES *PortCapabilities + ) + + /*++ + + Routine Description: + + This routine builds and sends a request to the port driver to + get a pointer to a structure that describes the adapter's + capabilities/limitations. This routine is sychronous. + + Arguments: + + PortDeviceObject - Port driver device object representing the HBA. + + PortCapabilities - Location to store pointer to capabilities structure. + + Return Value: + + Nt status indicating the results of the operation. + + Notes: + + This routine should only be called at initialization time. + + --*/ + + { + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + + PAGED_CODE(); + + // + // Create notification event object to be used to signal the + // request completion. + // + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Build the synchronous request to be sent to the port driver + // to perform the request. + // + + irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES, + PortDeviceObject, + NULL, + 0, + PortCapabilities, + sizeof(PVOID), + FALSE, + &event, + &ioStatus); + + if (irp == NULL) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Pass request to port driver and wait for request to complete. + // + + status = IoCallDriver(PortDeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); + return(ioStatus.Status); + } + + return status; + + } // end ScsiClassGetCapabilities() + + + NTSTATUS + NTAPI + ScsiClassGetInquiryData( + IN PDEVICE_OBJECT PortDeviceObject, + OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo + ) + + /*++ + + Routine Description: + + This routine sends a request to a port driver to return + configuration information. Space for the information is + allocated by this routine. The caller is responsible for + freeing the configuration information. This routine is + synchronous. + + Arguments: + + PortDeviceObject - Port driver device object representing the HBA. + + ConfigInfo - Returns a pointer to the configuration information. + + Return Value: + + Nt status indicating the results of the operation. + + Notes: + + This routine should be called only at initialization time. + + --*/ + + { + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + PSCSI_ADAPTER_BUS_INFO buffer; + + PAGED_CODE(); + + buffer = ExAllocatePool(PagedPool, INQUIRY_DATA_SIZE); + *ConfigInfo = buffer; + + if (buffer == NULL) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // Create notification event object to be used to signal the inquiry + // request completion. + // + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Build the synchronous request to be sent to the port driver + // to perform the inquiries. + // + + irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA, + PortDeviceObject, + NULL, + 0, + buffer, + INQUIRY_DATA_SIZE, + FALSE, + &event, + &ioStatus); + + if (irp == NULL) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // Pass request to port driver and wait for request to complete. + // + + status = IoCallDriver(PortDeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); + status = ioStatus.Status; + } + + if (!NT_SUCCESS(status)) { + + // + // Free the buffer on an error. + // + + ExFreePool(buffer); + *ConfigInfo = NULL; + + } + + return status; + + } // end ScsiClassGetInquiryData() + + + NTSTATUS + NTAPI + ScsiClassReadDriveCapacity( + IN PDEVICE_OBJECT DeviceObject + ) + + /*++ + + Routine Description: + + This routine sends a READ CAPACITY to the requested device, updates + the geometry information in the device object and returns + when it is complete. This routine is synchronous. + + Arguments: + + DeviceObject - Supplies a pointer to the device object that represents + the device whose capacity is to be read. + + Return Value: + + Status is returned. + + --*/ + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + ULONG retries = 1; + ULONG lastSector; + PCDB cdb; + PREAD_CAPACITY_DATA readCapacityBuffer; + SCSI_REQUEST_BLOCK srb; + NTSTATUS status; + + // + // Allocate read capacity buffer from nonpaged pool. + // + + readCapacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned, + sizeof(READ_CAPACITY_DATA)); + + if (!readCapacityBuffer) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); + + // + // Build the read capacity CDB. + // + + srb.CdbLength = 10; + cdb = (PCDB)srb.Cdb; + + // + // Set timeout value from device extension. + // + + srb.TimeOutValue = deviceExtension->TimeOutValue; + + cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; + + Retry: + + status = ScsiClassSendSrbSynchronous(DeviceObject, + &srb, + readCapacityBuffer, + sizeof(READ_CAPACITY_DATA), + FALSE); + + if (NT_SUCCESS(status)) { + + // + // Copy sector size from read capacity buffer to device extension + // in reverse byte order. + // + + ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte0 = + ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte3; + + ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte1 = + ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte2; + + ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte2 = + ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte1; + + ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte3 = + ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte0; + + // + // Copy last sector in reverse byte order. + // + + ((PFOUR_BYTE)&lastSector)->Byte0 = + ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte3; + + ((PFOUR_BYTE)&lastSector)->Byte1 = + ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte2; + + ((PFOUR_BYTE)&lastSector)->Byte2 = + ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte1; + + ((PFOUR_BYTE)&lastSector)->Byte3 = + ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte0; + + // + // Calculate sector to byte shift. + // + + WHICH_BIT(deviceExtension->DiskGeometry->Geometry.BytesPerSector, deviceExtension->SectorShift); + + DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", + deviceExtension->DiskGeometry->Geometry.BytesPerSector)); + + DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", + lastSector + 1)); + + // + // Calculate media capacity in bytes. + // + + deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); + + // + // Calculate number of cylinders. + // + + deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(DEFAULT_SECTORS_PER_TRACK * DEFAULT_TRACKS_PER_CYLINDER)); + + deviceExtension->PartitionLength.QuadPart = + (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { + + // + // This device supports removable media. + // + + deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; + + } else { + + // + // Assume media type is fixed disk. + // + + deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; + } + + // + // Assume sectors per track are DEFAULT_SECTORS_PER_TRACK; + // + + deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = DEFAULT_SECTORS_PER_TRACK; + + // + // Assume tracks per cylinder (number of heads) is DEFAULT_TRACKS_PER_CYLINDER. + // + + deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = DEFAULT_TRACKS_PER_CYLINDER; + } + + if (status == STATUS_VERIFY_REQUIRED) { + + // + // Routine ScsiClassSendSrbSynchronous does not retry + // requests returned with this status. + // Read Capacities should be retried + // anyway. + // + + if (retries--) { + + // + // Retry request. + // + + goto Retry; + } + } + + if (!NT_SUCCESS(status)) { + + // + // If the read capacity fails, set the geometry to reasonable parameter + // so things don't fail at unexpected places. Zero the geometry + // except for the bytes per sector and sector shift. + // + + RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); + deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512; + deviceExtension->SectorShift = 9; + deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0; + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { + + // + // This device supports removable media. + // + + deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; + + } else { + + // + // Assume media type is fixed disk. + // + + deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; + } + } + + // + // Deallocate read capacity buffer. + // + + ExFreePool(readCapacityBuffer); + + return status; + + } // end ScsiClassReadDriveCapacity() + + + VOID + NTAPI + ScsiClassReleaseQueue( + IN PDEVICE_OBJECT DeviceObject + ) + + /*++ + + Routine Description: + + This routine issues an internal device control command + to the port driver to release a frozen queue. The call + is issued asynchronously as ScsiClassReleaseQueue will be invoked + from the IO completion DPC (and will have no context to + wait for a synchronous call to complete). + + Arguments: + + DeviceObject - The device object for the logical unit with + the frozen queue. + + Return Value: + + None. + + --*/ + { + PIO_STACK_LOCATION irpStack; + PIRP irp; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PCOMPLETION_CONTEXT context; + PSCSI_REQUEST_BLOCK srb; + KIRQL currentIrql; + + // + // Allocate context from nonpaged pool. + // + + context = ExAllocatePool(NonPagedPoolMustSucceed, + sizeof(COMPLETION_CONTEXT)); + + // + // Save the device object in the context for use by the completion + // routine. + // + + context->DeviceObject = DeviceObject; + srb = &context->Srb; + + // + // Zero out srb. + // + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + // + // Write length to SRB. + // + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set up SCSI bus address. + // + + srb->PathId = deviceExtension->PathId; + srb->TargetId = deviceExtension->TargetId; + srb->Lun = deviceExtension->Lun; + + // + // If this device is removable then flush the queue. This will also + // release it. + // + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { + + srb->Function = SRB_FUNCTION_FLUSH_QUEUE; + + } else { + + srb->Function = SRB_FUNCTION_RELEASE_QUEUE; + + } + + // + // Build the asynchronous request to be sent to the port driver. + // + + irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + + if(irp == NULL) { + + // + // We have no better way of dealing with this at the moment + // + + KeBugCheck((ULONG)0x0000002DL); + + } + + IoSetCompletionRoutine(irp, + (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, + context, + TRUE, + TRUE, + TRUE); + + irpStack = IoGetNextIrpStackLocation(irp); + + irpStack->MajorFunction = IRP_MJ_SCSI; + + srb->OriginalRequest = irp; + + // + // Store the SRB address in next stack for port driver. + // + + irpStack->Parameters.Scsi.Srb = srb; + + // + // Since this routine can cause outstanding requests to be completed, and + // calling a completion routine at < DISPATCH_LEVEL is dangerous (if they + // call IoStartNextPacket we will bugcheck) raise up to dispatch level before + // issuing the request + // + + currentIrql = KeGetCurrentIrql(); + + if(currentIrql < DISPATCH_LEVEL) { + KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); + IoCallDriver(deviceExtension->PortDeviceObject, irp); + KeLowerIrql(currentIrql); + } else { + IoCallDriver(deviceExtension->PortDeviceObject, irp); + } + + return; + + } // end ScsiClassReleaseQueue() + + + VOID + NTAPI + StartUnit( + IN PDEVICE_OBJECT DeviceObject + ) + + /*++ + + Routine Description: + + Send command to SCSI unit to start or power up. + Because this command is issued asynchronounsly, that is, without + waiting on it to complete, the IMMEDIATE flag is not set. This + means that the CDB will not return until the drive has powered up. + This should keep subsequent requests from being submitted to the + device before it has completely spun up. + This routine is called from the InterpretSense routine, when a + request sense returns data indicating that a drive must be + powered up. + + Arguments: + + DeviceObject - The device object for the logical unit with + the frozen queue. + + Return Value: + + None. + + --*/ + { + PIO_STACK_LOCATION irpStack; + PIRP irp; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PSCSI_REQUEST_BLOCK srb; + PCOMPLETION_CONTEXT context; + PCDB cdb; + + // + // Allocate Srb from nonpaged pool. + // + + context = ExAllocatePool(NonPagedPoolMustSucceed, + sizeof(COMPLETION_CONTEXT)); + + // + // Save the device object in the context for use by the completion + // routine. + // + + context->DeviceObject = DeviceObject; + srb = &context->Srb; + + // + // Zero out srb. + // + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + // + // Write length to SRB. + // + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set up SCSI bus address. + // + + srb->PathId = deviceExtension->PathId; + srb->TargetId = deviceExtension->TargetId; + srb->Lun = deviceExtension->Lun; + + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + // + // Set timeout value large enough for drive to spin up. + // + + srb->TimeOutValue = START_UNIT_TIMEOUT; + + // + // Set the transfer length. + // + + srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + // + // Build the start unit CDB. + // + + srb->CdbLength = 6; + cdb = (PCDB)srb->Cdb; + + cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; + cdb->START_STOP.Start = 1; + cdb->START_STOP.LogicalUnitNumber = srb->Lun; + + // + // Build the asynchronous request to be sent to the port driver. + // Since this routine is called from a DPC the IRP should always be + // available. + // + + irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + IoSetCompletionRoutine(irp, + (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, + context, + TRUE, + TRUE, + TRUE); + + irpStack = IoGetNextIrpStackLocation(irp); + irpStack->MajorFunction = IRP_MJ_SCSI; + srb->OriginalRequest = irp; + + // + // Store the SRB address in next stack for port driver. + // + + irpStack->Parameters.Scsi.Srb = srb; + + // + // Call the port driver with the IRP. + // + + IoCallDriver(deviceExtension->PortDeviceObject, irp); + + return; + + } // end StartUnit() + + + NTSTATUS + NTAPI + ScsiClassAsynchronousCompletion( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context + ) + /*++ + + Routine Description: + + This routine is called when an asynchronous I/O request + which was issused by the class driver completes. Examples of such requests + are release queue or START UNIT. This routine releases the queue if + necessary. It then frees the context and the IRP. + + Arguments: + + DeviceObject - The device object for the logical unit; however since this + is the top stack location the value is NULL. + + Irp - Supplies a pointer to the Irp to be processed. + + Context - Supplies the context to be used to process this request. + + Return Value: + + None. + + --*/ + + { + PCOMPLETION_CONTEXT context = Context; + PSCSI_REQUEST_BLOCK srb; + + srb = &context->Srb; + + // + // If this is an execute srb, then check the return status and make sure. + // the queue is not frozen. + // + + if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { + + // + // Check for a frozen queue. + // + + if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { + + // + // Unfreeze the queue getting the device object from the context. + // + + ScsiClassReleaseQueue(context->DeviceObject); + } + } + + // + // Free the context and the Irp. + // + + if (Irp->MdlAddress != NULL) { + MmUnlockPages(Irp->MdlAddress); + IoFreeMdl(Irp->MdlAddress); + + Irp->MdlAddress = NULL; + } + + ExFreePool(context); + IoFreeIrp(Irp); + + // + // Indicate the I/O system should stop processing the Irp completion. + // + + return STATUS_MORE_PROCESSING_REQUIRED; + + } // ScsiClassAsynchronousCompletion() + + + VOID + NTAPI + ScsiClassSplitRequest( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN ULONG MaximumBytes + ) + + /*++ + + Routine Description: + + Break request into smaller requests. Each new request will be the + maximum transfer size that the port driver can handle or if it + is the final request, it may be the residual size. + + The number of IRPs required to process this request is written in the + current stack of the original IRP. Then as each new IRP completes + the count in the original IRP is decremented. When the count goes to + zero, the original IRP is completed. + + Arguments: + + DeviceObject - Pointer to the class device object to be addressed. + + Irp - Pointer to Irp the orginal request. + + Return Value: + + None. + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; + LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; + PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + ULONG dataLength = MaximumBytes; + ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes; + ULONG i; + PSCSI_REQUEST_BLOCK srb; + + DebugPrint((2, "ScsiClassSplitRequest: Requires %d IRPs\n", irpCount)); + DebugPrint((2, "ScsiClassSplitRequest: Original IRP %lx\n", Irp)); + + // + // If all partial transfers complete successfully then the status and + // bytes transferred are already set up. Failing a partial-transfer IRP + // will set status to error and bytes transferred to 0 during + // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows + // asynchronous partial transfers. This is an optimization for the + // successful case. + // + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = transferByteCount; + + // + // Save number of IRPs to complete count on current stack + // of original IRP. + // + + nextIrpStack->Parameters.Others.Argument1 = (PVOID)(ULONG_PTR) irpCount; + + for (i = 0; i < irpCount; i++) { + + PIRP newIrp; + PIO_STACK_LOCATION newIrpStack; + + // + // Allocate new IRP. + // + + newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + + if (newIrp == NULL) { + + DebugPrint((1,"ScsiClassSplitRequest: Can't allocate Irp\n")); + + // + // If an Irp can't be allocated then the orginal request cannot + // be executed. If this is the first request then just fail the + // orginal request; otherwise just return. When the pending + // requests complete, they will complete the original request. + // In either case set the IRP status to failure. + // + + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + + if (i == 0) { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return; + } + + DebugPrint((2, "ScsiClassSplitRequest: New IRP %lx\n", newIrp)); + + // + // Write MDL address to new IRP. In the port driver the SRB data + // buffer field is used as an offset into the MDL, so the same MDL + // can be used for each partial transfer. This saves having to build + // a new MDL for each partial transfer. + // + + newIrp->MdlAddress = Irp->MdlAddress; + + // + // At this point there is no current stack. IoSetNextIrpStackLocation + // will make the first stack location the current stack so that the + // SRB address can be written there. + // + + IoSetNextIrpStackLocation(newIrp); + newIrpStack = IoGetCurrentIrpStackLocation(newIrp); + + newIrpStack->MajorFunction = currentIrpStack->MajorFunction; + newIrpStack->Parameters.Read.Length = dataLength; + newIrpStack->Parameters.Read.ByteOffset = startingOffset; + newIrpStack->DeviceObject = DeviceObject; + + // + // Build SRB and CDB. + // + + ScsiClassBuildRequest(DeviceObject, newIrp); + + // + // Adjust SRB for this partial transfer. + // + + newIrpStack = IoGetNextIrpStackLocation(newIrp); + + srb = newIrpStack->Parameters.Others.Argument1; + srb->DataBuffer = dataBuffer; + + // + // Write original IRP address to new IRP. + // + + newIrp->AssociatedIrp.MasterIrp = Irp; + + // + // Set the completion routine to ScsiClassIoCompleteAssociated. + // + + IoSetCompletionRoutine(newIrp, + ScsiClassIoCompleteAssociated, + srb, + TRUE, + TRUE, + TRUE); + + // + // Call port driver with new request. + // + + IoCallDriver(deviceExtension->PortDeviceObject, newIrp); + + // + // Set up for next request. + // + + dataBuffer = (PCHAR)dataBuffer + MaximumBytes; + + transferByteCount -= MaximumBytes; + + if (transferByteCount > MaximumBytes) { + + dataLength = MaximumBytes; + + } else { + + dataLength = transferByteCount; + } + + // + // Adjust disk byte offset. + // + + startingOffset.QuadPart = startingOffset.QuadPart + MaximumBytes; + } + + return; + + } // end ScsiClassSplitRequest() + + + NTSTATUS + NTAPI + ScsiClassIoComplete( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) + + /*++ + + Routine Description: + + This routine executes when the port driver has completed a request. + It looks at the SRB status in the completing SRB and if not success + it checks for valid request sense buffer information. If valid, the + info is used to update status with more precise message of type of + error. This routine deallocates the SRB. + + Arguments: + + DeviceObject - Supplies the device object which represents the logical + unit. + + Irp - Supplies the Irp which has completed. + + Context - Supplies a pointer to the SRB. + + Return Value: + + NT status + + --*/ + + { + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PSCSI_REQUEST_BLOCK srb = Context; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + NTSTATUS status; + BOOLEAN retry; + + // + // Check SRB status for success of completing request. + // + + if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { + + DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb)); + + // + // Release the queue if it is frozen. + // + + if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { + ScsiClassReleaseQueue(DeviceObject); + } + + retry = ScsiClassInterpretSenseInfo( + DeviceObject, + srb, + irpStack->MajorFunction, + irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, + MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4), + &status); + + // + // If the status is verified required and the this request + // should bypass verify required then retry the request. + // + + if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && + status == STATUS_VERIFY_REQUIRED) { + + status = STATUS_IO_DEVICE_ERROR; + retry = TRUE; + } + + if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { + + // + // Retry request. + // + + DebugPrint((1, "Retry request %lx\n", Irp)); + RetryRequest(DeviceObject, Irp, srb, FALSE); + return STATUS_MORE_PROCESSING_REQUIRED; + } + } else { + + // + // Set status for successful request. + // + + status = STATUS_SUCCESS; + + } // end if (SRB_STATUS(srb->SrbStatus) ... + + // + // Return SRB to list. + // + + ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead, + srb); + + // + // Set status in completing IRP. + // + + Irp->IoStatus.Status = status; + if ((NT_SUCCESS(status)) && (Irp->Flags & IRP_PAGING_IO)) { + ASSERT(Irp->IoStatus.Information); + } + + // + // Set the hard error if necessary. + // + + if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { + + // + // Store DeviceObject for filesystem, and clear + // in IoStatus.Information field. + // + + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + Irp->IoStatus.Information = 0; + } + + // + // If pending has be returned for this irp then mark the current stack as + // pending. + // + + if (Irp->PendingReturned) { + IoMarkIrpPending(Irp); + } + + if (deviceExtension->ClassStartIo) { + if (irpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) { + IoStartNextPacket(DeviceObject, FALSE); + } + } + + return status; + + } // end ScsiClassIoComplete() + + + NTSTATUS + NTAPI + ScsiClassIoCompleteAssociated( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) + + /*++ + + Routine Description: + + This routine executes when the port driver has completed a request. + It looks at the SRB status in the completing SRB and if not success + it checks for valid request sense buffer information. If valid, the + info is used to update status with more precise message of type of + error. This routine deallocates the SRB. This routine is used for + requests which were build by split request. After it has processed + the request it decrements the Irp count in the master Irp. If the + count goes to zero then the master Irp is completed. + + Arguments: + + DeviceObject - Supplies the device object which represents the logical + unit. + + Irp - Supplies the Irp which has completed. + + Context - Supplies a pointer to the SRB. + + Return Value: + + NT status + + --*/ + + { + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PSCSI_REQUEST_BLOCK srb = Context; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIRP originalIrp = Irp->AssociatedIrp.MasterIrp; + LONG irpCount; + NTSTATUS status; + BOOLEAN retry; + + // + // Check SRB status for success of completing request. + // + + if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { + + DebugPrint((2,"ScsiClassIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb)); + + // + // Release the queue if it is frozen. + // + + if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { + ScsiClassReleaseQueue(DeviceObject); + } + + retry = ScsiClassInterpretSenseInfo( + DeviceObject, + srb, + irpStack->MajorFunction, + irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, + MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4), + &status); + + // + // If the status is verified required and the this request + // should bypass verify required then retry the request. + // + + if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && + status == STATUS_VERIFY_REQUIRED) { + + status = STATUS_IO_DEVICE_ERROR; + retry = TRUE; + } + + if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { + + // + // Retry request. If the class driver has supplied a StartIo, + // call it directly for retries. + // + + DebugPrint((1, "Retry request %lx\n", Irp)); + + /* + if (!deviceExtension->ClassStartIo) { + RetryRequest(DeviceObject, Irp, srb, TRUE); + } else { + deviceExtension->ClassStartIo(DeviceObject, Irp); + } + */ + + RetryRequest(DeviceObject, Irp, srb, TRUE); + + return STATUS_MORE_PROCESSING_REQUIRED; + } + + + + } else { + + // + // Set status for successful request. + // + + status = STATUS_SUCCESS; + + } // end if (SRB_STATUS(srb->SrbStatus) ... + + // + // Return SRB to list. + // + + ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead, + srb); + + // + // Set status in completing IRP. + // + + Irp->IoStatus.Status = status; + + DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial xfer IRP %lx\n", Irp)); + + // + // Get next stack location. This original request is unused + // except to keep track of the completing partial IRPs so the + // stack location is valid. + // + + irpStack = IoGetNextIrpStackLocation(originalIrp); + + // + // Update status only if error so that if any partial transfer + // completes with error, then the original IRP will return with + // error. If any of the asynchronous partial transfer IRPs fail, + // with an error then the original IRP will return 0 bytes transfered. + // This is an optimization for successful transfers. + // + + if (!NT_SUCCESS(status)) { + + originalIrp->IoStatus.Status = status; + originalIrp->IoStatus.Information = 0; + + // + // Set the hard error if necessary. + // + + if (IoIsErrorUserInduced(status)) { + + // + // Store DeviceObject for filesystem. + // + + IoSetHardErrorOrVerifyDevice(originalIrp, DeviceObject); + } + } + + // + // Decrement and get the count of remaining IRPs. + // + + irpCount = InterlockedDecrement((PLONG)&irpStack->Parameters.Others.Argument1); + + DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial IRPs left %d\n", + irpCount)); + + // + // Old bug could cause irp count to negative + // + + ASSERT(irpCount >= 0); + + if (irpCount == 0) { + + // + // All partial IRPs have completed. + // + + DebugPrint((2, + "ScsiClassIoCompleteAssociated: All partial IRPs complete %lx\n", + originalIrp)); + + IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); + + // + // If the class driver has supplied a startio, start the + // next request. + // + + if (deviceExtension->ClassStartIo) { + IoStartNextPacket(DeviceObject, FALSE); + } + } + + // + // Deallocate IRP and indicate the I/O system should not attempt any more + // processing. + // + + IoFreeIrp(Irp); + return STATUS_MORE_PROCESSING_REQUIRED; + + } // end ScsiClassIoCompleteAssociated() + + + NTSTATUS + NTAPI + ScsiClassSendSrbSynchronous( + PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice + ) + + /*++ + + Routine Description: + + This routine is called by SCSI device controls to complete an + SRB and send it to the port driver synchronously (ie wait for + completion). The CDB is already completed along with the SRB CDB + size and request timeout value. + + Arguments: + + DeviceObject - Supplies the device object which represents the logical + unit. + + Srb - Supplies a partially initialized SRB. The SRB cannot come from zone. + + BufferAddress - Supplies the address of the buffer. + + BufferLength - Supplies the length in bytes of the buffer. + + WriteToDevice - Indicates the data should be transfer to the device. + + Return Value: + + Nt status indicating the final results of the operation. + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + IO_STATUS_BLOCK ioStatus; + ULONG controlType, mjFunction; + PIRP irp; + PIO_STACK_LOCATION irpStack; + KEVENT event; + PUCHAR senseInfoBuffer; + ULONG retryCount = MAXIMUM_RETRIES; + NTSTATUS status; + BOOLEAN retry; + LARGE_INTEGER dummy; + + PAGED_CODE(); + + dummy.QuadPart = 0; + + // + // Write length to SRB. + // + + Srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set SCSI bus address. + // + + Srb->PathId = deviceExtension->PathId; + Srb->TargetId = deviceExtension->TargetId; + Srb->Lun = deviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + // + // NOTICE: The SCSI-II specification indicates that this field should be + // zero; however, some target controllers ignore the logical unit number + // in the INDENTIFY message and only look at the logical unit number field + // in the CDB. + // + + Srb->Cdb[1] |= deviceExtension->Lun << 5; + + // + // Enable auto request sense. + // + + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + // + // Sense buffer is in aligned nonpaged pool. + // + + senseInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); + + if (senseInfoBuffer == NULL) { + + DebugPrint((1, + "ScsiClassSendSrbSynchronous: Can't allocate request sense buffer\n")); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Srb->SenseInfoBuffer = senseInfoBuffer; + Srb->DataBuffer = BufferAddress; + + // + // Start retries here. + // + + retry: + + // + // Set the event object to the unsignaled state. + // It will be used to signal request completion. + // + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Set controlType and Srb direction flags. + // + + if (BufferAddress != NULL) { + + if (WriteToDevice) { + + controlType = IOCTL_SCSI_EXECUTE_OUT; + Srb->SrbFlags = SRB_FLAGS_DATA_OUT; + mjFunction = IRP_MJ_WRITE; + + } else { + + controlType = IOCTL_SCSI_EXECUTE_IN; + Srb->SrbFlags = SRB_FLAGS_DATA_IN; + mjFunction = IRP_MJ_READ; + } + + } else { + + BufferLength = 0; + controlType = IOCTL_SCSI_EXECUTE_NONE; + Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; + mjFunction = IRP_MJ_FLUSH_BUFFERS; + } + + // + // Build device I/O control request with data transfer. + // + irp = IoBuildAsynchronousFsdRequest( + mjFunction, + deviceExtension->DeviceObject, + BufferAddress, + (BufferAddress) ? BufferLength : 0, + &dummy, + &ioStatus); + + if (irp == NULL) { + ExFreePool(senseInfoBuffer); + DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n")); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // Set event field + irp->UserEvent = &event; + + // + // Disable synchronous transfer for these requests. + // + + Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + // + // Set the transfer length. + // + + Srb->DataTransferLength = BufferLength; + + // + // Zero out status. + // + + Srb->ScsiStatus = Srb->SrbStatus = 0; + Srb->NextSrb = 0; + + // Set completion routine + IoSetCompletionRoutine( + irp, + ClassCompletionRoutine, + NULL, + TRUE, + TRUE, + TRUE); + + // + // Get next stack location. + // + + irpStack = IoGetNextIrpStackLocation(irp); + + irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + irpStack->Parameters.DeviceIoControl.IoControlCode = controlType; + + // + // Set up SRB for execute scsi request. Save SRB address in next stack + // for the port driver. + // + + irpStack->Parameters.Scsi.Srb = Srb; + + // + // Set up IRP Address. + // + + Srb->OriginalRequest = irp; + + // + // Call the port driver with the request and wait for it to complete. + // + + status = IoCallDriver(deviceExtension->PortDeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); + } + + // + // Check that request completed without error. + // + + if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) { + + // + // Release the queue if it is frozen. + // + + if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { + ScsiClassReleaseQueue(DeviceObject); + } + + // + // Update status and determine if request should be retried. + // + + retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IRP_MJ_SCSI, + 0, + MAXIMUM_RETRIES - retryCount, + &status); + + if (retry) { + + if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer) + ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) || + SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) { + + LARGE_INTEGER delay; + + // + // Delay for 2 seconds. + // + + delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 ); + + // + // Stall for a while to let the controller spinup. + // + + KeDelayExecutionThread(KernelMode, + FALSE, + &delay); + + } + + // + // If retries are not exhausted then retry this operation. + // + + if (retryCount--) { + goto retry; + } + } + + } else { + + status = STATUS_SUCCESS; + } + + ExFreePool(senseInfoBuffer); + return status; + + } // end ScsiClassSendSrbSynchronous() + + + BOOLEAN + NTAPI + ScsiClassInterpretSenseInfo( + IN PDEVICE_OBJECT DeviceObject, + IN PSCSI_REQUEST_BLOCK Srb, + IN UCHAR MajorFunctionCode, + IN ULONG IoDeviceCode, + IN ULONG RetryCount, + OUT NTSTATUS *Status + ) + + /*++ + + Routine Description: + + This routine interprets the data returned from the SCSI + request sense. It determines the status to return in the + IRP and whether this request can be retried. + + Arguments: + + DeviceObject - Supplies the device object associated with this request. + + Srb - Supplies the scsi request block which failed. + + MajorFunctionCode - Supplies the function code to be used for logging. + + IoDeviceCode - Supplies the device code to be used for logging. + + Status - Returns the status for the request. + + Return Value: + + BOOLEAN TRUE: Drivers should retry this request. + FALSE: Drivers should not retry this request. + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; + PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; + BOOLEAN retry = TRUE; + BOOLEAN logError = FALSE; + ULONG badSector = 0; + ULONG uniqueId = 0; + NTSTATUS logStatus; + ULONG readSector; + ULONG index; + PIO_ERROR_LOG_PACKET errorLogEntry; + #if DBG + ULONG i; + #endif + + + // + // Check that request sense buffer is valid. + // + + #if DBG + DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0])); + for (i = 1; i < 12; i++) { + DebugPrint((3,"%x ",Srb->Cdb[i])); + } + DebugPrint((3,"\n")); + #endif + + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && + Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) { + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n", + senseBuffer->ErrorCode)); + DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n", + senseBuffer->SenseKey)); + DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n", + senseBuffer->AdditionalSenseCode)); + DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n", + senseBuffer->AdditionalSenseCodeQualifier)); + + // + // Zero the additional sense code and additional sense code qualifier + // if they were not returned by the device. + // + + readSector = senseBuffer->AdditionalSenseLength + + FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength); + + if (readSector > Srb->SenseInfoBufferLength) { + readSector = Srb->SenseInfoBufferLength; + } + + if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) { + senseBuffer->AdditionalSenseCode = 0; + } + + if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) { + senseBuffer->AdditionalSenseCodeQualifier = 0; + } + + switch (senseBuffer->SenseKey & 0xf) { + + case SCSI_SENSE_NOT_READY: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n")); + *Status = STATUS_DEVICE_NOT_READY; + + switch (senseBuffer->AdditionalSenseCode) { + + case SCSI_ADSENSE_LUN_NOT_READY: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n")); + + switch (senseBuffer->AdditionalSenseCodeQualifier) { + + case SCSI_SENSEQ_BECOMING_READY: + + DebugPrint((1, "ScsiClassInterpretSenseInfo:" + " In process of becoming ready\n")); + break; + + case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: + + DebugPrint((1, "ScsiClassInterpretSenseInfo:" + " Manual intervention required\n")); + *Status = STATUS_NO_MEDIA_IN_DEVICE; + retry = FALSE; + break; + + case SCSI_SENSEQ_FORMAT_IN_PROGRESS: + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n")); + retry = FALSE; + break; + + case SCSI_SENSEQ_INIT_COMMAND_REQUIRED: + + default: + + DebugPrint((1, "ScsiClassInterpretSenseInfo:" + " Initializing command required\n")); + + // + // This sense code/additional sense code + // combination may indicate that the device + // needs to be started. Send an start unit if this + // is a disk device. + // + + if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) { + StartUnit(DeviceObject); + } + + break; + + } // end switch (senseBuffer->AdditionalSenseCodeQualifier) + + break; + + case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE: + + DebugPrint((1, + "ScsiClassInterpretSenseInfo:" + " No Media in device.\n")); + *Status = STATUS_NO_MEDIA_IN_DEVICE; + retry = FALSE; + + // + // signal autorun that there isn't any media in the device + // + + if((deviceExtension->MediaChangeEvent != NULL)&& + (!deviceExtension->MediaChangeNoMedia)) { + KeSetEvent(deviceExtension->MediaChangeEvent, + (KPRIORITY) 0, + FALSE); + DebugPrint((0, "ScsiClassInterpretSenseInfo:" + "Detected No Media In Device " + "[irp = 0x%lx]\n", Srb->OriginalRequest)); + deviceExtension->MediaChangeNoMedia = TRUE; + } + + break; + } // end switch (senseBuffer->AdditionalSenseCode) + + break; + + case SCSI_SENSE_DATA_PROTECT: + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n")); + *Status = STATUS_MEDIA_WRITE_PROTECTED; + retry = FALSE; + break; + + case SCSI_SENSE_MEDIUM_ERROR: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n")); + *Status = STATUS_DEVICE_DATA_ERROR; + + retry = FALSE; + logError = TRUE; + uniqueId = 256; + logStatus = 0;//IO_ERR_BAD_BLOCK; + break; + + case SCSI_SENSE_HARDWARE_ERROR: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n")); + *Status = STATUS_IO_DEVICE_ERROR; + + logError = TRUE; + uniqueId = 257; + logStatus = 0;//IO_ERR_CONTROLLER_ERROR; + + break; + + case SCSI_SENSE_ILLEGAL_REQUEST: + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n")); + *Status = STATUS_INVALID_DEVICE_REQUEST; + + switch (senseBuffer->AdditionalSenseCode) { + + case SCSI_ADSENSE_ILLEGAL_COMMAND: + DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n")); + retry = FALSE; + break; + + case SCSI_ADSENSE_ILLEGAL_BLOCK: + DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n")); + *Status = STATUS_NONEXISTENT_SECTOR; + retry = FALSE; + break; + + case SCSI_ADSENSE_INVALID_LUN: + DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n")); + *Status = STATUS_NO_SUCH_DEVICE; + retry = FALSE; + break; + + case SCSI_ADSENSE_MUSIC_AREA: + DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n")); + retry = FALSE; + break; + + case SCSI_ADSENSE_DATA_AREA: + DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n")); + retry = FALSE; + break; + + case SCSI_ADSENSE_VOLUME_OVERFLOW: + DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n")); + retry = FALSE; + break; + + case SCSI_ADSENSE_INVALID_CDB: + DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n")); + + // + // Check if write cache enabled. + // + + if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) { + + // + // Assume FUA is not supported. + // + + deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; + retry = TRUE; + + } else { + retry = FALSE; + } + + break; + + } // end switch (senseBuffer->AdditionalSenseCode) + + break; + + case SCSI_SENSE_UNIT_ATTENTION: + + switch (senseBuffer->AdditionalSenseCode) { + case SCSI_ADSENSE_MEDIUM_CHANGED: + DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n")); + + if(deviceExtension->MediaChangeEvent != NULL) { + + KeSetEvent(deviceExtension->MediaChangeEvent, + (KPRIORITY) 0, + FALSE); + DebugPrint((0, "ScsiClassInterpretSenseInfo:" + "New Media Found - Setting MediaChanged event" + " [irp = 0x%lx]\n", Srb->OriginalRequest)); + deviceExtension->MediaChangeNoMedia = FALSE; + + } + break; + + case SCSI_ADSENSE_BUS_RESET: + DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n")); + break; + + default: + DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n")); + break; + + } // end switch (senseBuffer->AdditionalSenseCode) + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA && + DeviceObject->Vpb->Flags & VPB_MOUNTED) { + + // + // Set bit to indicate that media may have changed + // and volume needs verification. + // + + DeviceObject->Flags |= DO_VERIFY_VOLUME; + + *Status = STATUS_VERIFY_REQUIRED; + retry = FALSE; + + } else { + + *Status = STATUS_IO_DEVICE_ERROR; + + } + + // + // A media change may have occured so increment the change + // count for the physical device + // + + physicalExtension->MediaChangeCount++; + + DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change " + "count for device %d is %d\n", + physicalExtension->DeviceNumber, + physicalExtension->MediaChangeCount)); + + break; + + case SCSI_SENSE_ABORTED_COMMAND: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n")); + *Status = STATUS_IO_DEVICE_ERROR; + break; + + case SCSI_SENSE_RECOVERED_ERROR: + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n")); + *Status = STATUS_SUCCESS; + retry = FALSE; + logError = TRUE; + uniqueId = 258; + + switch(senseBuffer->AdditionalSenseCode) { + case SCSI_ADSENSE_SEEK_ERROR: + case SCSI_ADSENSE_TRACK_ERROR: + logStatus = 0;//IO_ERR_SEEK_ERROR; + break; + + case SCSI_ADSENSE_REC_DATA_NOECC: + case SCSI_ADSENSE_REC_DATA_ECC: + logStatus = 0;//IO_RECOVERED_VIA_ECC; + break; + + default: + logStatus = 0;//IO_ERR_CONTROLLER_ERROR; + break; + + } // end switch(senseBuffer->AdditionalSenseCode) + + if (senseBuffer->IncorrectLength) { + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n")); + *Status = STATUS_INVALID_BLOCK_LENGTH ; + } + + break; + + case SCSI_SENSE_NO_SENSE: + + // + // Check other indicators. + // + + if (senseBuffer->IncorrectLength) { + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n")); + *Status = STATUS_INVALID_BLOCK_LENGTH ; + retry = FALSE; + + } else { + + DebugPrint((1, "ScsiClassInterpretSenseInfo: No specific sense key\n")); + *Status = STATUS_IO_DEVICE_ERROR; + retry = TRUE; + } + + break; + + default: + + DebugPrint((1, "ScsiClassInterpretSenseInfo: Unrecognized sense code\n")); + *Status = STATUS_IO_DEVICE_ERROR; + break; + + } // end switch (senseBuffer->SenseKey & 0xf) + + // + // Try to determine the bad sector from the inquiry data. + // + + if ((((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_READ || + ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY || + ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_WRITE)) { + + for (index = 0; index < 4; index++) { + badSector = (badSector << 8) | senseBuffer->Information[index]; + } + + readSector = 0; + for (index = 0; index < 4; index++) { + readSector = (readSector << 8) | Srb->Cdb[index+2]; + } + + index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) | + ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb; + + // + // Make sure the bad sector is within the read sectors. + // + + if (!(badSector >= readSector && badSector < readSector + index)) { + badSector = readSector; + } + } + + } else { + + // + // Request sense buffer not valid. No sense information + // to pinpoint the error. Return general request fail. + // + + DebugPrint((1,"ScsiClassInterpretSenseInfo: Request sense info not valid. SrbStatus %2x\n", + SRB_STATUS(Srb->SrbStatus))); + retry = TRUE; + + switch (SRB_STATUS(Srb->SrbStatus)) { + case SRB_STATUS_INVALID_LUN: + case SRB_STATUS_INVALID_TARGET_ID: + case SRB_STATUS_NO_DEVICE: + case SRB_STATUS_NO_HBA: + case SRB_STATUS_INVALID_PATH_ID: + *Status = STATUS_NO_SUCH_DEVICE; + retry = FALSE; + break; + + case SRB_STATUS_COMMAND_TIMEOUT: + case SRB_STATUS_ABORTED: + case SRB_STATUS_TIMEOUT: + + // + // Update the error count for the device. + // + + deviceExtension->ErrorCount++; + *Status = STATUS_IO_TIMEOUT; + break; + + case SRB_STATUS_SELECTION_TIMEOUT: + logError = TRUE; + logStatus = 0;//IO_ERR_NOT_READY; + uniqueId = 260; + *Status = STATUS_DEVICE_NOT_CONNECTED; + retry = FALSE; + break; + + case SRB_STATUS_DATA_OVERRUN: + *Status = STATUS_DATA_OVERRUN; + retry = FALSE; + break; + + case SRB_STATUS_PHASE_SEQUENCE_FAILURE: + + // + // Update the error count for the device. + // + + deviceExtension->ErrorCount++; + *Status = STATUS_IO_DEVICE_ERROR; + + // + // If there was phase sequence error then limit the number of + // retries. + // + + if (RetryCount > 1 ) { + retry = FALSE; + } + + break; + + case SRB_STATUS_REQUEST_FLUSHED: + + // + // If the status needs verification bit is set. Then set + // the status to need verification and no retry; otherwise, + // just retry the request. + // + + if (DeviceObject->Flags & DO_VERIFY_VOLUME ) { + + *Status = STATUS_VERIFY_REQUIRED; + retry = FALSE; + } else { + *Status = STATUS_IO_DEVICE_ERROR; + } + + break; + + case SRB_STATUS_INVALID_REQUEST: + + // + // An invalid request was attempted. + // + + *Status = STATUS_INVALID_DEVICE_REQUEST; + retry = FALSE; + break; + + case SRB_STATUS_UNEXPECTED_BUS_FREE: + case SRB_STATUS_PARITY_ERROR: + + // + // Update the error count for the device. + // + + deviceExtension->ErrorCount++; + + // + // Fall through to below. + // + + case SRB_STATUS_BUS_RESET: + *Status = STATUS_IO_DEVICE_ERROR; + break; + + case SRB_STATUS_ERROR: + + *Status = STATUS_IO_DEVICE_ERROR; + if (Srb->ScsiStatus == 0) { + + // + // This is some strange return code. Update the error + // count for the device. + // + + deviceExtension->ErrorCount++; + + } if (Srb->ScsiStatus == SCSISTAT_BUSY) { + + *Status = STATUS_DEVICE_NOT_READY; + + } if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) { + + *Status = STATUS_DEVICE_BUSY; + retry = FALSE; + + } + + break; + + default: + logError = TRUE; + logStatus = 0;//IO_ERR_CONTROLLER_ERROR; + uniqueId = 259; + *Status = STATUS_IO_DEVICE_ERROR; + break; + + } + + // + // If the error count has exceeded the error limit, then disable + // any tagged queuing, multiple requests per lu queueing + // and sychronous data transfers. + // + + if (deviceExtension->ErrorCount == 4) { + + // + // Clearing the no queue freeze flag prevents the port driver + // from sending multiple requests per logical unit. + // + + deviceExtension->SrbFlags &= ~(SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_NO_QUEUE_FREEZE); + + deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling tagged queuing and synchronous data tranfers.\n")); + + } else if (deviceExtension->ErrorCount == 8) { + + // + // If a second threshold is reached, disable disconnects. + // + + deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT; + DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling disconnects.\n")); + } + } + + // + // If there is a class specific error handler call it. + // + + if (deviceExtension->ClassError != NULL) { + + deviceExtension->ClassError(DeviceObject, + Srb, + Status, + &retry); + } + + // + // Log an error if necessary. + // + + if (logError) { + + errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( + DeviceObject, + sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG)); + + if (errorLogEntry == NULL) { + + // + // Return if no packet could be allocated. + // + + return retry; + + } + + if (retry && RetryCount < MAXIMUM_RETRIES) { + errorLogEntry->FinalStatus = STATUS_SUCCESS; + } else { + errorLogEntry->FinalStatus = *Status; + } + + // + // Calculate the device offset if there is a geometry. + // + + if (deviceExtension->DiskGeometry != NULL) { + + errorLogEntry->DeviceOffset.QuadPart = (LONGLONG) badSector; + errorLogEntry->DeviceOffset = RtlExtendedIntegerMultiply( + errorLogEntry->DeviceOffset, + deviceExtension->DiskGeometry->Geometry.BytesPerSector); + } + + errorLogEntry->ErrorCode = logStatus; + errorLogEntry->SequenceNumber = 0; + errorLogEntry->MajorFunctionCode = MajorFunctionCode; + errorLogEntry->IoControlCode = IoDeviceCode; + errorLogEntry->RetryCount = (UCHAR) RetryCount; + errorLogEntry->UniqueErrorValue = uniqueId; + errorLogEntry->DumpDataSize = 6 * sizeof(ULONG); + errorLogEntry->DumpData[0] = Srb->PathId; + errorLogEntry->DumpData[1] = Srb->TargetId; + errorLogEntry->DumpData[2] = Srb->Lun; + errorLogEntry->DumpData[3] = 0; + errorLogEntry->DumpData[4] = Srb->SrbStatus << 8 | Srb->ScsiStatus; + + if (senseBuffer != NULL) { + errorLogEntry->DumpData[5] = senseBuffer->SenseKey << 16 | + senseBuffer->AdditionalSenseCode << 8 | + senseBuffer->AdditionalSenseCodeQualifier; + + } + + // + // Write the error log packet. + // + + IoWriteErrorLogEntry(errorLogEntry); + } + + return retry; + + } // end ScsiClassInterpretSenseInfo() + + + VOID + NTAPI + RetryRequest( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PSCSI_REQUEST_BLOCK Srb, + BOOLEAN Associated + ) + + /*++ + + Routine Description: + + This routine reinitalizes the necessary fields, and sends the request + to the port driver. + + Arguments: + + DeviceObject - Supplies the device object associated with this request. + + Irp - Supplies the request to be retried. + + Srb - Supplies a Pointer to the SCSI request block to be retied. + + Assocaiated - Indicates this is an assocatied Irp created by split request. + + Return Value: + + None + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + ULONG transferByteCount; + + // + // Determine the transfer count of the request. If this is a read or a + // write then the transfer count is in the Irp stack. Otherwise assume + // the MDL contains the correct length. If there is no MDL then the + // transfer length must be zero. + // + + if (currentIrpStack->MajorFunction == IRP_MJ_READ || + currentIrpStack->MajorFunction == IRP_MJ_WRITE) { + + transferByteCount = currentIrpStack->Parameters.Read.Length; + + } else if (Irp->MdlAddress != NULL) { + + // + // Note this assumes that only read and write requests are spilt and + // other request do not need to be. If the data buffer address in + // the MDL and the SRB don't match then transfer length is most + // likely incorrect. + // + + ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress)); + transferByteCount = Irp->MdlAddress->ByteCount; + + } else { + + transferByteCount = 0; + } + + // + // Reset byte count of transfer in SRB Extension. + // + + Srb->DataTransferLength = transferByteCount; + + // + // Zero SRB statuses. + // + + Srb->SrbStatus = Srb->ScsiStatus = 0; + + // + // Set the no disconnect flag, disable synchronous data transfers and + // disable tagged queuing. This fixes some errors. + // + + Srb->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT | + SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + Srb->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE; + Srb->QueueTag = SP_UNTAGGED; + + // + // Set up major SCSI function. + // + + nextIrpStack->MajorFunction = IRP_MJ_SCSI; + + // + // Save SRB address in next stack for port driver. + // + + nextIrpStack->Parameters.Scsi.Srb = Srb; + + // + // Set up IoCompletion routine address. + // + + if (Associated) { + + IoSetCompletionRoutine(Irp, ScsiClassIoCompleteAssociated, Srb, TRUE, TRUE, TRUE); + + } else { + + IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE); + } + + // + // Pass the request to the port driver. + // + + (VOID)IoCallDriver(deviceExtension->PortDeviceObject, Irp); + + } // end RetryRequest() + + VOID + NTAPI + ScsiClassBuildRequest( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ) + + /*++ + + Routine Description: + + This routine allocates and builds an Srb for a read or write request. + The block address and length are supplied by the Irp. The retry count + is stored in the current stack for use by ScsiClassIoComplete which + processes these requests when they complete. The Irp is ready to be + passed to the port driver when this routine returns. + + Arguments: + + DeviceObject - Supplies the device object associated with this request. + + Irp - Supplies the request to be retried. + + Note: + + If the IRP is for a disk transfer, the byteoffset field + will already have been adjusted to make it relative to + the beginning of the disk. + + + Return Value: + + None. + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; + PSCSI_REQUEST_BLOCK srb; + PCDB cdb; + ULONG logicalBlockAddress; + USHORT transferBlocks; + + // + // Calculate relative sector address. + // + + logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, deviceExtension->SectorShift)); + + // + // Allocate an Srb. + // + + srb = ExAllocateFromNPagedLookasideList(&deviceExtension->SrbLookasideListHead); + + srb->SrbFlags = 0; + + // + // Write length to SRB. + // + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set up IRP Address. + // + + srb->OriginalRequest = Irp; + + // + // Set up target ID and logical unit number. + // + + srb->PathId = deviceExtension->PathId; + srb->TargetId = deviceExtension->TargetId; + srb->Lun = deviceExtension->Lun; + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + + // + // Save byte count of transfer in SRB Extension. + // + + srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; + + // + // Initialize the queue actions field. + // + + srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; + + // + // Queue sort key is Relative Block Address. + // + + srb->QueueSortKey = logicalBlockAddress; + + // + // Indicate auto request sense by specifying buffer and size. + // + + srb->SenseInfoBuffer = deviceExtension->SenseData; + srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + // + // Set timeout value of one unit per 64k bytes of data. + // + + srb->TimeOutValue = ((srb->DataTransferLength + 0xFFFF) >> 16) * + deviceExtension->TimeOutValue; + + // + // Zero statuses. + // + + srb->SrbStatus = srb->ScsiStatus = 0; + srb->NextSrb = 0; + + // + // Indicate that 10-byte CDB's will be used. + // + + srb->CdbLength = 10; + + // + // Fill in CDB fields. + // + + cdb = (PCDB)srb->Cdb; + + // + // Zero 12 bytes for Atapi Packets + // + + RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); + + cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; + transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift); + + // + // Move little endian values into CDB in big endian format. + // + + cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; + cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; + cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; + cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; + + cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; + cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; + + // + // Set transfer direction flag and Cdb command. + // + + if (currentIrpStack->MajorFunction == IRP_MJ_READ) { + + DebugPrint((3, "ScsiClassBuildRequest: Read Command\n")); + + srb->SrbFlags |= SRB_FLAGS_DATA_IN; + cdb->CDB10.OperationCode = SCSIOP_READ; + + } else { + + DebugPrint((3, "ScsiClassBuildRequest: Write Command\n")); + + srb->SrbFlags |= SRB_FLAGS_DATA_OUT; + cdb->CDB10.OperationCode = SCSIOP_WRITE; + } + + // + // If this is not a write-through request, then allow caching. + // + + if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) { + + srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE; + + } else { + + // + // If write caching is enable then force media access in the + // cdb. + // + + if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) { + cdb->CDB10.ForceUnitAccess = TRUE; + } + } + + // + // Or in the default flags from the device object. + // + + srb->SrbFlags |= deviceExtension->SrbFlags; + + // + // Set up major SCSI function. + // + + nextIrpStack->MajorFunction = IRP_MJ_SCSI; + + // + // Save SRB address in next stack for port driver. + // + + nextIrpStack->Parameters.Scsi.Srb = srb; + + // + // Save retry count in current IRP stack. + // + + currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; + + // + // Set up IoCompletion routine address. + // + + IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, TRUE); + + return; + + } // end ScsiClassBuildRequest() + + ULONG + NTAPI + ScsiClassModeSense( + IN PDEVICE_OBJECT DeviceObject, + IN PCHAR ModeSenseBuffer, + IN ULONG Length, + IN UCHAR PageMode + ) + + /*++ + + Routine Description: + + This routine sends a mode sense command to a target ID and returns + when it is complete. + + Arguments: + + DeviceObject - Supplies the device object associated with this request. + + ModeSenseBuffer - Supplies a buffer to store the sense data. + + Length - Supplies the length in bytes of the mode sense buffer. + + PageMode - Supplies the page or pages of mode sense data to be retrived. + + Return Value: + + Length of the transferred data is returned. + + --*/ + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PCDB cdb; + SCSI_REQUEST_BLOCK srb; + ULONG retries = 1; + NTSTATUS status; + + RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); + + // + // Build the MODE SENSE CDB. + // + + srb.CdbLength = 6; + cdb = (PCDB)srb.Cdb; + + // + // Set timeout value from device extension. + // + + srb.TimeOutValue = deviceExtension->TimeOutValue; + + cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; + cdb->MODE_SENSE.PageCode = PageMode; + cdb->MODE_SENSE.AllocationLength = (UCHAR)Length; + + Retry: + + status = ScsiClassSendSrbSynchronous(DeviceObject, + &srb, + ModeSenseBuffer, + Length, + FALSE); + + + if (status == STATUS_VERIFY_REQUIRED) { + + // + // Routine ScsiClassSendSrbSynchronous does not retry requests returned with + // this status. MODE SENSE commands should be retried anyway. + // + + if (retries--) { + + // + // Retry request. + // + + goto Retry; + } + + } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) { + status = STATUS_SUCCESS; + } + + if (NT_SUCCESS(status)) { + return(srb.DataTransferLength); + } else { + return(0); + } + + } // end ScsiClassModeSense() + + + PVOID + NTAPI + ScsiClassFindModePage( + IN PCHAR ModeSenseBuffer, + IN ULONG Length, + IN UCHAR PageMode, + IN BOOLEAN Use6Byte + ) + + /*++ + + Routine Description: + + This routine scans through the mode sense data and finds the requested + mode sense page code. + + Arguments: + ModeSenseBuffer - Supplies a pointer to the mode sense data. + + Length - Indicates the length of valid data. + + PageMode - Supplies the page mode to be searched for. + + Use6Byte - Indicates whether 6 or 10 byte mode sense was used. + + Return Value: + + A pointer to the the requested mode page. If the mode page was not found + then NULL is return. + + --*/ + { + PUCHAR limit; + ULONG parameterHeaderLength; + + limit = (PUCHAR)ModeSenseBuffer + Length; + parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10); + + + // + // Skip the mode select header and block descriptors. + // + + if (Length < parameterHeaderLength) { + return(NULL); + } + + + + ModeSenseBuffer += parameterHeaderLength + ((Use6Byte) ? ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength : + ((PMODE_PARAMETER_HEADER10) ModeSenseBuffer)->BlockDescriptorLength[1]); + + // + // ModeSenseBuffer now points at pages. Walk the pages looking for the + // requested page until the limit is reached. + // + + + while ((PUCHAR)ModeSenseBuffer < limit) { + + if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) { + return(ModeSenseBuffer); + } + + // + // Advance to the next page. + // + + ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength + 2; + } + + return(NULL); + } + + NTSTATUS + NTAPI + ScsiClassSendSrbAsynchronous( + PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PIRP Irp, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice + ) + /*++ + + Routine Description: + + This routine takes a partially built Srb and an Irp and sends it down to + the port driver. + + Arguments: + DeviceObject - Supplies the device object for the orginal request. + + Srb - Supplies a paritally build ScsiRequestBlock. In particular, the + CDB and the SRB timeout value must be filled in. The SRB must not be + allocated from zone. + + Irp - Supplies the requesting Irp. + + BufferAddress - Supplies a pointer to the buffer to be transfered. + + BufferLength - Supplies the length of data transfer. + + WriteToDevice - Indicates the data transfer will be from system memory to + device. + + Return Value: + + Returns STATUS_INSUFFICIENT_RESOURCES or the status of IoCallDriver. + + --*/ + { + + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION irpStack; + + PAGED_CODE(); + + // + // Write length to SRB. + // + + Srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set SCSI bus address. + // + + Srb->PathId = deviceExtension->PathId; + Srb->TargetId = deviceExtension->TargetId; + Srb->Lun = deviceExtension->Lun; + + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + // + // This is a violation of the SCSI spec but it is required for + // some targets. + // + + Srb->Cdb[1] |= deviceExtension->Lun << 5; + + // + // Indicate auto request sense by specifying buffer and size. + // + + Srb->SenseInfoBuffer = deviceExtension->SenseData; + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + Srb->DataBuffer = BufferAddress; + + if (BufferAddress != NULL) { + + // + // Build Mdl if necessary. + // + + if (Irp->MdlAddress == NULL) { + + if (IoAllocateMdl(BufferAddress, + BufferLength, + FALSE, + FALSE, + Irp) == NULL) { + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + MmBuildMdlForNonPagedPool(Irp->MdlAddress); + + } else { + + // + // Make sure the buffer requested matches the MDL. + // + + ASSERT(BufferAddress == MmGetMdlVirtualAddress(Irp->MdlAddress)); + } + + // + // Set read flag. + // + + Srb->SrbFlags = WriteToDevice ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN; + + } else { + + // + // Clear flags. + // + + Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; + } + + // + // Disable synchronous transfer for these requests. + // + + Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + // + // Set the transfer length. + // + + Srb->DataTransferLength = BufferLength; + + // + // Zero out status. + // + + Srb->ScsiStatus = Srb->SrbStatus = 0; + + Srb->NextSrb = 0; + + // + // Save a few parameters in the current stack location. + // + + irpStack = IoGetCurrentIrpStackLocation(Irp); + + // + // Save retry count in current Irp stack. + // + + irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; + + // + // Set up IoCompletion routine address. + // + + IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE); + + // + // Get next stack location and + // set major function code. + // + + irpStack = IoGetNextIrpStackLocation(Irp); + + irpStack->MajorFunction = IRP_MJ_SCSI; + + // + // Save SRB address in next stack for port driver. + // + + irpStack->Parameters.Scsi.Srb = Srb; + + // + // Set up Irp Address. + // + + Srb->OriginalRequest = Irp; + + // + // Call the port driver to process the request. + // + + return(IoCallDriver(deviceExtension->PortDeviceObject, Irp)); + + } + + + NTSTATUS + NTAPI + ScsiClassDeviceControlDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ) + + /*++ + + Routine Description: + + The routine is the common class driver device control dispatch entry point. + This routine is invokes the device-specific drivers DeviceControl routine, + (which may call the Class driver's common DeviceControl routine). + + Arguments: + + DeviceObject - Supplies a pointer to the device object for this request. + + Irp - Supplies the Irp making the request. + + Return Value: + + Returns the status returned from the device-specific driver. + + --*/ + + { + + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + + + // + // Call the class specific driver DeviceControl routine. + // If it doesn't handle it, it will call back into ScsiClassDeviceControl. + // + + ASSERT(deviceExtension->ClassDeviceControl); + + return deviceExtension->ClassDeviceControl(DeviceObject,Irp); + } + + + NTSTATUS + NTAPI + ScsiClassDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ) + /*++ + + Routine Description: + + The routine is the common class driver device control dispatch function. + This routine is called by a class driver when it get an unrecognized + device control request. This routine will perform the correct action for + common requests such as lock media. If the device request is unknown it + passed down to the next level. + + Arguments: + + DeviceObject - Supplies a pointer to the device object for this request. + + Irp - Supplies the Irp making the request. + + Return Value: + + Returns back a STATUS_PENDING or a completion status. + + --*/ + + { + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PIO_STACK_LOCATION nextStack; + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PSCSI_REQUEST_BLOCK srb; + PCDB cdb; + NTSTATUS status; + ULONG modifiedIoControlCode; + + if (irpStack->Parameters.DeviceIoControl.IoControlCode == + IOCTL_STORAGE_RESET_DEVICE) { + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_UNSUCCESSFUL; + goto SetStatusAndReturn; + } + + // + // If this is a pass through I/O control, set the minor function code + // and device address and pass it to the port driver. + // + + if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH + || irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) { + + PSCSI_PASS_THROUGH scsiPass; + + nextStack = IoGetNextIrpStackLocation(Irp); + + // + // Validiate the user buffer. + // + + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)){ + + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_INVALID_PARAMETER; + goto SetStatusAndReturn; + } + + // + // Force the SCSI address to the correct value. + // + + scsiPass = Irp->AssociatedIrp.SystemBuffer; + scsiPass->PathId = deviceExtension->PathId; + scsiPass->TargetId = deviceExtension->TargetId; + scsiPass->Lun = deviceExtension->Lun; + + // + // NOTICE: The SCSI-II specificaiton indicates that this field + // should be zero; however, some target controllers ignore the logical + // unit number in the INDENTIFY message and only look at the logical + // unit number field in the CDB. + // + + scsiPass->Cdb[1] |= deviceExtension->Lun << 5; + + nextStack->Parameters = irpStack->Parameters; + nextStack->MajorFunction = irpStack->MajorFunction; + nextStack->MinorFunction = IRP_MN_SCSI_CLASS; + + status = IoCallDriver(deviceExtension->PortDeviceObject, Irp); + goto SetStatusAndReturn; + } + + if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS) { + + PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer; + + if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(SCSI_ADDRESS)) { + + // + // Indicate unsuccessful status and no data transferred. + // + + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_BUFFER_TOO_SMALL; + goto SetStatusAndReturn; + + } + + scsiAddress->Length = sizeof(SCSI_ADDRESS); + scsiAddress->PortNumber = deviceExtension->PortNumber; + scsiAddress->PathId = deviceExtension->PathId; + scsiAddress->TargetId = deviceExtension->TargetId; + scsiAddress->Lun = deviceExtension->Lun; + Irp->IoStatus.Information = sizeof(SCSI_ADDRESS); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_SUCCESS; + goto SetStatusAndReturn; + } + + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); + + if (srb == NULL) { + + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_INSUFFICIENT_RESOURCES; + goto SetStatusAndReturn; + } + + // + // Write zeros to Srb. + // + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + cdb = (PCDB)srb->Cdb; + + // + // Change the device type to disk for the switch statement. + // + + modifiedIoControlCode = (irpStack->Parameters.DeviceIoControl.IoControlCode + & ~0xffff0000) | (IOCTL_DISK_BASE << 16); + + switch (modifiedIoControlCode) { + + case IOCTL_DISK_CHECK_VERIFY: { + + PIRP irp2 = NULL; + PIO_STACK_LOCATION newStack; + + DebugPrint((1,"ScsiDeviceIoControl: Check verify\n")); + + // + // If a buffer for a media change count was provided, make sure it's + // big enough to hold the result + // + + if(irpStack->Parameters.DeviceIoControl.OutputBufferLength) { + + // + // If the buffer is too small to hold the media change count + // then return an error to the caller + // + + if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(ULONG)) { + + DebugPrint((3,"ScsiDeviceIoControl: media count " + "buffer too small\n")); + + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = 0; + ExFreePool(srb); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_BUFFER_TOO_SMALL; + goto SetStatusAndReturn; + + } + + // + // The caller has provided a valid buffer. Allocate an additional + // irp and stick the CheckVerify completion routine on it. We will + // then send this down to the port driver instead of the irp the + // caller sent in + // + + DebugPrint((2,"ScsiDeviceIoControl: Check verify wants " + "media count\n")); + + // + // Allocate a new irp to send the TestUnitReady to the port driver + // + + irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE); + + if(irp2 == NULL) { + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + ExFreePool(srb); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_INSUFFICIENT_RESOURCES; + goto SetStatusAndReturn; + + break; + } + + irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; + IoSetNextIrpStackLocation(irp2); + + // + // Set the top stack location and shove the master Irp into the + // top location + // + + newStack = IoGetCurrentIrpStackLocation(irp2); + newStack->Parameters.Others.Argument1 = Irp; + newStack->DeviceObject = DeviceObject; + + // + // Stick the check verify completion routine onto the stack + // and prepare the irp for the port driver + // + + IoSetCompletionRoutine(irp2, + ScsiClassCheckVerifyComplete, + NULL, + TRUE, + TRUE, + TRUE); + + IoSetNextIrpStackLocation(irp2); + newStack = IoGetCurrentIrpStackLocation(irp2); + newStack->DeviceObject = DeviceObject; + + // + // Mark the master irp as pending - whether the lower level + // driver completes it immediately or not this should allow it + // to go all the way back up. + // + + IoMarkIrpPending(Irp); + + Irp = irp2; + + } + + // + // Test Unit Ready + // + + srb->CdbLength = 6; + cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + + // + // Since this routine will always hand the request to the + // port driver if there isn't a data transfer to be done + // we don't have to worry about completing the request here + // on an error + // + + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + + break; + } + + case IOCTL_DISK_MEDIA_REMOVAL: { + + PPREVENT_MEDIA_REMOVAL MediaRemoval = Irp->AssociatedIrp.SystemBuffer; + + // + // Prevent/Allow media removal. + // + + DebugPrint((3,"DiskIoControl: Prevent/Allow media removal\n")); + + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < + sizeof(PREVENT_MEDIA_REMOVAL)) { + + // + // Indicate unsuccessful status and no data transferred. + // + + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = 0; + ExFreePool(srb); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_BUFFER_TOO_SMALL; + goto SetStatusAndReturn; + } + + // + // Get physical device extension. This is where the + // lock count is stored. + // + + deviceExtension = deviceExtension->PhysicalDevice->DeviceExtension; + + // + // If command succeeded then increment or decrement lock counter. + // + + if (MediaRemoval->PreventMediaRemoval) { + + // + // This is a lock command. Reissue the command in case bus or device + // was reset and lock cleared. + // + + InterlockedIncrement(&deviceExtension->LockCount); + + DebugPrint((1, + "ScsiClassDeviceControl: Lock media, lock count %x on disk %x\n", + deviceExtension->LockCount, + deviceExtension->DeviceNumber)); + + } else { + + // + // This is an unlock command. + // + + if (!deviceExtension->LockCount || + (InterlockedDecrement(&deviceExtension->LockCount) != 0)) { + + DebugPrint((1, + "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n", + deviceExtension->LockCount, + deviceExtension->DeviceNumber)); + + // + // Don't unlock because someone still wants it locked. + // + + Irp->IoStatus.Status = STATUS_SUCCESS; + ExFreePool(srb); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_SUCCESS; + goto SetStatusAndReturn; + } + + DebugPrint((1, + "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n", + deviceExtension->LockCount, + deviceExtension->DeviceNumber)); + } + + srb->CdbLength = 6; + + cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; + + // + // TRUE - prevent media removal. + // FALSE - allow media removal. + // + + cdb->MEDIA_REMOVAL.Prevent = MediaRemoval->PreventMediaRemoval; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + + // + // Some devices will not support lock/unlock. + // Pretend that it worked. + // + + break; + } + + case IOCTL_DISK_RESERVE: { + + // + // Reserve logical unit. + // + + srb->CdbLength = 6; + + cdb->CDB6GENERIC.OperationCode = SCSIOP_RESERVE_UNIT; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + + break; + } + + case IOCTL_DISK_RELEASE: { + + // + // Release logical unit. + // + + srb->CdbLength = 6; + + cdb->CDB6GENERIC.OperationCode = SCSIOP_RELEASE_UNIT; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + + break; + } + + case IOCTL_DISK_EJECT_MEDIA: { + + // + // Eject media. + // + + srb->CdbLength = 6; + + cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; + cdb->START_STOP.LoadEject = 1; + cdb->START_STOP.Start = 0; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + break; + } + + case IOCTL_DISK_LOAD_MEDIA: { + + // + // Load media. + // + + DebugPrint((3,"CdRomDeviceControl: Load media\n")); + + srb->CdbLength = 6; + + cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; + cdb->START_STOP.LoadEject = 1; + cdb->START_STOP.Start = 1; + + // + // Set timeout value. + // + + srb->TimeOutValue = deviceExtension->TimeOutValue; + status = ScsiClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + + break; + } + + case IOCTL_DISK_FIND_NEW_DEVICES: { + + // + // Search for devices that have been powered on since the last + // device search or system initialization. + // + + DebugPrint((3,"CdRomDeviceControl: Find devices\n")); + status = DriverEntry(DeviceObject->DriverObject, + NULL); + + Irp->IoStatus.Status = status; + ExFreePool(srb); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + break; + } + + default: { + + DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n")); + + // + // Pass the device control to the next driver. + // + + ExFreePool(srb); + + // + // Copy the Irp stack parameters to the next stack location. + // + + nextStack = IoGetNextIrpStackLocation(Irp); + nextStack->Parameters = irpStack->Parameters; + nextStack->MajorFunction = irpStack->MajorFunction; + nextStack->MinorFunction = irpStack->MinorFunction; + + status = IoCallDriver(deviceExtension->PortDeviceObject, Irp); + break; + } + + } // end switch( ... + + SetStatusAndReturn: + + return status; + } + + + NTSTATUS + NTAPI + ScsiClassShutdownFlush( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + + /*++ + + Routine Description: + + This routine is called for a shutdown and flush IRPs. These are sent by the + system before it actually shuts down or when the file system does a flush. + If it exists, the device-specific driver's routine will be invoked. If there + wasn't one specified, the Irp will be completed with an Invalid device request. + + Arguments: + + DriverObject - Pointer to device object to being shutdown by system. + + Irp - IRP involved. + + Return Value: + + NT Status + + --*/ + + { + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + + if (deviceExtension->ClassShutdownFlush) { + + // + // Call the device-specific driver's routine. + // + + return deviceExtension->ClassShutdownFlush(DeviceObject, Irp); + } + + // + // Device-specific driver doesn't support this. + // + + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_INVALID_DEVICE_REQUEST; + } + + + ULONG + NTAPI + ScsiClassFindUnclaimedDevices( + IN PCLASS_INIT_DATA InitializationData, + IN PSCSI_ADAPTER_BUS_INFO AdapterInformation + ) + + { + ULONG scsiBus,deviceCount = 0; + PCHAR buffer = (PCHAR)AdapterInformation; + PSCSI_INQUIRY_DATA lunInfo; + PINQUIRYDATA inquiryData; + + for (scsiBus=0; scsiBus < (ULONG)AdapterInformation->NumberOfBuses; scsiBus++) { + + // + // Get the SCSI bus scan data for this bus. + // + + lunInfo = (PVOID) (buffer + AdapterInformation->BusData[scsiBus].InquiryDataOffset); + + // + // Search list for unclaimed disk devices. + // + + while (AdapterInformation->BusData[scsiBus].InquiryDataOffset) { + + inquiryData = (PVOID)lunInfo->InquiryData; + + ASSERT(InitializationData->ClassFindDeviceCallBack); + + if ((InitializationData->ClassFindDeviceCallBack(inquiryData)) && (!lunInfo->DeviceClaimed)) { + + deviceCount++; + } + + if (lunInfo->NextInquiryDataOffset == 0) { + break; + } + + lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); + } + } + return deviceCount; + } + + + + NTSTATUS + NTAPI + ScsiClassCreateDeviceObject( + IN PDRIVER_OBJECT DriverObject, + IN PCCHAR ObjectNameBuffer, + IN OPTIONAL PDEVICE_OBJECT PhysicalDeviceObject, + IN OUT PDEVICE_OBJECT *DeviceObject, + IN PCLASS_INIT_DATA InitializationData + ) + + /*++ + + Routine Description: + + This routine creates an object for the physical device specified and + sets up the deviceExtension's function pointers for each entry point + in the device-specific driver. + + Arguments: + + DriverObject - Pointer to driver object created by system. + + ObjectNameBuffer - Dir. name of the object to create. + + PhysicalDeviceObject - Pointer to the physical (class) device object for + this logical unit or NULL if this is it. + + DeviceObject - Pointer to the device object pointer we will return. + + InitializationData - Pointer to the init data created by the device-specific driver. + + Return Value: + + NTSTATUS + + --*/ + + { + STRING ntNameString; + UNICODE_STRING ntUnicodeString; + NTSTATUS status; + PDEVICE_OBJECT deviceObject = NULL; + + *DeviceObject = NULL; + + DebugPrint((2, + "ScsiClassCreateDeviceObject: Create device object %s\n", + ObjectNameBuffer)); + + RtlInitString(&ntNameString, + ObjectNameBuffer); + + status = RtlAnsiStringToUnicodeString(&ntUnicodeString, + &ntNameString, + TRUE); + + if (!NT_SUCCESS(status)) { + + DebugPrint((1, + "CreateDiskDeviceObjects: Cannot convert string %s\n", + ObjectNameBuffer)); + + ntUnicodeString.Buffer = NULL; + return status; + } + + status = IoCreateDevice(DriverObject, + InitializationData->DeviceExtensionSize, + &ntUnicodeString, + InitializationData->DeviceType, + InitializationData->DeviceCharacteristics, + FALSE, + &deviceObject); + + + if (!NT_SUCCESS(status)) { + + DebugPrint((1, + "CreateDiskDeviceObjects: Can not create device object %s\n", + ObjectNameBuffer)); + + } else { + + PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension; + + // + // Fill in entry points + // + + deviceExtension->ClassError = InitializationData->ClassError; + deviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification; + deviceExtension->ClassFindDevices = InitializationData->ClassFindDevices; + deviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl; + deviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush; + deviceExtension->ClassCreateClose = InitializationData->ClassCreateClose; + deviceExtension->ClassStartIo = InitializationData->ClassStartIo; + + deviceExtension->MediaChangeCount = 0; + + // + // If a pointer to the physical device object was passed in then use + // that. If the value was NULL, then this is the physical device so + // use the pointer to the device we just created. + // + + if(ARGUMENT_PRESENT(PhysicalDeviceObject)) { + deviceExtension->PhysicalDevice = PhysicalDeviceObject; + } else { + deviceExtension->PhysicalDevice = deviceObject; + } + } + + *DeviceObject = deviceObject; + + RtlFreeUnicodeString(&ntUnicodeString); + + // + // Indicate the ntUnicodeString is free. + // + + ntUnicodeString.Buffer = NULL; + + return status; + } + + + NTSTATUS + NTAPI + ScsiClassClaimDevice( + IN PDEVICE_OBJECT PortDeviceObject, + IN PSCSI_INQUIRY_DATA LunInfo, + IN BOOLEAN Release, + OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL + ) + /*++ + + Routine Description: + + This function claims a device in the port driver. The port driver object + is updated with the correct driver object if the device is successfully + claimed. + + Arguments: + + PortDeviceObject - Supplies the base port device object. + + LunInfo - Supplies the logical unit inforamtion of the device to be claimed. + + Release - Indicates the logical unit should be released rather than claimed. + + NewPortDeviceObject - Returns the updated port device object to be used + for all future accesses. + + Return Value: + + Returns a status indicating success or failure of the operation. + + --*/ + + { + IO_STATUS_BLOCK ioStatus; + PIRP irp; + PIO_STACK_LOCATION irpStack; + KEVENT event; + NTSTATUS status; + SCSI_REQUEST_BLOCK srb; + + PAGED_CODE(); + + if (NewPortDeviceObject != NULL) { + *NewPortDeviceObject = NULL; + } + + // + // Clear the SRB fields. + // + + RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); + + // + // Write length to SRB. + // + + srb.Length = SCSI_REQUEST_BLOCK_SIZE; + + // + // Set SCSI bus address. + // + + srb.PathId = LunInfo->PathId; + srb.TargetId = LunInfo->TargetId; + srb.Lun = LunInfo->Lun; + + srb.Function = Release ? SRB_FUNCTION_RELEASE_DEVICE : + SRB_FUNCTION_CLAIM_DEVICE; + + // + // Set the event object to the unsignaled state. + // It will be used to signal request completion. + // + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Build synchronous request with no transfer. + // + + irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE, + PortDeviceObject, + NULL, + 0, + NULL, + 0, + TRUE, + &event, + &ioStatus); + + if (irp == NULL) { + + DebugPrint((1, "ScsiClassClaimDevice: Can't allocate Irp\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + irpStack = IoGetNextIrpStackLocation(irp); + + // + // Save SRB address in next stack for port driver. + // + + irpStack->Parameters.Scsi.Srb = &srb; + + // + // Set up IRP Address. + // + + srb.OriginalRequest = irp; + + // + // Call the port driver with the request and wait for it to complete. + // + + status = IoCallDriver(PortDeviceObject, irp); + if (status == STATUS_PENDING) { + + KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); + status = ioStatus.Status; + } + + // + // If this is a release request, then just decrement the reference count + // and return. The status does not matter. + // + + if (Release) { + + ObDereferenceObject(PortDeviceObject); + return STATUS_SUCCESS; + } + + if (!NT_SUCCESS(status)) { + return status; + } + + ASSERT(srb.DataBuffer != NULL); + + // + // Reference the new port driver object so that it will not go away while + // it is being used. + // + + status = ObReferenceObjectByPointer(srb.DataBuffer, + 0, + NULL, + KernelMode ); + + if (!NT_SUCCESS(status)) { + + return status; + } + + // + // Return the new port device object pointer. + // + + if (NewPortDeviceObject != NULL) { + *NewPortDeviceObject = srb.DataBuffer; + } + + return status; + } + + + NTSTATUS + NTAPI + ScsiClassInternalIoControl ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + + /*++ + + Routine Description: + + This routine passes internal device controls to the port driver. + Internal device controls are used by higher level class drivers to + send scsi requests to a device that are not normally sent by a generic + class driver. + + The path ID, target ID and logical unit ID are set in the srb so the + higher level driver does not have to figure out what values are actually + used. + + Arguments: + + DeviceObject - Supplies a pointer to the device object for this request. + + Irp - Supplies the Irp making the request. + + Return Value: + + Returns back a STATUS_PENDING or a completion status. + + --*/ + { + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PSCSI_REQUEST_BLOCK srb; + + // + // Get a pointer to the SRB. + // + + srb = irpStack->Parameters.Scsi.Srb; + + // + // Set SCSI bus address. + // + + srb->PathId = deviceExtension->PathId; + srb->TargetId = deviceExtension->TargetId; + srb->Lun = deviceExtension->Lun; + + // + // NOTICE: The SCSI-II specificaiton indicates that this field should be + // zero; however, some target controllers ignore the logical unit number + // in the INDENTIFY message and only look at the logical unit number field + // in the CDB. + // + + srb->Cdb[1] |= deviceExtension->Lun << 5; + + // + // Set the parameters in the next stack location. + // + + irpStack = IoGetNextIrpStackLocation(Irp); + + irpStack->Parameters.Scsi.Srb = srb; + irpStack->MajorFunction = IRP_MJ_SCSI; + irpStack->MinorFunction = IRP_MN_SCSI_CLASS; + + IoSetCompletionRoutine(Irp, ClassIoCompletion, NULL, TRUE, TRUE, TRUE); + return IoCallDriver(deviceExtension->PortDeviceObject, Irp); + } + + NTSTATUS + NTAPI + ClassIoCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) + + /*++ + + Routine Description: + + This routine is called when an internal device control I/O request + has completed. It marks the IRP pending if necessary and returns the + status of the request. + + Arguments: + + DeviceObject - Target device object. + + Irp - Completed request. + + Context - not used. + + Return Value: + + Returns the status of the completed request. + + --*/ + + { + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(DeviceObject); + + // + // If pending is returned for this Irp then mark current stack + // as pending + // + + if (Irp->PendingReturned) { + + IoMarkIrpPending( Irp ); + } + + return Irp->IoStatus.Status; + } + + + VOID + NTAPI + ScsiClassInitializeSrbLookasideList( + IN PDEVICE_EXTENSION DeviceExtension, + IN ULONG NumberElements + ) + + /*++ + + Routine Description: + + This routine sets up a lookaside listhead for srbs. + + Arguments: + + DeviceExtension - Pointer to the deviceExtension containing the listhead. + + NumberElements - Supplies the maximum depth of the lookaside list. + + + Return Value: + + None + + --*/ + + { + ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead, + NULL, + NULL, + NonPagedPoolMustSucceed, + SCSI_REQUEST_BLOCK_SIZE, + 'ScsH', + (USHORT)NumberElements); + + } + + + ULONG + NTAPI + ScsiClassQueryTimeOutRegistryValue( + IN PUNICODE_STRING RegistryPath + ) + + /*++ + + Routine Description: + + This routine determines whether a reg key for a user-specified timeout value exists. + + Arguments: + + RegistryPath - Pointer to the hardware reg. entry describing the key. + + Return Value: + + New default timeout for a class of devices. + + --*/ + + { + // + // Find the appropriate reg. key + // + + PRTL_QUERY_REGISTRY_TABLE parameters = NULL; + PWSTR path; + NTSTATUS status; + LONG timeOut = 0; + ULONG zero = 0; + ULONG size; + + if (!RegistryPath) { + return 0; + } + + parameters = ExAllocatePool(NonPagedPool, + sizeof(RTL_QUERY_REGISTRY_TABLE)*2); + + if (!parameters) { + return 0; + } + + size = RegistryPath->MaximumLength + sizeof(WCHAR); + path = ExAllocatePool(NonPagedPool, size); + + if (!path) { + ExFreePool(parameters); + return 0; + } + + RtlZeroMemory(path,size); + RtlCopyMemory(path, RegistryPath->Buffer, size - sizeof(WCHAR)); + + + // + // Check for the Timeout value. + // + + RtlZeroMemory(parameters, + (sizeof(RTL_QUERY_REGISTRY_TABLE)*2)); + + parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + parameters[0].Name = L"TimeOutValue"; + parameters[0].EntryContext = &timeOut; + parameters[0].DefaultType = REG_DWORD; + parameters[0].DefaultData = &zero; + parameters[0].DefaultLength = sizeof(ULONG); + + status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + path, + parameters, + NULL, + NULL); + + if (!(NT_SUCCESS(status))) { + timeOut = 0; + } + + ExFreePool(parameters); + ExFreePool(path); + + DebugPrint((2, + "ScsiClassQueryTimeOutRegistryValue: Timeout value %d\n", + timeOut)); + + + return timeOut; + + } + + NTSTATUS + NTAPI + ScsiClassCheckVerifyComplete( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) + + /*++ + + Routine Description: + + This routine executes when the port driver has completed a check verify + ioctl. It will set the status of the master Irp, copy the media change + count and complete the request. + + Arguments: + + DeviceObject - Supplies the device object which represents the logical + unit. + + Irp - Supplies the Irp which has completed. + + Context - NULL + + Return Value: + + NT status + + --*/ + + { + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; + PDEVICE_EXTENSION physicalExtension = + deviceExtension->PhysicalDevice->DeviceExtension; + PIRP originalIrp; + + originalIrp = irpStack->Parameters.Others.Argument1; + + // + // Copy the media change count and status + // + + *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) = + physicalExtension->MediaChangeCount; + + DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change count for" + "device %d is %d\n", + physicalExtension->DeviceNumber, + physicalExtension->MediaChangeCount)); + + originalIrp->IoStatus.Status = Irp->IoStatus.Status; + originalIrp->IoStatus.Information = sizeof(ULONG); + + IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); + + IoFreeIrp(Irp); + + return STATUS_MORE_PROCESSING_REQUIRED; + } + + NTSTATUS + NTAPI + ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) + { + PIO_STATUS_BLOCK IoStatusBlock = Irp->UserIosb; + PKEVENT Event = Irp->UserEvent; + PMDL Mdl; + + *IoStatusBlock = Irp->IoStatus; + Irp->UserIosb = NULL; + Irp->UserEvent = NULL; + + if(Irp->MdlAddress) + { + Mdl = Irp->MdlAddress; + + // if necessary - unlock pages + if ((Mdl->MdlFlags & MDL_PAGES_LOCKED) && + !(Mdl->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED)) + { + MmUnlockPages(Mdl); + } + + // free this mdl + IoFreeMdl(Mdl); + } + + // free irp and set event to unsignaled state + IoFreeIrp(Irp); + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; + } diff --cc reactos/drivers/storage/class/disk_new/CMakeLists.txt index 00000000000,f97376b5545,f97376b5545..f97376b5545 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/CMakeLists.txt +++ b/reactos/drivers/storage/class/disk_new/CMakeLists.txt diff --cc reactos/drivers/storage/class/disk_new/data.c index 00000000000,c2fab4fea00,c2fab4fea00..c2fab4fea00 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/data.c +++ b/reactos/drivers/storage/class/disk_new/data.c diff --cc reactos/drivers/storage/class/disk_new/disk.c index 00000000000,7bd390d447f,7bd390d447f..7bd390d447f mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/disk.c +++ b/reactos/drivers/storage/class/disk_new/disk.c diff --cc reactos/drivers/storage/class/disk_new/disk.h index 00000000000,2f2c7eb81d4,2f2c7eb81d4..2f2c7eb81d4 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/disk.h +++ b/reactos/drivers/storage/class/disk_new/disk.h diff --cc reactos/drivers/storage/class/disk_new/disk.rc index 00000000000,14825451b14,14825451b14..14825451b14 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/disk.rc +++ b/reactos/drivers/storage/class/disk_new/disk.rc diff --cc reactos/drivers/storage/class/disk_new/diskdev.inf index 00000000000,d14de6688bf,d14de6688bf..d14de6688bf mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/diskdev.inf +++ b/reactos/drivers/storage/class/disk_new/diskdev.inf diff --cc reactos/drivers/storage/class/disk_new/diskwmi.c index 00000000000,1ce6dd5aa97,1ce6dd5aa97..1ce6dd5aa97 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/diskwmi.c +++ b/reactos/drivers/storage/class/disk_new/diskwmi.c diff --cc reactos/drivers/storage/class/disk_new/enum.c index 00000000000,56febd7853d,56febd7853d..56febd7853d mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/enum.c +++ b/reactos/drivers/storage/class/disk_new/enum.c diff --cc reactos/drivers/storage/class/disk_new/geometry.c index 00000000000,9495e36eedf,9495e36eedf..9495e36eedf mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/geometry.c +++ b/reactos/drivers/storage/class/disk_new/geometry.c diff --cc reactos/drivers/storage/class/disk_new/part.c index 00000000000,66e69435493,66e69435493..66e69435493 mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/part.c +++ b/reactos/drivers/storage/class/disk_new/part.c diff --cc reactos/drivers/storage/class/disk_new/pnp.c index 00000000000,fe1ef90a9cb,fe1ef90a9cb..fe1ef90a9cb mode 000000,100644,100644..100644 --- a/reactos/drivers/storage/class/disk_new/pnp.c +++ b/reactos/drivers/storage/class/disk_new/pnp.c diff --cc reactos/drivers/usb/directory.rbuild index e81eb8b291a,00000000000,8640fe372b0..8640fe372b0 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/directory.rbuild +++ b/reactos/drivers/usb/directory.rbuild @@@@ -1,16 -1,0 -1,22 +1,22 @@@@ + + + - - ++ ++ + + + + - ++ + diff --cc reactos/drivers/usb/usbccgp/CMakeLists.txt index 00000000000,f3da240ef0c,f3da240ef0c..f3da240ef0c mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbccgp/CMakeLists.txt +++ b/reactos/drivers/usb/usbccgp/CMakeLists.txt diff --cc reactos/drivers/usb/usbccgp/descriptor.c index 00000000000,e8e74f8ba5f,e8e74f8ba5f..e8e74f8ba5f mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbccgp/descriptor.c +++ b/reactos/drivers/usb/usbccgp/descriptor.c diff --cc reactos/drivers/usb/usbccgp/fdo.c index 00000000000,00000000000,74c89eb0845..74c89eb0845 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbccgp/fdo.c +++ b/reactos/drivers/usb/usbccgp/fdo.c diff --cc reactos/drivers/usb/usbccgp/function.c index 00000000000,00000000000,2840166b803..2840166b803 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbccgp/function.c +++ b/reactos/drivers/usb/usbccgp/function.c diff --cc reactos/drivers/usb/usbccgp/misc.c index 00000000000,1cb81f6f020,1cb81f6f020..1cb81f6f020 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbccgp/misc.c +++ b/reactos/drivers/usb/usbccgp/misc.c diff --cc reactos/drivers/usb/usbccgp/pdo.c index 00000000000,00000000000,e6c343b7f76..e6c343b7f76 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbccgp/pdo.c +++ b/reactos/drivers/usb/usbccgp/pdo.c diff --cc reactos/drivers/usb/usbccgp/usbccgp.c index 00000000000,00000000000,1757505b098..1757505b098 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbccgp/usbccgp.c +++ b/reactos/drivers/usb/usbccgp/usbccgp.c diff --cc reactos/drivers/usb/usbccgp/usbccgp.h index 00000000000,2208dfe8b49,2208dfe8b49..2208dfe8b49 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbccgp/usbccgp.h +++ b/reactos/drivers/usb/usbccgp/usbccgp.h diff --cc reactos/drivers/usb/usbccgp/usbccgp.rbuild index 00000000000,00000000000,4b26820fbed..4b26820fbed mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbccgp/usbccgp.rbuild +++ b/reactos/drivers/usb/usbccgp/usbccgp.rbuild diff --cc reactos/drivers/usb/usbccgp/usbccgp.rc index 00000000000,df848aa5e4d,df848aa5e4d..df848aa5e4d mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbccgp/usbccgp.rc +++ b/reactos/drivers/usb/usbccgp/usbccgp.rc diff --cc reactos/drivers/usb/usbd/usbd.c index 5732a343f0d,00000000000,fa3735acc16..fa3735acc16 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbd/usbd.c +++ b/reactos/drivers/usb/usbd/usbd.c @@@@ -1,541 -1,0 -1,665 +1,665 @@@@ + /* + * PROJECT: ReactOS Universal Serial Bus Driver/Helper Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbd/usbd.c + * PURPOSE: Helper Library for USB + * PROGRAMMERS: + * Filip Navara + * Michael Martin + * + */ + + /* + * Universal Serial Bus Driver/Helper Library + * + * Written by Filip Navara + * + * Notes: + * This driver was obsoleted in Windows XP and most functions + * became pure stubs. But some of them were retained for backward + * compatibilty with existing drivers. + * + * Preserved functions: + * + * USBD_Debug_GetHeap (implemented) + * USBD_Debug_RetHeap (implemented) + * USBD_CalculateUsbBandwidth (implemented, tested) + * USBD_CreateConfigurationRequestEx (implemented) + * USBD_CreateConfigurationRequest + * USBD_GetInterfaceLength (implemented) + * USBD_ParseConfigurationDescriptorEx (implemented) + * USBD_ParseDescriptors (implemented) + * USBD_GetPdoRegistryParameters (implemented) + */ + - #include ++ #include + #include - ++ #define NDEBUG ++ #include + #ifndef PLUGPLAY_REGKEY_DRIVER + #define PLUGPLAY_REGKEY_DRIVER 2 + #endif + typedef struct _USBD_INTERFACE_LIST_ENTRY { + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + PUSBD_INTERFACE_INFORMATION Interface; + } USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY; + + NTSTATUS NTAPI + DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) + { + return STATUS_SUCCESS; + } + + /* + * @implemented + */ + ULONG NTAPI + DllInitialize(ULONG Unknown) + { + return 0; + } + + /* + * @implemented + */ + ULONG NTAPI + DllUnload(VOID) + { + return 0; + } + + /* + * @implemented + */ + PVOID NTAPI + USBD_Debug_GetHeap(ULONG Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes, + ULONG Tag) + { + return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); + } + + /* + * @implemented + */ + VOID NTAPI + USBD_Debug_RetHeap(PVOID Heap, ULONG Unknown2, ULONG Unknown3) + { + ExFreePool(Heap); + } + + /* + * @implemented + */ + VOID NTAPI + USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2, + ULONG_PTR Info3) + { + } + + /* + * @implemented + */ + PVOID NTAPI + USBD_AllocateDeviceName(ULONG Unknown) + { ++ UNIMPLEMENTED + return NULL; + } + + /* + * @implemented + */ + ULONG NTAPI + USBD_CalculateUsbBandwidth( + ULONG MaxPacketSize, + UCHAR EndpointType, + BOOLEAN LowSpeed + ) + { + ULONG OverheadTable[] = { + 0x00, /* UsbdPipeTypeControl */ + 0x09, /* UsbdPipeTypeIsochronous */ + 0x00, /* UsbdPipeTypeBulk */ + 0x0d /* UsbdPipeTypeInterrupt */ + }; + ULONG Result; + + if (OverheadTable[EndpointType] != 0) + { + Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6; + if (LowSpeed) + return Result << 3; + return Result; + } + return 0; + } + + /* + * @implemented + */ + ULONG NTAPI + USBD_Dispatch(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4) + { ++ UNIMPLEMENTED + return 1; + } + + /* + * @implemented + */ + VOID NTAPI + USBD_FreeDeviceMutex(PVOID Unknown) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + VOID NTAPI + USBD_FreeDeviceName(PVOID Unknown) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + VOID NTAPI + USBD_WaitDeviceMutex(PVOID Unknown) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + ULONG NTAPI + USBD_GetSuspendPowerState(ULONG Unknown1) + { ++ UNIMPLEMENTED + return 0; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_InitializeDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, + ULONG Unknown4, ULONG Unknown5, ULONG Unknown6) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_RegisterHostController(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, + ULONG Unknown4, ULONG Unknown5, ULONG Unknown6, ULONG Unknown7, + ULONG Unknown8, ULONG Unknown9, ULONG Unknown10) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_GetDeviceInformation(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_CreateDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, + ULONG Unknown4, ULONG Unknown5) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_RemoveDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + VOID NTAPI + USBD_CompleteRequest(ULONG Unknown1, ULONG Unknown2) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + VOID NTAPI + USBD_RegisterHcFilter( + PDEVICE_OBJECT DeviceObject, + PDEVICE_OBJECT FilterDeviceObject + ) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + VOID NTAPI + USBD_SetSuspendPowerState(ULONG Unknown1, ULONG Unknown2) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_MakePdoName(ULONG Unknown1, ULONG Unknown2) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_QueryBusTime( + PDEVICE_OBJECT RootHubPdo, + PULONG CurrentFrame + ) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + VOID NTAPI + USBD_GetUSBDIVersion( + PUSBD_VERSION_INFORMATION Version + ) + { + if (Version != NULL) + { + Version->USBDI_Version = USBDI_VERSION; - Version->Supported_USB_Version = 0x100; ++ Version->Supported_USB_Version = 0x200; + } + } + + /* + * @implemented + */ + NTSTATUS NTAPI + USBD_RestoreDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) + { ++ UNIMPLEMENTED + return STATUS_NOT_SUPPORTED; + } + + /* + * @implemented + */ + VOID NTAPI + USBD_RegisterHcDeviceCapabilities(ULONG Unknown1, ULONG Unknown2, + ULONG Unknown3) + { ++ UNIMPLEMENTED + } + + /* + * @implemented + */ + PURB NTAPI + USBD_CreateConfigurationRequestEx( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PUSBD_INTERFACE_LIST_ENTRY InterfaceList + ) + { + PURB Urb; + ULONG UrbSize = 0; + ULONG InterfaceCount; + ULONG InterfaceNumber, EndPointNumber; + PUSBD_INTERFACE_INFORMATION InterfaceInfo; + + for (InterfaceCount = 0; + InterfaceList[InterfaceCount].InterfaceDescriptor != NULL; + InterfaceCount++) + { + UrbSize += sizeof(USBD_INTERFACE_INFORMATION); + UrbSize += (InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USBD_PIPE_INFORMATION); + } + + UrbSize += sizeof(URB) + sizeof(USBD_INTERFACE_INFORMATION); + + Urb = ExAllocatePool(NonPagedPool, UrbSize); + RtlZeroMemory(Urb, UrbSize); + Urb->UrbSelectConfiguration.Hdr.Function = URB_FUNCTION_SELECT_CONFIGURATION; + Urb->UrbSelectConfiguration.Hdr.Length = sizeof(Urb->UrbSelectConfiguration); + Urb->UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor; + + InterfaceInfo = &Urb->UrbSelectConfiguration.Interface; + for (InterfaceNumber = 0; InterfaceNumber < InterfaceCount; InterfaceNumber++) + { + InterfaceList[InterfaceNumber].Interface = InterfaceInfo; + InterfaceInfo->Length = sizeof(USBD_INTERFACE_INFORMATION) + + ((InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USBD_PIPE_INFORMATION)); + InterfaceInfo->InterfaceNumber = InterfaceList[InterfaceNumber].InterfaceDescriptor->bInterfaceNumber; + InterfaceInfo->AlternateSetting = InterfaceList[InterfaceNumber].InterfaceDescriptor->bAlternateSetting; + InterfaceInfo->NumberOfPipes = InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints; + for (EndPointNumber = 0; EndPointNumber < InterfaceInfo->NumberOfPipes; EndPointNumber++) + { + InterfaceInfo->Pipes[EndPointNumber].MaximumTransferSize = PAGE_SIZE; + } + InterfaceInfo = (PUSBD_INTERFACE_INFORMATION) ((ULONG_PTR)InterfaceInfo + InterfaceInfo->Length); + } + + return Urb; + } + + /* + * @implemented + */ + PURB NTAPI + USBD_CreateConfigurationRequest( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PUSHORT Size + ) + { + /* WindowsXP returns NULL */ + return NULL; + } + + /* + * @implemented + */ + ULONG NTAPI + USBD_GetInterfaceLength( + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, + PUCHAR BufferEnd + ) + { + ULONG_PTR Current; + PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor; + ULONG Length = 0; + BOOLEAN InterfaceFound = FALSE; + + for (Current = (ULONG_PTR)CurrentDescriptor; + Current < (ULONG_PTR)BufferEnd; + Current += CurrentDescriptor->bLength) + { + CurrentDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current; + + if ((CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) && (InterfaceFound)) + break; + else if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) + InterfaceFound = TRUE; + + Length += CurrentDescriptor->bLength; + } + + return Length; + } + + /* + * @implemented + */ + PUSB_COMMON_DESCRIPTOR NTAPI + USBD_ParseDescriptors( + PVOID DescriptorBuffer, + ULONG TotalLength, + PVOID StartPosition, + LONG DescriptorType + ) + { - PUSB_COMMON_DESCRIPTOR PComDes = StartPosition; ++ PUSB_COMMON_DESCRIPTOR CommonDescriptor; ++ ++ /* use start position */ ++ CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)StartPosition; ++ + - while(PComDes) ++ /* find next available descriptor */ ++ while(CommonDescriptor) + { - if (PComDes >= (PUSB_COMMON_DESCRIPTOR) - ((PLONG)DescriptorBuffer + TotalLength) ) break; - if (PComDes->bDescriptorType == DescriptorType) return PComDes; - if (PComDes->bLength == 0) break; - PComDes = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)PComDes + PComDes->bLength); ++ if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)DescriptorBuffer + TotalLength)) ++ { ++ /* end reached */ ++ DPRINT("End reached %p\n", CommonDescriptor); ++ return NULL; ++ } ++ ++ DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor->bDescriptorType, CommonDescriptor->bLength); ++ ++ /* is the requested one */ ++ if (CommonDescriptor->bDescriptorType == DescriptorType) ++ { ++ /* it is */ ++ return CommonDescriptor; ++ } ++ ++ /* sanity check */ ++ ASSERT(CommonDescriptor->bLength); ++ ++ /* move to next descriptor */ ++ CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength); + } ++ ++ /* no descriptor found */ + return NULL; + } + + + /* + * @implemented + */ + PUSB_INTERFACE_DESCRIPTOR NTAPI + USBD_ParseConfigurationDescriptorEx( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PVOID StartPosition, + LONG InterfaceNumber, + LONG AlternateSetting, + LONG InterfaceClass, + LONG InterfaceSubClass, + LONG InterfaceProtocol + ) + { - int x = 0; - PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDesc = StartPosition; ++ BOOLEAN Found; ++ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; ++ ++ /* set to start position */ ++ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)StartPosition; + - while(UsbInterfaceDesc) ++ DPRINT("USBD_ParseConfigurationDescriptorEx\n"); ++ DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength); ++ DPRINT("CurrentOffset %p Offset %lu\n", StartPosition, ((ULONG_PTR)StartPosition - (ULONG_PTR)ConfigurationDescriptor)); ++ ++ while(InterfaceDescriptor) + { - UsbInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) - USBD_ParseDescriptors(ConfigurationDescriptor, - ConfigurationDescriptor->wTotalLength, - UsbInterfaceDesc, - USB_INTERFACE_DESCRIPTOR_TYPE); ++ /* get interface descriptor */ ++ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE); ++ if (!InterfaceDescriptor) ++ { ++ /* no more descriptors available */ ++ break; ++ } ++ ++ DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bLength); + - if (!UsbInterfaceDesc) break; ++ /* set found */ ++ Found = TRUE; + ++ /* is there an interface number provided */ + if(InterfaceNumber != -1) + { - if(InterfaceNumber != UsbInterfaceDesc->bInterfaceNumber) x = 1; ++ if(InterfaceNumber != InterfaceDescriptor->bInterfaceNumber) ++ { ++ /* interface number does not match */ ++ Found = FALSE; ++ } + } ++ ++ /* is there an alternate setting provided */ + if(AlternateSetting != -1) + { - if(AlternateSetting != UsbInterfaceDesc->bAlternateSetting) x = 1; ++ if(AlternateSetting != InterfaceDescriptor->bAlternateSetting) ++ { ++ /* alternate setting does not match */ ++ Found = FALSE; ++ } + } ++ ++ /* match on interface class */ + if(InterfaceClass != -1) + { - if(InterfaceClass != UsbInterfaceDesc->bInterfaceClass) x = 1; ++ if(InterfaceClass != InterfaceDescriptor->bInterfaceClass) ++ { ++ /* no match with interface class criteria */ ++ Found = FALSE; ++ } + } ++ ++ /* match on interface sub class */ + if(InterfaceSubClass != -1) + { - if(InterfaceSubClass != UsbInterfaceDesc->bInterfaceSubClass) x = 1; ++ if(InterfaceSubClass != InterfaceDescriptor->bInterfaceSubClass) ++ { ++ /* no interface sub class match */ ++ Found = FALSE; ++ } + } ++ ++ /* interface protocol criteria */ + if(InterfaceProtocol != -1) + { - if(InterfaceProtocol != UsbInterfaceDesc->bInterfaceProtocol) x = 1; ++ if(InterfaceProtocol != InterfaceDescriptor->bInterfaceProtocol) ++ { ++ /* no interface protocol match */ ++ Found = FALSE; ++ } + } + - if (!x) return UsbInterfaceDesc; ++ if (Found) ++ { ++ /* the choosen one */ ++ return InterfaceDescriptor; ++ } ++ ++ /* sanity check */ ++ ASSERT(InterfaceDescriptor->bLength); + - if (UsbInterfaceDesc->bLength == 0) break; - UsbInterfaceDesc = UsbInterfaceDesc + UsbInterfaceDesc->bLength; ++ /* move to next descriptor */ ++ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); + } ++ ++ DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber, ++ AlternateSetting, InterfaceClass, InterfaceSubClass, InterfaceProtocol); ++ + return NULL; + } + + /* + * @implemented + */ + PUSB_INTERFACE_DESCRIPTOR NTAPI + USBD_ParseConfigurationDescriptor( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + UCHAR InterfaceNumber, + UCHAR AlternateSetting + ) + { + return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, + (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting, + -1, -1, -1); + } + + + /* + * @implemented + */ + ULONG NTAPI + USBD_GetPdoRegistryParameter( + PDEVICE_OBJECT PhysicalDeviceObject, + PVOID Parameter, + ULONG ParameterLength, + PWCHAR KeyName, + ULONG KeyNameLength + ) + { + NTSTATUS Status; + HANDLE DevInstRegKey; + ++ /* Open the device key */ + Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, - PLUGPLAY_REGKEY_DRIVER, STANDARD_RIGHTS_ALL, &DevInstRegKey); ++ PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &DevInstRegKey); + if (NT_SUCCESS(Status)) + { - PKEY_VALUE_FULL_INFORMATION FullInfo; ++ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo; + UNICODE_STRING ValueName; + ULONG Length; + - RtlInitUnicodeString(&ValueName, KeyName); - Length = ParameterLength + KeyNameLength + sizeof(KEY_VALUE_FULL_INFORMATION); - FullInfo = ExAllocatePool(PagedPool, Length); - if (FullInfo) ++ /* Initialize the unicode string based on caller data */ ++ ValueName.Buffer = KeyName; ++ ValueName.Length = ValueName.MaximumLength = KeyNameLength; ++ ++ Length = ParameterLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION); ++ PartialInfo = ExAllocatePool(PagedPool, Length); ++ if (PartialInfo) + { + Status = ZwQueryValueKey(DevInstRegKey, &ValueName, - KeyValueFullInformation, FullInfo, Length, &Length); ++ KeyValuePartialInformation, PartialInfo, Length, &Length); ++ if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) ++ { ++ /* The caller doesn't want all the data */ ++ ExFreePool(PartialInfo); ++ PartialInfo = ExAllocatePool(PagedPool, Length); ++ if (PartialInfo) ++ { ++ Status = ZwQueryValueKey(DevInstRegKey, &ValueName, ++ KeyValuePartialInformation, PartialInfo, Length, &Length); ++ } ++ else ++ { ++ Status = STATUS_NO_MEMORY; ++ } ++ } ++ + if (NT_SUCCESS(Status)) + { ++ /* Compute the length to copy back */ ++ if (ParameterLength < PartialInfo->DataLength) ++ Length = ParameterLength; ++ else ++ Length = PartialInfo->DataLength; ++ + RtlCopyMemory(Parameter, - ((PUCHAR)FullInfo) + FullInfo->DataOffset, - ParameterLength /*FullInfo->DataLength*/); ++ PartialInfo->Data, ++ Length); ++ } ++ ++ if (PartialInfo) ++ { ++ ExFreePool(PartialInfo); + } - ExFreePool(FullInfo); + } else + Status = STATUS_NO_MEMORY; + ZwClose(DevInstRegKey); + } + return Status; + } diff --cc reactos/drivers/usb/usbd/usbd.rbuild index c5900b5ff35,00000000000,18ef89793e4..18ef89793e4 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbd/usbd.rbuild +++ b/reactos/drivers/usb/usbd/usbd.rbuild @@@@ -1,9 -1,0 -1,10 +1,10 @@@@ + + + ++ + + ntoskrnl + hal + usbd.c + usbd.rc + diff --cc reactos/drivers/usb/usbehci/CMakeLists.txt index 0d8a7ba0cf5,00000000000,8bad4b1d840..8bad4b1d840 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/CMakeLists.txt +++ b/reactos/drivers/usb/usbehci/CMakeLists.txt @@@@ -1,21 -1,0 -1,34 +1,34 @@@@ + - list(APPEND SOURCE - usbehci.c - hardware.c - physmem.c - hwiface.c - transfer.c - fdo.c - pdo.c - common.c - misc.c - irp.c - usbiffn.c ++ set_cpp() ++ ++ remove_definitions(-D_WIN32_WINNT=0x502) ++ add_definitions(-D_WIN32_WINNT=0x600) ++ ++ add_library(usbehci SHARED ++ usbehci.cpp ++ usb_device.cpp ++ usb_request.cpp ++ usb_queue.cpp ++ hcd_controller.cpp ++ hardware.cpp ++ misc.cpp ++ purecall.cpp ++ hub_controller.cpp ++ memory_manager.cpp + usbehci.rc) + - add_library(usbehci SHARED ${SOURCE}) ++ target_link_libraries(usbehci ++ libcntpr ++ ${PSEH_LIB}) ++ ++ if(MSVC) ++ set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "/GR-") ++ else() ++ target_link_libraries(usbehci -lgcc) ++ set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti") ++ endif(MSVC) + + set_module_type(usbehci kernelmodedriver) + add_importlibs(usbehci ntoskrnl hal) + - add_cab_target(usbehci 2) ++ add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --cc reactos/drivers/usb/usbehci/hardware.cpp index 00000000000,00000000000,8cec292b180..8cec292b180 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/hardware.cpp +++ b/reactos/drivers/usb/usbehci/hardware.cpp diff --cc reactos/drivers/usb/usbehci/hcd_controller.cpp index 00000000000,00000000000,bbbf04ccd1a..bbbf04ccd1a mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/hcd_controller.cpp +++ b/reactos/drivers/usb/usbehci/hcd_controller.cpp diff --cc reactos/drivers/usb/usbehci/hub_controller.cpp index 00000000000,00000000000,9b97655df11..9b97655df11 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/hub_controller.cpp +++ b/reactos/drivers/usb/usbehci/hub_controller.cpp diff --cc reactos/drivers/usb/usbehci/interfaces.h index 00000000000,8527948903d,8527948903d..8527948903d mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbehci/interfaces.h +++ b/reactos/drivers/usb/usbehci/interfaces.h diff --cc reactos/drivers/usb/usbehci/memory_manager.cpp index 00000000000,4b60d968b4c,4b60d968b4c..4b60d968b4c mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbehci/memory_manager.cpp +++ b/reactos/drivers/usb/usbehci/memory_manager.cpp diff --cc reactos/drivers/usb/usbehci/misc.cpp index 00000000000,56c35cc806b,56c35cc806b..56c35cc806b mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbehci/misc.cpp +++ b/reactos/drivers/usb/usbehci/misc.cpp diff --cc reactos/drivers/usb/usbehci/purecall.cpp index 00000000000,c168b79e10e,c168b79e10e..c168b79e10e mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbehci/purecall.cpp +++ b/reactos/drivers/usb/usbehci/purecall.cpp diff --cc reactos/drivers/usb/usbehci/usb_device.cpp index 00000000000,00000000000,b2db3cf5c58..b2db3cf5c58 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/usb_device.cpp +++ b/reactos/drivers/usb/usbehci/usb_device.cpp diff --cc reactos/drivers/usb/usbehci/usb_queue.cpp index 00000000000,00000000000,3c7d4db58fe..3c7d4db58fe mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/usb_queue.cpp +++ b/reactos/drivers/usb/usbehci/usb_queue.cpp diff --cc reactos/drivers/usb/usbehci/usb_request.cpp index 00000000000,00000000000,46ed3a4c4dd..46ed3a4c4dd mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/usb_request.cpp +++ b/reactos/drivers/usb/usbehci/usb_request.cpp diff --cc reactos/drivers/usb/usbehci/usbehci.cpp index 00000000000,2793eee8927,2793eee8927..2793eee8927 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbehci/usbehci.cpp +++ b/reactos/drivers/usb/usbehci/usbehci.cpp diff --cc reactos/drivers/usb/usbehci/usbehci.rbuild index f30b683d498,00000000000,63d39433c95..63d39433c95 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbehci/usbehci.rbuild +++ b/reactos/drivers/usb/usbehci/usbehci.rbuild @@@@ -1,18 -1,0 -1,22 +1,22 @@@@ + + + ++ ++ 0x600 + ntoskrnl + hal - usbehci.c - hardware.c - physmem.c - hwiface.c - transfer.c - fdo.c - pdo.c - common.c - misc.c - irp.c - usbiffn.c ++ pseh ++ usbehci.cpp ++ usb_device.cpp ++ usb_request.cpp ++ usb_queue.cpp ++ hcd_controller.cpp ++ hardware.cpp ++ misc.cpp ++ purecall.cpp ++ hub_controller.cpp ++ memory_manager.cpp + usbehci.rc ++ -fno-rtti ++ -fno-exceptions + diff --cc reactos/drivers/usb/usbhub/fdo.c index bea0e09e65f,00000000000,6333d1e19c4..6333d1e19c4 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbhub/fdo.c +++ b/reactos/drivers/usb/usbhub/fdo.c @@@@ -1,1190 -1,0 -1,1975 +1,1975 @@@@ - /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: USB hub driver - * FILE: drivers/usb/cromwell/hub/fdo.c - * PURPOSE: IRP_MJ_PNP operations for FDOs - * - * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.com) ++ /* ++ * PROJECT: ReactOS Universal Serial Bus Hub Driver ++ * LICENSE: GPL - See COPYING in the top level directory ++ * FILE: drivers/usb/usbhub/fdo.c ++ * PURPOSE: Handle FDO ++ * PROGRAMMERS: + * Michael Martin (michael.martin@reactos.org) ++ * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + + #define INITGUID - #include - #define NDEBUG + #include "usbhub.h" - #include "usbdlib.h" - - #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) - - typedef struct _PORTSTATUSANDCHANGE - { - USHORT Status; - USHORT Change; - } PORTSTATUSANDCHANGE, *PPORTSTATUSANDCHANGE; + + NTSTATUS - QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2); ++ QueryStatusChangeEndpoint( ++ IN PDEVICE_OBJECT DeviceObject); ++ + NTSTATUS - WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject); ++ CreateUsbChildDeviceObject( ++ IN PDEVICE_OBJECT UsbHubDeviceObject, ++ IN LONG PortId, ++ OUT PDEVICE_OBJECT *UsbChildDeviceObject, ++ IN ULONG PortStatus); ++ + NTSTATUS - SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb); ++ DestroyUsbChildDeviceObject( ++ IN PDEVICE_OBJECT UsbHubDeviceObject, ++ IN LONG PortId); + - VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) ++ NTSTATUS ++ SubmitRequestToRootHub( ++ IN PDEVICE_OBJECT RootHubDeviceObject, ++ IN ULONG IoControlCode, ++ OUT PVOID OutParameter1, ++ OUT PVOID OutParameter2) + { - DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor); - DPRINT1("bLength %x\n", DeviceDescriptor->bLength); - DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType); - DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB); - DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass); - DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass); - DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol); - DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0); - DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor); - DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct); - DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice); - DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer); - DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct); - DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber); - DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); - } ++ KEVENT Event; ++ PIRP Irp; ++ IO_STATUS_BLOCK IoStatus; ++ NTSTATUS Status; ++ PIO_STACK_LOCATION Stack = NULL; + - VOID DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) - { - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - LONG i, j; - - DPRINT1("Duming ConfigurationDescriptor %x\n", ConfigurationDescriptor); - DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength); - DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType); - DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength); - DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); - DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue); - DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration); - DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes); - DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower); - - InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR)); - - for (i=0; i < ConfigurationDescriptor->bNumInterfaces; i++) ++ KeInitializeEvent(&Event, NotificationEvent, FALSE); ++ ++ // ++ // Build Control Request ++ // ++ Irp = IoBuildDeviceIoControlRequest(IoControlCode, ++ RootHubDeviceObject, ++ NULL, 0, ++ NULL, 0, ++ TRUE, ++ &Event, ++ &IoStatus); ++ ++ if (Irp == NULL) + { - DPRINT1("- Dumping InterfaceDescriptor %x\n", InterfaceDescriptor); - DPRINT1(" bLength %x\n", InterfaceDescriptor->bLength); - DPRINT1(" bDescriptorType %x\n", InterfaceDescriptor->bDescriptorType); - DPRINT1(" bInterfaceNumber %x\n", InterfaceDescriptor->bInterfaceNumber); - DPRINT1(" bAlternateSetting %x\n", InterfaceDescriptor->bAlternateSetting); - DPRINT1(" bNumEndpoints %x\n", InterfaceDescriptor->bNumEndpoints); - DPRINT1(" bInterfaceClass %x\n", InterfaceDescriptor->bInterfaceClass); - DPRINT1(" bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceSubClass); - DPRINT1(" bInterfaceProtocol %x\n", InterfaceDescriptor->bInterfaceProtocol); - DPRINT1(" iInterface %x\n", InterfaceDescriptor->iInterface); - - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR)); - - for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++) - { - DPRINT1(" bLength %x\n", EndpointDescriptor->bLength); - DPRINT1(" bDescriptorType %x\n", EndpointDescriptor->bDescriptorType); - DPRINT1(" bEndpointAddress %x\n", EndpointDescriptor->bEndpointAddress); - DPRINT1(" bmAttributes %x\n", EndpointDescriptor->bmAttributes); - DPRINT1(" wMaxPacketSize %x\n", EndpointDescriptor->wMaxPacketSize); - DPRINT1(" bInterval %x\n", EndpointDescriptor->bInterval); - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDescriptor + sizeof(USB_ENDPOINT_DESCRIPTOR)); - } - InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor; ++ DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; + } + - } - - VOID DumpInterfaceInfo(PUSBD_INTERFACE_INFORMATION InterfaceInformation) - { - PUSBD_PIPE_INFORMATION PipeInformation; - ULONG i; ++ // ++ // Initialize the status block before sending the IRP ++ // ++ IoStatus.Status = STATUS_NOT_SUPPORTED; ++ IoStatus.Information = 0; + - DPRINT1("IntefaceLenth %x\n",InterfaceInformation->Length); - DPRINT1("InterfaceNumber %x\n",InterfaceInformation->InterfaceNumber); - DPRINT1("AlternateSetting %x\n",InterfaceInformation->AlternateSetting); - DPRINT1("Class %x\n",InterfaceInformation->Class); - DPRINT1("SubClass %x\n",InterfaceInformation->SubClass); - DPRINT1("Protocol %x\n",InterfaceInformation->Protocol); - DPRINT1("Reserved %x\n",InterfaceInformation->Reserved); - DPRINT1("InterfaceHandle %x\n",InterfaceInformation->InterfaceHandle); - DPRINT1("NumberOfPipes %x\n", InterfaceInformation->NumberOfPipes); ++ // ++ // Get Next Stack Location and Initialize it ++ // ++ Stack = IoGetNextIrpStackLocation(Irp); ++ Stack->Parameters.Others.Argument1 = OutParameter1; ++ Stack->Parameters.Others.Argument2 = OutParameter2; + - PipeInformation = &InterfaceInformation->Pipes[0]; ++ // ++ // Call RootHub ++ // ++ Status = IoCallDriver(RootHubDeviceObject, Irp); + - for (i = 0; i < InterfaceInformation->NumberOfPipes; i++) ++ // ++ // Its ok to block here as this function is called in an nonarbitrary thread ++ // ++ if (Status == STATUS_PENDING) + { - - DPRINT1("MaximumPacketSize %x\n", PipeInformation->MaximumPacketSize); - DPRINT1("EndpointAddress %x\n", PipeInformation->EndpointAddress); - DPRINT1("Interval %x\n", PipeInformation->Interval); - DPRINT1("PipeType %x\n", PipeInformation->PipeType); - DPRINT1("PipeHandle %x\n", PipeInformation->PipeHandle); - DPRINT1("PipeFlags %x\n", PipeInformation->PipeFlags); - DPRINT1("MaximumTransferSize %x\n", PipeInformation->MaximumTransferSize); - PipeInformation = (PUSBD_PIPE_INFORMATION)((ULONG_PTR)PipeInformation + sizeof(USBD_PIPE_INFORMATION)); ++ KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); ++ Status = IoStatus.Status; + } - } + ++ // ++ // The IO Manager will free the IRP ++ // + - VOID NTAPI - WorkerThread(IN PVOID Context) ++ return Status; ++ } ++ ++ NTSTATUS ++ GetPortStatusAndChange( ++ IN PDEVICE_OBJECT RootHubDeviceObject, ++ IN ULONG PortId, ++ OUT PPORT_STATUS_CHANGE StatusChange) + { - PHUB_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT DeviceObject, Pdo; - PHUB_CHILDDEVICE_EXTENSION PdoExtension; - PURB Urb = NULL; - PORTSTATUSANDCHANGE PortStatusAndChange; - int PortLoop, DeviceCount; + NTSTATUS Status; - USB_DEVICE_DESCRIPTOR DevDesc; - USB_CONFIGURATION_DESCRIPTOR ConfigDesc; - ULONG DevDescSize, ConfigDescSize; - PUSB_STRING_DESCRIPTOR StringDesc; - USB_STRING_DESCRIPTOR LanguageIdDescriptor; - PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context; ++ PURB Urb; + - DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; ++ // ++ // Allocate URB ++ // ++ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); ++ if (!Urb) ++ { ++ DPRINT1("Failed to allocate memory for URB!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ // ++ // Zero it ++ // ++ RtlZeroMemory(Urb, sizeof(URB)); ++ ++ // ++ // Initialize URB for getting Port Status ++ // ++ UsbBuildVendorRequest(Urb, ++ URB_FUNCTION_CLASS_OTHER, ++ sizeof(Urb->UrbControlVendorClassRequest), ++ USBD_TRANSFER_DIRECTION_OUT, ++ 0, ++ USB_REQUEST_GET_STATUS, ++ 0, ++ PortId, ++ StatusChange, ++ 0, ++ sizeof(PORT_STATUS_CHANGE), ++ 0); ++ ++ // ++ // Query the Root Hub ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ ++ // ++ // Free URB ++ // ++ ExFreePool(Urb); + - /* Determine where in the children array to store this device info */ - for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++) ++ return Status; ++ } ++ ++ NTSTATUS ++ SetPortFeature( ++ IN PDEVICE_OBJECT RootHubDeviceObject, ++ IN ULONG PortId, ++ IN ULONG Feature) ++ { ++ NTSTATUS Status; ++ PURB Urb; ++ ++ // ++ // Allocate URB ++ // ++ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); ++ if (!Urb) + { - if (DeviceExtension->UsbChildren[DeviceCount] == NULL) - { - break; - } ++ DPRINT1("Failed to allocate memory for URB!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; + } + ++ // ++ // Zero it ++ // ++ RtlZeroMemory(Urb, sizeof(URB)); ++ ++ // ++ // Initialize URB for Clearing Port Reset ++ // ++ UsbBuildVendorRequest(Urb, ++ URB_FUNCTION_CLASS_OTHER, ++ sizeof(Urb->UrbControlVendorClassRequest), ++ USBD_TRANSFER_DIRECTION_IN, ++ 0, ++ USB_REQUEST_SET_FEATURE, ++ Feature, ++ PortId, ++ NULL, ++ 0, ++ 0, ++ 0); ++ // ++ // Query the Root Hub ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ ++ // ++ // Free URB ++ // ++ ExFreePool(Urb); ++ ++ return Status; ++ } ++ ++ NTSTATUS ++ ClearPortFeature( ++ IN PDEVICE_OBJECT RootHubDeviceObject, ++ IN ULONG PortId, ++ IN ULONG Feature) ++ { ++ NTSTATUS Status; ++ PURB Urb; ++ ++ // ++ // Allocate a URB ++ // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + if (!Urb) + { + DPRINT1("Failed to allocate memory for URB!\n"); - ASSERT(FALSE); ++ return STATUS_INSUFFICIENT_RESOURCES; + } + ++ // ++ // Zero it ++ // + RtlZeroMemory(Urb, sizeof(URB)); + - for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) ++ // ++ // Initialize URB for Clearing Port Reset ++ // ++ UsbBuildVendorRequest(Urb, ++ URB_FUNCTION_CLASS_OTHER, ++ sizeof(Urb->UrbControlVendorClassRequest), ++ USBD_TRANSFER_DIRECTION_IN, ++ 0, ++ USB_REQUEST_CLEAR_FEATURE, ++ Feature, ++ PortId, ++ NULL, ++ 0, ++ 0, ++ 0); ++ // ++ // Query the Root Hub ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ ++ // ++ // Free URB ++ // ++ ExFreePool(Urb); ++ ++ return Status; ++ } ++ ++ VOID NTAPI ++ DeviceStatusChangeThread( ++ IN PVOID Context) ++ { ++ NTSTATUS Status; ++ PDEVICE_OBJECT DeviceObject, RootHubDeviceObject; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PWORK_ITEM_DATA WorkItemData; ++ PORT_STATUS_CHANGE PortStatus; ++ LONG PortId; ++ BOOLEAN SignalResetComplete = FALSE; ++ ++ DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context); ++ ++ WorkItemData = (PWORK_ITEM_DATA)Context; ++ DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; ++ // ++ // Loop all ports ++ // ++ for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++) + { - /* Get the port status */ - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_OUT, - 0, - USB_REQUEST_GET_STATUS, - 0, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PORTSTATUSANDCHANGE), - 0); - - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ // ++ // Get Port Status ++ // ++ Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Failed to get PortStatus!\n"); - goto CleanUp; ++ DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status); ++ // FIXME: Do we really want to halt further SCE requests? ++ return; + } + - DPRINT("Notification Port %x:\n", PortLoop + 1); - DPRINT("Status %x\n", PortStatusAndChange.Status); - DPRINT("Change %x\n", PortStatusAndChange.Change); ++ DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status); ++ DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change); ++ + - if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET) ++ // ++ // Check for new device connection ++ // ++ if (PortStatus.Change & USB_PORT_STATUS_CONNECT) + { - /* Clear the Reset */ - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN, - 0, - USB_REQUEST_CLEAR_FEATURE, - C_PORT_RESET, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PORTSTATUSANDCHANGE), - 0); ++ // ++ // Clear Port Connect ++ // ++ Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to clear connection change for port %d\n", PortId); ++ } + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ // ++ // Is this a connect or disconnect? ++ // ++ if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT)) ++ { ++ DPRINT1("Device disconnected from port %d\n", PortId); ++ ++ Status = DestroyUsbChildDeviceObject(DeviceObject, PortId); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to delete child device object after disconnect\n"); ++ } ++ } ++ else ++ { ++ DPRINT1("Device connected from port %d\n", PortId); ++ ++ // No SCE completion done for clearing C_PORT_CONNECT ++ ++ // ++ // Reset Port ++ // ++ Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to reset port %d\n", PortId); ++ } ++ } ++ } ++ else if (PortStatus.Change & USB_PORT_STATUS_ENABLE) ++ { ++ // ++ // Clear Enable ++ // ++ Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_ENABLE); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to clear enable change on port %d\n", PortId); ++ } ++ } ++ else if (PortStatus.Change & USB_PORT_STATUS_RESET) ++ { ++ // ++ // Clear Reset ++ // ++ Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_RESET); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status); - goto CleanUp; ++ DPRINT1("Failed to clear reset change on port %d\n", PortId); + } + - UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_OUT, - 0, - USB_REQUEST_GET_STATUS, - 0, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PORTSTATUSANDCHANGE), - 0); - - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - DPRINT("Status %x\n", PortStatusAndChange.Status); - DPRINT("Change %x\n", PortStatusAndChange.Change); - - /* Create the UsbDevice */ - Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo, - (PVOID)&DeviceExtension->UsbChildren[DeviceCount], - DeviceExtension->RootHubUsbDevice, - PortStatusAndChange.Status, - PortLoop + 1); - DPRINT1("CreateUsbDevice Status %x\n", Status); - - Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]); - DPRINT1("InitializeUsbDevice Status %x\n", Status); - - DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR); - ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); - Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo, - DeviceExtension->UsbChildren[DeviceCount], - (PUCHAR)&DevDesc, - &DevDescSize, - (PUCHAR)&ConfigDesc, - &ConfigDescSize); ++ // ++ // Get Port Status ++ // ++ Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status); ++ DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status); ++ // FIXME: Do we really want to halt further SCE requests? ++ return; + } + - DumpDeviceDescriptor(&DevDesc); ++ DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status); ++ DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change); + - Status = IoCreateDevice(DeviceObject->DriverObject, - sizeof(HUB_CHILDDEVICE_EXTENSION), - NULL, - FILE_DEVICE_CONTROLLER, - FILE_AUTOGENERATED_DEVICE_NAME, - FALSE, - &DeviceExtension->Children[DeviceCount]); ++ // ++ // Check that reset was cleared ++ // ++ if(PortStatus.Change & USB_PORT_STATUS_RESET) ++ { ++ DPRINT1("Port did not clear reset! Possible Hardware problem!\n"); ++ } + - if (!NT_SUCCESS(Status)) ++ // ++ // Check if the device is still connected ++ // ++ if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT)) + { - DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status); - goto CleanUp; ++ DPRINT1("Device has been disconnected\n"); ++ continue; + } + - Pdo = DeviceExtension->Children[DeviceCount]; - DPRINT1("Created New Device with %x\n", Pdo); - Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; ++ // ++ // Make sure its Connected and Enabled ++ // ++ if (!(PortStatus.Status & (USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE))) ++ { ++ DPRINT1("Usb Device is not connected and enabled!\n"); ++ // ++ // Attempt another reset ++ // ++ Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to reset port %d\n", PortId); ++ } ++ continue; ++ } + - PdoExtension = Pdo->DeviceExtension; ++ // ++ // This is a new device ++ // ++ Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status); + - RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); ++ // ++ // Request event signalling later ++ // ++ SignalResetComplete = TRUE; ++ } ++ } + - PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG); - RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR)); - swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct); ++ ExFreePool(WorkItemData); + ++ // ++ // Send another SCE Request ++ // ++ DPRINT("Sending another SCE!\n"); ++ QueryStatusChangeEndpoint(DeviceObject); + - /* Get the LANGids */ - RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR)); - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - USB_STRING_DESCRIPTOR_TYPE, - 0, - 0, - &LanguageIdDescriptor, - NULL, - sizeof(USB_STRING_DESCRIPTOR), - NULL); ++ // ++ // Check if a reset event was satisfied ++ // ++ if (SignalResetComplete) ++ { ++ // ++ // Signal anyone waiting on it ++ // ++ KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE); ++ } ++ } + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ NTSTATUS ++ NTAPI ++ StatusChangeEndpointCompletion( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp, ++ IN PVOID Context) ++ { ++ PDEVICE_OBJECT RealDeviceObject; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PWORK_ITEM_DATA WorkItemData; ++ ++ RealDeviceObject = (PDEVICE_OBJECT)Context; ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension; ++ ++ // ++ // NOTE: USBPORT frees this IRP ++ // ++ DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp, HubDeviceExtension->PendingSCEIrp); ++ //IoFreeIrp(Irp); ++ ++ // ++ // Create and initialize work item data ++ // ++ WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG); ++ if (!WorkItemData) ++ { ++ DPRINT1("Failed to allocate memory!n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } ++ WorkItemData->Context = RealDeviceObject; + - /* Get the length of the SerialNumber */ - StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG); - RtlZeroMemory(StringDesc, 64); - StringDesc->bLength = 0; - StringDesc->bDescriptorType = 0; ++ DPRINT("Queuing work item\n"); + - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - USB_STRING_DESCRIPTOR_TYPE, - DevDesc.iSerialNumber, - LanguageIdDescriptor.bString[0], - StringDesc, - NULL, - 64, - NULL); ++ // ++ // Queue the work item to handle initializing the device ++ // ++ ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData); ++ ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue); + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; ++ // ++ // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed ++ // ++ return STATUS_MORE_PROCESSING_REQUIRED; ++ } + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ NTSTATUS ++ QueryStatusChangeEndpoint( ++ IN PDEVICE_OBJECT DeviceObject) ++ { ++ NTSTATUS Status; ++ PDEVICE_OBJECT RootHubDeviceObject; ++ PIO_STACK_LOCATION Stack; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PURB PendingSCEUrb; + - PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); - DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId); ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; + - RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR)); - RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength); - DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId); ++ // ++ // Allocate a URB ++ // ++ PendingSCEUrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + ++ // ++ // Initialize URB for Status Change Endpoint request ++ // ++ UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb, ++ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), ++ HubDeviceExtension->PipeHandle, ++ HubDeviceExtension->PortStatusChange, ++ NULL, ++ sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts, ++ USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, ++ NULL); + ++ // ++ // Set the device handle to null for roothub ++ // ++ PendingSCEUrb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle; + - RtlZeroMemory(StringDesc, 64); - StringDesc->bLength = 0; - StringDesc->bDescriptorType = 0; ++ // ++ // Allocate an Irp ++ // + - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - USB_STRING_DESCRIPTOR_TYPE, - DevDesc.iProduct, - LanguageIdDescriptor.bString[0], - StringDesc, - NULL, - 64, - NULL); ++ HubDeviceExtension->PendingSCEIrp = ExAllocatePoolWithTag(NonPagedPool, ++ IoSizeOfIrp(RootHubDeviceObject->StackSize), ++ USB_HUB_TAG); ++ /* ++ HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize, ++ FALSE); ++ */ ++ DPRINT("Allocated IRP %x\n", HubDeviceExtension->PendingSCEIrp); + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; ++ if (!HubDeviceExtension->PendingSCEIrp) ++ { ++ DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ // ++ // Initialize the IRP ++ // ++ IoInitializeIrp(HubDeviceExtension->PendingSCEIrp, ++ IoSizeOfIrp(RootHubDeviceObject->StackSize), ++ RootHubDeviceObject->StackSize); ++ ++ HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; ++ HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0; ++ HubDeviceExtension->PendingSCEIrp->Flags = 0; ++ HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL; ++ ++ // ++ // Get the Next Stack Location and Initialize it ++ // ++ Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp); ++ Stack->DeviceObject = DeviceObject; ++ Stack->Parameters.Others.Argument1 = PendingSCEUrb; ++ Stack->Parameters.Others.Argument2 = NULL; ++ Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; ++ Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; + - PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); ++ // ++ // Set the completion routine for when device is connected to root hub ++ // ++ IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp, ++ StatusChangeEndpointCompletion, ++ DeviceObject, ++ TRUE, ++ TRUE, ++ TRUE); ++ ++ // ++ // Send to RootHub ++ // ++ DPRINT("DeviceObject is %x\n", DeviceObject); ++ DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp); ++ Status = IoCallDriver(RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp); + - RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR)); - RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength); - ExFreePool(StringDesc); - DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription); ++ return STATUS_PENDING; ++ } + - PdoExtension->IsFDO = FALSE; - PdoExtension->Parent = DeviceObject; - Pdo->Flags &= ~DO_DEVICE_INITIALIZING; ++ NTSTATUS ++ QueryInterface( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN CONST GUID InterfaceType, ++ IN LONG Size, ++ IN LONG Version, ++ OUT PVOID Interface) ++ { ++ KEVENT Event; ++ PIRP Irp; ++ IO_STATUS_BLOCK IoStatus; ++ NTSTATUS Status; ++ PIO_STACK_LOCATION Stack = NULL; + - ExFreePool(WorkItemData); - ExFreePool(Urb); ++ // ++ // Initialize the Event used to wait for Irp completion ++ // ++ KeInitializeEvent(&Event, NotificationEvent, FALSE); + - IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations); - return; - } ++ // ++ // Build Control Request ++ // ++ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, ++ DeviceObject, ++ NULL, ++ 0, ++ NULL, ++ &Event, ++ &IoStatus); + - /* Is a device connected to this port */ - if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT) - { - /* Clear the Connect from ProtChange */ - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN, - 0, - USB_REQUEST_CLEAR_FEATURE, - C_PORT_CONNECTION, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PORTSTATUSANDCHANGE), - 0); - - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Clear the Port Connect!\n"); - goto CleanUp; - } ++ // ++ // Get Next Stack Location and Initialize it. ++ // ++ Stack = IoGetNextIrpStackLocation(Irp); ++ Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; ++ Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID; ++ Stack->Parameters.QueryInterface.Size = Size; ++ Stack->Parameters.QueryInterface.Version = Version; ++ Stack->Parameters.QueryInterface.Interface = Interface; ++ Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; + - /* Send the miniport controller a SCE request so when the port resets we can be informed */ - WaitForUsbDeviceArrivalNotification(DeviceObject); ++ Status = IoCallDriver(DeviceObject, Irp); + - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN, - 0, - USB_REQUEST_SET_FEATURE, - PORT_RESET, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PORTSTATUSANDCHANGE), - 0); - - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ if (Status == STATUS_PENDING) ++ { ++ DPRINT("Operation pending\n"); ++ KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); ++ Status = IoStatus.Status; ++ } + - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Reset the port!\n"); - goto CleanUp; - } - /* At this point the miniport will complete another SCE to inform of Reset completed */ - } ++ return Status; ++ } ++ ++ NTSTATUS ++ GetUsbDeviceDescriptor( ++ IN PDEVICE_OBJECT ChildDeviceObject, ++ IN UCHAR DescriptorType, ++ IN UCHAR Index, ++ IN USHORT LangId, ++ OUT PVOID TransferBuffer, ++ IN ULONG TransferBufferLength) ++ { ++ NTSTATUS Status; ++ PDEVICE_OBJECT RootHubDeviceObject; ++ PURB Urb; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; ++ ++ // ++ // Get the Hubs Device Extension ++ // ++ ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension; ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension; ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; ++ ++ // ++ // Allocate a URB ++ // ++ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); ++ if (!Urb) ++ { ++ DPRINT1("Failed to allocate memory for URB!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; + } + - CleanUp: - ExFreePool(WorkItemData); - ExFreePool(Urb); ++ // ++ // Zero it ++ // ++ RtlZeroMemory(Urb, sizeof(URB)); ++ ++ // ++ // Initialize URB for getting device descriptor ++ // ++ UsbBuildGetDescriptorRequest(Urb, ++ sizeof(Urb->UrbControlDescriptorRequest), ++ DescriptorType, ++ Index, ++ LangId, ++ TransferBuffer, ++ NULL, ++ TransferBufferLength, ++ NULL); ++ ++ // ++ // Set the device handle ++ // ++ Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceExtension->UsbDeviceHandle; ++ ++ // ++ // Query the Root Hub ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ Urb, ++ NULL); ++ ++ return Status; + } + + NTSTATUS - DeviceArrivalCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) ++ GetUsbStringDescriptor( ++ IN PDEVICE_OBJECT ChildDeviceObject, ++ IN UCHAR Index, ++ IN USHORT LangId, ++ OUT PVOID *TransferBuffer, ++ OUT USHORT *Size) + { - PHUB_DEVICE_EXTENSION DeviceExtension; - LONG i; - PWORKITEMDATA WorkItemData; ++ NTSTATUS Status; ++ PUSB_STRING_DESCRIPTOR StringDesc = NULL; ++ ULONG SizeNeeded; ++ LPWSTR Buffer; ++ ++ StringDesc = ExAllocatePoolWithTag(NonPagedPool, ++ sizeof(USB_STRING_DESCRIPTOR), ++ USB_HUB_TAG); ++ if (!StringDesc) ++ { ++ DPRINT1("Failed to allocate buffer for string!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - DeviceExtension = (PHUB_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension; ++ // ++ // Get the index string descriptor length ++ // FIXME: Implement LangIds ++ // ++ Status = GetUsbDeviceDescriptor(ChildDeviceObject, ++ USB_STRING_DESCRIPTOR_TYPE, ++ Index, ++ 0x0409, ++ StringDesc, ++ sizeof(USB_STRING_DESCRIPTOR)); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status); ++ ExFreePool(StringDesc); ++ return Status; ++ } ++ DPRINT1("StringDesc->bLength %d\n", StringDesc->bLength); + - for (i=0; i < DeviceExtension->UsbExtHubInfo.NumberOfPorts; i++) - DPRINT1("Port %x DeviceExtension->PortStatus %x\n",i+1, DeviceExtension->PortStatus[i]); ++ // ++ // Did we get something more than the length of the first two fields of structure? ++ // ++ if (StringDesc->bLength == 2) ++ { ++ DPRINT1("USB Device Error!\n"); ++ ExFreePool(StringDesc); ++ return STATUS_DEVICE_DATA_ERROR; ++ } ++ SizeNeeded = StringDesc->bLength + sizeof(WCHAR); ++ ++ // ++ // Free String ++ // ++ ExFreePool(StringDesc); ++ ++ // ++ // Recreate with appropriate size ++ // ++ StringDesc = ExAllocatePoolWithTag(NonPagedPool, ++ SizeNeeded, ++ USB_HUB_TAG); ++ if (!StringDesc) ++ { ++ DPRINT1("Failed to allocate buffer for string!\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - IoFreeIrp(Irp); ++ RtlZeroMemory(StringDesc, SizeNeeded); ++ ++ // ++ // Get the string ++ // ++ Status = GetUsbDeviceDescriptor(ChildDeviceObject, ++ USB_STRING_DESCRIPTOR_TYPE, ++ Index, ++ 0x0409, ++ StringDesc, ++ SizeNeeded); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status); ++ ExFreePool(StringDesc); ++ return Status; ++ } + - WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEMDATA)); - if (!WorkItemData) ++ // ++ // Allocate Buffer to return ++ // ++ Buffer = ExAllocatePoolWithTag(NonPagedPool, ++ SizeNeeded, ++ USB_HUB_TAG); ++ if (!Buffer) + { - DPRINT1("Failed to allocate memory\n"); - return STATUS_NO_MEMORY; ++ DPRINT1("Failed to allocate buffer for string!\n"); ++ ExFreePool(StringDesc); ++ return STATUS_INSUFFICIENT_RESOURCES; + } ++ DPRINT("Buffer %p\n", Buffer); ++ RtlZeroMemory(Buffer, SizeNeeded); + ++ DPRINT("SizeNeeded %lu\n", SizeNeeded); ++ DPRINT("Offset %lu\n", FIELD_OFFSET(USB_STRING_DESCRIPTOR, bLength)); ++ DPRINT("Length %lu\n", SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bLength)); + - RtlZeroMemory(WorkItemData, sizeof(WORKITEMDATA)); - WorkItemData->Context = Context; ++ // ++ // Copy the string to destination ++ // ++ RtlCopyMemory(Buffer, StringDesc->bString, SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)); ++ *Size = SizeNeeded; ++ *TransferBuffer = Buffer; + - ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)WorkerThread, (PVOID)WorkItemData); - ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue); - return STATUS_MORE_PROCESSING_REQUIRED; - } ++ ExFreePool(StringDesc); + ++ return STATUS_SUCCESS; ++ } + - NTSTATUS - WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject) ++ ULONG ++ IsCompositeDevice( ++ IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor, ++ IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) + { - PURB Urb; - PIRP Irp; - NTSTATUS Status; - PIO_STACK_LOCATION Stack = NULL; - PHUB_DEVICE_EXTENSION DeviceExtension; ++ if (DeviceDescriptor->bNumConfigurations != 1) ++ { ++ // ++ // composite device must have only one configuration ++ // ++ DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); ++ return FALSE; ++ } + - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ if (ConfigurationDescriptor->bNumInterfaces < 2) ++ { ++ // ++ // composite device must have multiple interfaces ++ // ++ DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); ++ return FALSE; ++ } + - Urb = &DeviceExtension->Urb; ++ if (DeviceDescriptor->bDeviceClass == 0) ++ { ++ // ++ // composite device ++ // ++ ASSERT(DeviceDescriptor->bDeviceSubClass == 0); ++ ASSERT(DeviceDescriptor->bDeviceProtocol == 0); ++ DPRINT1("IsCompositeDevice: TRUE\n"); ++ return TRUE; ++ } + - RtlZeroMemory(Urb, sizeof(URB)); ++ if (DeviceDescriptor->bDeviceClass == 0xEF && ++ DeviceDescriptor->bDeviceSubClass == 0x02 && ++ DeviceDescriptor->bDeviceProtocol == 0x01) ++ { ++ // ++ // USB-IF association descriptor ++ // ++ DPRINT1("IsCompositeDevice: TRUE\n"); ++ return TRUE; ++ } + - /* Send URB to the miniports Status Change Endpoint SCE */ - UsbBuildInterruptOrBulkTransferRequest(Urb, - sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), - DeviceExtension->PipeHandle, - &DeviceExtension->PortStatus, - NULL, - sizeof(ULONG) * 2, - USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, - NULL); ++ DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol); + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; ++ // ++ // not a composite device ++ // ++ return FALSE; ++ } + - Irp = IoAllocateIrp(DeviceExtension->RootHubPdo->StackSize, FALSE); ++ NTSTATUS ++ CreateDeviceIds( ++ PDEVICE_OBJECT UsbChildDeviceObject) ++ { ++ NTSTATUS Status = STATUS_SUCCESS; ++ ULONG Index = 0; ++ LPWSTR DeviceString; ++ WCHAR Buffer[200]; ++ PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; ++ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; ++ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; ++ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + - if (Irp == NULL) ++ // ++ // get child device extension ++ // ++ UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension; ++ ++ // ++ // get device descriptor ++ // ++ DeviceDescriptor = &UsbChildExtension->DeviceDesc; ++ ++ // ++ // get configuration descriptor ++ // ++ ConfigurationDescriptor = UsbChildExtension->FullConfigDesc; ++ ++ // ++ // use first interface descriptor available ++ // ++ InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, 0, -1, -1, -1, -1); ++ ASSERT(InterfaceDescriptor); ++ ++ // ++ // Construct the CompatibleIds ++ // ++ if (IsCompositeDevice(DeviceDescriptor, ConfigurationDescriptor)) + { - DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; ++ // ++ // sanity checks ++ // ++ ASSERT(DeviceDescriptor->bNumConfigurations == 1); ++ ASSERT(ConfigurationDescriptor->bNumInterfaces > 1); ++ Index += swprintf(&Buffer[Index], ++ L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x", ++ DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\DevClass_%02x&SubClass_%02x", ++ DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\DevClass_%02x", ++ DeviceDescriptor->bDeviceClass) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\COMPOSITE") + 1; ++ } ++ else ++ { ++ // ++ // sanity checks for simple usb device ++ // ++ ASSERT(ConfigurationDescriptor->bNumInterfaces == 1); ++ ++ // ++ // FIXME: support multiple configurations ++ // ++ ASSERT(DeviceDescriptor->bNumConfigurations == 1); ++ ++ if (DeviceDescriptor->bDeviceClass == 0) ++ { ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", ++ InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass, InterfaceDescriptor->bInterfaceProtocol) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x&SubClass_%02x", ++ InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x", ++ InterfaceDescriptor->bInterfaceClass) + 1; ++ } ++ else ++ { ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", ++ DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x&SubClass_%02x", ++ DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Class_%02x", ++ DeviceDescriptor->bDeviceClass) + 1; ++ } + } + ++ // ++ // now allocate the buffer ++ // ++ DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR)); ++ if (!DeviceString) ++ { ++ // ++ // no memory ++ // ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Information = 0; - Irp->Flags = 0; - Irp->UserBuffer = NULL; ++ // ++ // copy buffer ++ // ++ RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); ++ DeviceString[Index] = UNICODE_NULL; ++ UsbChildExtension->usCompatibleIds.Buffer = DeviceString; ++ UsbChildExtension->usCompatibleIds.Length = Index * sizeof(WCHAR); ++ UsbChildExtension->usCompatibleIds.MaximumLength = (Index + 1) * sizeof(WCHAR); ++ DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds); ++ ++ // ++ // Construct DeviceId string ++ // ++ Index = swprintf(Buffer, L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1; ++ ++ // ++ // now allocate the buffer ++ // ++ DeviceString = ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR)); ++ if (!DeviceString) ++ { ++ // ++ // no memory ++ // ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - Stack = IoGetCurrentIrpStackLocation(Irp); - Stack->DeviceObject = DeviceExtension->RootHubPdo; ++ // ++ // copy buffer ++ // ++ RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); ++ UsbChildExtension->usDeviceId.Buffer = DeviceString; ++ UsbChildExtension->usDeviceId.Length = (Index-1) * sizeof(WCHAR); ++ UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR); ++ DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId); ++ ++ // ++ // Construct HardwareIds ++ // ++ Index = 0; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Vid_%04x&Pid_%04x&Rev_%04x", ++ UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1; ++ Index += swprintf(&Buffer[Index], ++ L"USB\\Vid_%04x&Pid_%04x", ++ UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1; ++ ++ // ++ // now allocate the buffer ++ // ++ DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR)); ++ if (!DeviceString) ++ { ++ // ++ // no memory ++ // ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } + - Stack = IoGetNextIrpStackLocation(Irp); - Stack->DeviceObject = DeviceExtension->RootHubPdo; - Stack->Parameters.Others.Argument1 = Urb; - Stack->Parameters.Others.Argument2 = NULL; - Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; ++ // ++ // copy buffer ++ // ++ RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); ++ DeviceString[Index] = UNICODE_NULL; ++ UsbChildExtension->usHardwareIds.Buffer = DeviceString; ++ UsbChildExtension->usHardwareIds.Length = (Index + 1) * sizeof(WCHAR); ++ UsbChildExtension->usHardwareIds.MaximumLength = (Index + 1) * sizeof(WCHAR); ++ DPRINT("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds); ++ ++ // ++ // FIXME: Handle Lang ids ++ // ++ ++ // ++ // Get the product string if obe provided ++ // ++ if (UsbChildExtension->DeviceDesc.iProduct) ++ { ++ Status = GetUsbStringDescriptor(UsbChildDeviceObject, ++ UsbChildExtension->DeviceDesc.iProduct, ++ 0, ++ (PVOID*)&UsbChildExtension->usTextDescription.Buffer, ++ &UsbChildExtension->usTextDescription.Length); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status); ++ RtlInitUnicodeString(&UsbChildExtension->usTextDescription, L""); ++ } ++ else ++ { ++ UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length; ++ DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription); ++ } ++ } + - //IoSetCompletionRoutineEx(DeviceExtension->RootHubPdo, Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE); - IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE); ++ // ++ // Get the Serial Number string if obe provided ++ // ++ if (UsbChildExtension->DeviceDesc.iSerialNumber) ++ { ++ Status = GetUsbStringDescriptor(UsbChildDeviceObject, ++ UsbChildExtension->DeviceDesc.iSerialNumber, ++ 0, ++ (PVOID*)&UsbChildExtension->usInstanceId.Buffer, ++ &UsbChildExtension->usInstanceId.Length); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status); ++ return Status; ++ } + - Status = IoCallDriver(DeviceExtension->RootHubPdo, Irp); - DPRINT1("SCE request status %x\n", Status); ++ UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length; ++ DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId); ++ } ++ else ++ { ++ // ++ // the device did not provide a serial number, lets create a pseudo instance id ++ // ++ Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1; ++ UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR)); ++ if (UsbChildExtension->usInstanceId.Buffer == NULL) ++ { ++ DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR)); ++ Status = STATUS_INSUFFICIENT_RESOURCES; ++ return Status; ++ } ++ ++ // ++ // copy instance id ++ // ++ RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR)); ++ UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR); ++ ++ DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId); ++ } + - return STATUS_PENDING; ++ return Status; + } + + NTSTATUS - SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb) ++ DestroyUsbChildDeviceObject( ++ IN PDEVICE_OBJECT UsbHubDeviceObject, ++ IN LONG PortId) + { - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; - PIO_STACK_LOCATION Stack = NULL; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL; ++ PDEVICE_OBJECT ChildDeviceObject = NULL; ++ ULONG Index = 0; + - Irp = IoBuildDeviceIoControlRequest(IoControlCode, - Pdo, - NULL, 0, - NULL, 0, - TRUE, - NULL, - &IoStatus); ++ DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index); + - if (Irp == NULL) ++ for (Index = 0; Index < USB_MAXCHILDREN; Index++) + { - DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } ++ if (HubDeviceExtension->ChildDeviceObject[Index]) ++ { ++ UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension; + - /* Initialize the status block before sending the IRP */ - IoStatus.Status = STATUS_NOT_SUPPORTED; - IoStatus.Information = 0; ++ /* Check if it matches the port ID */ ++ if (UsbChildExtension->PortNumber == PortId) ++ { ++ /* We found it */ ++ ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index]; ++ break; ++ } ++ } ++ } + - Stack = IoGetNextIrpStackLocation(Irp); ++ /* Fail the request if the device doesn't exist */ ++ if (!ChildDeviceObject) ++ { ++ DPRINT1("Removal request for non-existant device!\n"); ++ return STATUS_UNSUCCESSFUL; ++ } + - Stack->Parameters.Others.Argument1 = Urb; - Stack->Parameters.Others.Argument2 = NULL; ++ /* Remove the device from the table */ ++ HubDeviceExtension->ChildDeviceObject[Index] = NULL; + - Status = IoCallDriver(Pdo, Irp); ++ /* Invalidate device relations for the root hub */ ++ IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations); + - return Status; ++ /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */ ++ return STATUS_SUCCESS; + } + + NTSTATUS - QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2) ++ CreateUsbChildDeviceObject( ++ IN PDEVICE_OBJECT UsbHubDeviceObject, ++ IN LONG PortId, ++ OUT PDEVICE_OBJECT *UsbChildDeviceObject, ++ IN ULONG PortStatus) + { - KEVENT Event; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; - PIO_STACK_LOCATION Stack = NULL; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); ++ PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; ++ PUSB_BUS_INTERFACE_HUB_V5 HubInterface; ++ ULONG ChildDeviceCount, UsbDeviceNumber = 0; ++ WCHAR CharDeviceName[64]; ++ UNICODE_STRING DeviceName; ++ ULONG ConfigDescSize, DeviceDescSize; ++ PVOID HubInterfaceBusContext; ++ USB_CONFIGURATION_DESCRIPTOR ConfigDesc; + - Irp = IoBuildDeviceIoControlRequest(IoControlCode, - Pdo, - NULL, 0, - NULL, 0, - TRUE, - &Event, - &IoStatus); ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension; ++ HubInterface = &HubDeviceExtension->HubInterface; ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; ++ HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext; ++ // ++ // Find an empty slot in the child device array ++ // ++ for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++) ++ { ++ if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL) ++ { ++ DPRINT("Found unused entry at %d\n", ChildDeviceCount); ++ break; ++ } ++ } + - if (Irp == NULL) ++ // ++ // Check if the limit has been reached for maximum usb devices ++ // ++ if (ChildDeviceCount == USB_MAXCHILDREN) + { - DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; ++ DPRINT1("USBHUB: Too many child devices!\n"); ++ return STATUS_UNSUCCESSFUL; + } + - /* Initialize the status block before sending the IRP */ - IoStatus.Status = STATUS_NOT_SUPPORTED; - IoStatus.Information = 0; ++ while (TRUE) ++ { ++ // ++ // Create a Device Name ++ // ++ swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber); ++ ++ // ++ // Initialize UnicodeString ++ // ++ RtlInitUnicodeString(&DeviceName, CharDeviceName); ++ ++ // ++ // Create a DeviceObject ++ // ++ Status = IoCreateDevice(UsbHubDeviceObject->DriverObject, ++ sizeof(HUB_CHILDDEVICE_EXTENSION), ++ NULL, ++ FILE_DEVICE_CONTROLLER, ++ FILE_AUTOGENERATED_DEVICE_NAME, ++ FALSE, ++ &NewChildDeviceObject); ++ ++ // ++ // Check if the name is already in use ++ // ++ if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION)) ++ { ++ // ++ // Try next name ++ // ++ UsbDeviceNumber++; ++ continue; ++ } + - Stack = IoGetNextIrpStackLocation(Irp); ++ // ++ // Check for other errors ++ // ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status); ++ return Status; ++ } + - Stack->Parameters.Others.Argument1 = OutParameter1; - Stack->Parameters.Others.Argument2 = OutParameter2; ++ DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject); ++ break; ++ } + - Status = IoCallDriver(Pdo, Irp); ++ NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE; ++ ++ // ++ // Assign the device extensions ++ // ++ UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension; ++ RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); ++ UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject; ++ UsbChildExtension->PortNumber = PortId; ++ ++ // ++ // Create the UsbDeviceObject ++ // ++ Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext, ++ (PVOID)&UsbChildExtension->UsbDeviceHandle, ++ HubDeviceExtension->RootHubHandle, ++ PortStatus, ++ PortId); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status); ++ goto Cleanup; ++ } + - if (Status == STATUS_PENDING) ++ // ++ // Initialize UsbDevice ++ // ++ Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle); ++ if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: Operation pending\n"); - KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; ++ DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status); ++ goto Cleanup; + } + - return Status; - } ++ DPRINT("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle); ++ ++ ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); ++ DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR); ++ ++ // ++ // Get the descriptors ++ // ++ Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext, ++ UsbChildExtension->UsbDeviceHandle, ++ (PUCHAR)&UsbChildExtension->DeviceDesc, ++ &DeviceDescSize, ++ (PUCHAR)&ConfigDesc, ++ &ConfigDescSize); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status); ++ goto Cleanup; ++ } + - NTSTATUS QueryInterface(IN PDEVICE_OBJECT Pdo, IN CONST GUID InterfaceType, IN LONG Size, IN LONG Version, OUT PVOID Interface) - { - KEVENT Event; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; - PIO_STACK_LOCATION Stack = NULL; ++ DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc); ++ DumpConfigurationDescriptor(&ConfigDesc); + - KeInitializeEvent(&Event, NotificationEvent, FALSE); ++ // ++ // FIXME: Support more than one configuration and one interface? ++ // ++ if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1) ++ { ++ DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n"); ++ } + - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, - Pdo, - NULL, - 0, - NULL, - &Event, - &IoStatus); ++ if (ConfigDesc.bNumInterfaces > 1) ++ { ++ DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n"); ++ } + - Stack = IoGetNextIrpStackLocation(Irp); - Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; - Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID; - Stack->Parameters.QueryInterface.Size = Size; - Stack->Parameters.QueryInterface.Version = Version; - Stack->Parameters.QueryInterface.Interface = Interface; - Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; ++ ConfigDescSize = ConfigDesc.wTotalLength; + - Status = IoCallDriver(Pdo, Irp); ++ // ++ // Allocate memory for the first full descriptor, including interfaces and endpoints. ++ // ++ UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG); + - if (Status == STATUS_PENDING) ++ // ++ // Retrieve the full configuration descriptor ++ // ++ Status = GetUsbDeviceDescriptor(NewChildDeviceObject, ++ USB_CONFIGURATION_DESCRIPTOR_TYPE, ++ 0, ++ 0, ++ UsbChildExtension->FullConfigDesc, ++ ConfigDescSize); ++ ++ if (!NT_SUCCESS(Status)) + { - DPRINT("Usbhub: Operation pending\n"); - KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; ++ DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status); ++ goto Cleanup; + } + - return Status; - } - - static VOID - UsbhubGetUserBuffers(IN PIRP Irp, IN ULONG IoControlCode, OUT PVOID* BufferIn, OUT PVOID* BufferOut) - { - ASSERT(Irp); - ASSERT(BufferIn); - ASSERT(BufferOut); ++ //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc); + - switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) ++ // ++ // Construct all the strings that will described the device to PNP ++ // ++ Status = CreateDeviceIds(NewChildDeviceObject); ++ if (!NT_SUCCESS(Status)) + { - case METHOD_BUFFERED: - *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer; - break; - case METHOD_IN_DIRECT: - case METHOD_OUT_DIRECT: - *BufferIn = Irp->AssociatedIrp.SystemBuffer; - *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress); - break; - case METHOD_NEITHER: - *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer; - *BufferOut = Irp->UserBuffer; - break; - default: - /* Should never happen */ - *BufferIn = NULL; - *BufferOut = NULL; - break; ++ DPRINT1("Failed to create strings needed to describe device to PNP.\n"); ++ goto Cleanup; + } ++ ++ HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject; ++ ++ IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations); ++ return STATUS_SUCCESS; ++ ++ Cleanup: ++ ++ // ++ // Remove the usb device if it was created ++ // ++ if (UsbChildExtension->UsbDeviceHandle) ++ HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0); ++ ++ // ++ // Free full configuration descriptor if one was allocated ++ // ++ if (UsbChildExtension->FullConfigDesc) ++ ExFreePool(UsbChildExtension->FullConfigDesc); ++ ++ // ++ // Delete the device object ++ // ++ IoDeleteDevice(NewChildDeviceObject); ++ return Status; + } + + NTSTATUS - UsbhubFdoQueryBusRelations(IN PDEVICE_OBJECT DeviceObject, OUT PDEVICE_RELATIONS* pDeviceRelations) ++ USBHUB_FdoQueryBusRelations( ++ IN PDEVICE_OBJECT DeviceObject, ++ OUT PDEVICE_RELATIONS* pDeviceRelations) + { - PHUB_DEVICE_EXTENSION DeviceExtension; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; + PDEVICE_RELATIONS DeviceRelations; + ULONG i; + ULONG Children = 0; + ULONG NeededSize; + - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - DPRINT1("USBHUB: Query Bus Relations\n"); ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + - /* Create PDOs that are missing */ ++ // ++ // Count the number of children ++ // + for (i = 0; i < USB_MAXCHILDREN; i++) + { + - if (DeviceExtension->UsbChildren[i] == NULL) ++ if (HubDeviceExtension->ChildDeviceObject[i] == NULL) + { + continue; + } + Children++; + } + - /* Fill returned structure */ + NeededSize = sizeof(DEVICE_RELATIONS); + if (Children > 1) + NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT); + ++ // ++ // Allocate DeviceRelations ++ // + DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, + NeededSize); + + if (!DeviceRelations) + return STATUS_INSUFFICIENT_RESOURCES; + DeviceRelations->Count = Children; + Children = 0; + ++ // ++ // Fill in return structure ++ // + for (i = 0; i < USB_MAXCHILDREN; i++) + { - if (DeviceExtension->Children[i]) ++ if (HubDeviceExtension->ChildDeviceObject[i]) + { - ObReferenceObject(DeviceExtension->Children[i]); - DeviceRelations->Objects[Children++] = DeviceExtension->Children[i]; ++ ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]); ++ HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING; ++ DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i]; + } + } + + ASSERT(Children == DeviceRelations->Count); + *pDeviceRelations = DeviceRelations; + - WaitForUsbDeviceArrivalNotification(DeviceObject); - + return STATUS_SUCCESS; + } + - VOID CallBackRoutine(IN PVOID Argument1) ++ VOID ++ NTAPI ++ RootHubInitCallbackFunction( ++ PVOID Context) + { - DPRINT1("RH_INIT_CALLBACK %x\n", Argument1); - ASSERT(FALSE); ++ PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context; ++ NTSTATUS Status; ++ ULONG PortId; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PORT_STATUS_CHANGE StatusChange; ++ ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; ++ ++ DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject); ++ ++ // ++ // Send the first SCE Request ++ // ++ QueryStatusChangeEndpoint(DeviceObject); ++ ++ for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) ++ { ++ // ++ // get port status ++ // ++ Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange); ++ if (NT_SUCCESS(Status)) ++ { ++ // ++ // is there a device connected ++ // ++ if (StatusChange.Status & USB_PORT_STATUS_CONNECT) ++ { ++ // ++ // reset port ++ // ++ Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to reset on port %d\n", PortId); ++ } ++ else ++ { ++ // ++ // wait for the reset to be handled since we want to enumerate synchronously ++ // ++ KeWaitForSingleObject(&HubDeviceExtension->ResetComplete, ++ Executive, ++ KernelMode, ++ FALSE, ++ NULL); ++ KeClearEvent(&HubDeviceExtension->ResetComplete); ++ } ++ } ++ } ++ } + } + - NTSTATUS NTAPI - UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) ++ NTSTATUS ++ USBHUB_FdoHandlePnp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) + { - PIO_STACK_LOCATION IrpSp; ++ PIO_STACK_LOCATION Stack; + NTSTATUS Status = STATUS_SUCCESS; - ULONG MinorFunction; + ULONG_PTR Information = 0; - PHUB_DEVICE_EXTENSION DeviceExtension; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PDEVICE_OBJECT RootHubDeviceObject; ++ PVOID HubInterfaceBusContext , UsbDInterfaceBusContext; ++ PORT_STATUS_CHANGE StatusChange; + - IrpSp = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = IrpSp->MinorFunction; ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + - DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; ++ Stack = IoGetCurrentIrpStackLocation(Irp); + - switch (MinorFunction) ++ switch (Stack->MinorFunction) + { - case IRP_MN_START_DEVICE: /* 0x0 */ ++ case IRP_MN_START_DEVICE: + { + PURB Urb; - ULONG Result = 0; + PUSB_INTERFACE_DESCRIPTOR Pid; - /* Theres only one descriptor on hub */ ++ ULONG Result = 0, PortId; + USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; + PURB ConfigUrb = NULL; ++ ULONG HubStatus; + - /* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */ - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); ++ DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); + - /* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */ ++ // ++ // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY ++ // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG); + RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY)); + - /* Get the hubs PDO */ - QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo); - ASSERT(DeviceExtension->RootHubPdo); - ASSERT(DeviceExtension->RootHubFdo); - DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo); - - /* Send the START_DEVICE irp down to the PDO of RootHub */ - Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp); ++ // ++ // Get the Root Hub Pdo ++ // ++ SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, ++ IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, ++ &HubDeviceExtension->RootHubPhysicalDeviceObject, ++ &HubDeviceExtension->RootHubFunctionalDeviceObject); ++ ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; ++ ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject); ++ ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject); ++ DPRINT("RootPdo %x, RootFdo %x\n", ++ HubDeviceExtension->RootHubPhysicalDeviceObject, ++ HubDeviceExtension->RootHubFunctionalDeviceObject); ++ ++ // ++ // Send the StartDevice to RootHub ++ // ++ Status = ForwardIrpAndWait(RootHubDeviceObject, Irp); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to start the RootHub PDO\n"); + ASSERT(FALSE); + } + - /* Get the current number of hubs */ - QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL); - - /* Get the Direct Call Interfaces */ - Status = QueryInterface(DeviceExtension->RootHubPdo, ++ // ++ // Get the current number of hubs ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_GET_HUB_COUNT, ++ &HubDeviceExtension->NumberOfHubs, NULL); ++ ++ // ++ // Get the Hub Interface ++ // ++ Status = QueryInterface(RootHubDeviceObject, + USB_BUS_INTERFACE_HUB_GUID, + sizeof(USB_BUS_INTERFACE_HUB_V5), + 5, - (PVOID)&DeviceExtension->HubInterface); ++ (PVOID)&HubDeviceExtension->HubInterface); ++ + if (!NT_SUCCESS(Status)) + { - DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status); ++ DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status); + return STATUS_UNSUCCESSFUL; + } + - Status = QueryInterface(DeviceExtension->RootHubPdo, ++ HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext; ++ ++ // ++ // Get the USBDI Interface ++ // ++ Status = QueryInterface(RootHubDeviceObject, + USB_BUS_INTERFACE_USBDI_GUID, + sizeof(USB_BUS_INTERFACE_USBDI_V2), + 2, - (PVOID)&DeviceExtension->UsbDInterface); - if (!NT_SUCCESS(Status)) - { - DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); - return STATUS_UNSUCCESSFUL; - } ++ (PVOID)&HubDeviceExtension->UsbDInterface); + - /* Get roothub device handle */ - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); ++ DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); + return Status; + } + - Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo, - DeviceExtension->RootHubUsbDevice, - &DeviceExtension->DeviceInformation, - sizeof(USB_DEVICE_INFORMATION_0), - &Result); ++ UsbDInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext; + ++ // ++ // Get Root Hub Device Handle ++ // ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, ++ &HubDeviceExtension->RootHubHandle, ++ NULL); + - DPRINT("Status %x, Result %x\n", Status, Result); - DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel); - DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength); - DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber); - DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor); - DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress); - DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); ++ return Status; ++ } + - /* Get roothubs device descriptor */ ++ // ++ // Get Hub Device Information ++ // ++ Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext, ++ HubDeviceExtension->RootHubHandle, ++ &HubDeviceExtension->DeviceInformation, ++ sizeof(USB_DEVICE_INFORMATION_0), ++ &Result); ++ ++ DPRINT1("Status %x, Result 0x%08lx\n", Status, Result); ++ DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel); ++ DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength); ++ DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber); ++ DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor); ++ DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress); ++ DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes); ++ ++ // ++ // Get Root Hubs Device Descriptor ++ // + UsbBuildGetDescriptorRequest(Urb, + sizeof(Urb->UrbControlDescriptorRequest), + USB_DEVICE_DESCRIPTOR_TYPE, + 0, + 0, - &DeviceExtension->HubDeviceDescriptor, ++ &HubDeviceExtension->HubDeviceDescriptor, + NULL, + sizeof(USB_DEVICE_DESCRIPTOR), + NULL); + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; ++ Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle; ++ ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ Urb, ++ NULL); + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n"); ++ DPRINT1("Failed to get HubDeviceDescriptor!\n"); + } + - DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor); ++ DumpDeviceDescriptor(&HubDeviceExtension->HubDeviceDescriptor); + - /* Get roothubs configuration descriptor */ ++ // ++ // Get Root Hubs Configuration Descriptor ++ // + UsbBuildGetDescriptorRequest(Urb, + sizeof(Urb->UrbControlDescriptorRequest), + USB_CONFIGURATION_DESCRIPTOR_TYPE, + 0, + 0, - &DeviceExtension->HubConfigDescriptor, ++ &HubDeviceExtension->HubConfigDescriptor, + NULL, + sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), + NULL); - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ DPRINT("RootHub Handle %x\n", HubDeviceExtension->RootHubHandle); ++ Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle; ++ ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ Urb, ++ NULL); + + if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status); ++ DPRINT1("Failed to get RootHub Configuration with status %x\n", Status); + ASSERT(FALSE); + } - ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength); ++ ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength); + - DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor); - //DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength); ++ DumpConfigurationDescriptor(&HubDeviceExtension->HubConfigDescriptor); + - Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo, - DeviceExtension->RootHubPdo, - &DeviceExtension->UsbExtHubInfo, - sizeof(USB_EXTHUB_INFORMATION_0), - &Result); ++ Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext, ++ RootHubDeviceObject, ++ &HubDeviceExtension->UsbExtHubInfo, ++ sizeof(USB_EXTHUB_INFORMATION_0), ++ &Result); + if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n"); ++ DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n"); + ASSERT(FALSE); + } + - DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts); ++ DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts); + ++ // ++ // Get the Hub Descriptor ++ // + UsbBuildVendorRequest(Urb, + URB_FUNCTION_CLASS_DEVICE, + sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN, ++ USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, + 0, ++ USB_REQUEST_GET_DESCRIPTOR, + USB_DEVICE_CLASS_RESERVED, + 0, - 0, - &DeviceExtension->HubDescriptor, ++ &HubDeviceExtension->HubDescriptor, + NULL, + sizeof(USB_HUB_DESCRIPTOR), + NULL); + - Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; ++ Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle; ++ ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ Urb, ++ NULL); ++ ++ DPRINT1("bDescriptorType %x\n", HubDeviceExtension->HubDescriptor.bDescriptorType); ++ ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to get Hub Descriptor!\n"); ++ ExFreePool(Urb); ++ return STATUS_UNSUCCESSFUL; ++ } ++ ++ HubStatus = 0; ++ UsbBuildGetStatusRequest(Urb, ++ URB_FUNCTION_GET_STATUS_FROM_DEVICE, ++ 0, ++ &HubStatus, ++ 0, ++ NULL); ++ Urb->UrbHeader.UsbdDeviceHandle = NULL;//HubDeviceExtension->RootHubHandle; ++ ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ Urb, ++ NULL); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to get Hub Status!\n"); ++ ExFreePool(Urb); ++ return STATUS_UNSUCCESSFUL; ++ } + - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); ++ DPRINT1("HubStatus %x\n", HubStatus); + - DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType); ++ // ++ // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub ++ // ++ HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool, ++ sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts, ++ USB_HUB_TAG); + - /* Select the configuration */ ++ // ++ // Get the first Configuration Descriptor ++ // ++ Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, ++ &HubDeviceExtension->HubConfigDescriptor, ++ -1, -1, -1, -1, -1); + - /* Get the first one */ - Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor, - &DeviceExtension->HubConfigDescriptor, - -1, -1, -1, -1, -1); + ASSERT(Pid != NULL); ++ + InterfaceList[0].InterfaceDescriptor = Pid; - ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); ++ ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, ++ (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); + ASSERT(ConfigUrb != NULL); - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL); + - DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; - DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; - DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle); ++ Status = SubmitRequestToRootHub(RootHubDeviceObject, ++ IOCTL_INTERNAL_USB_SUBMIT_URB, ++ ConfigUrb, ++ NULL); ++ ++ HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; ++ HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; ++ DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); ++ ++ // ++ // check if function is available ++ // ++ if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed) ++ { ++ // ++ // is it high speed bus ++ // ++ if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext)) ++ { ++ // ++ // initialize usb 2.0 hub ++ // ++ Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext, ++ HubDeviceExtension->RootHubHandle, 1); ++ DPRINT("Status %x\n", Status); ++ ++ // ++ // FIXME handle error ++ // ++ ASSERT(Status == STATUS_SUCCESS); ++ } ++ } + + ExFreePool(ConfigUrb); + - Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1); - DPRINT1("Status %x\n", Status); ++ // ++ // Enable power on all ports ++ // + ++ DPRINT("Enabling PortPower on all ports!\n"); ++ ++ for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) + { - int PortLoop; - USHORT PortStatusAndChange[2]; ++ Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER); ++ if (!NT_SUCCESS(Status)) ++ DPRINT1("Failed to power on port %d\n", PortId); ++ ++ Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION); ++ if (!NT_SUCCESS(Status)) ++ DPRINT1("Failed to power on port %d\n", PortId); ++ } ++ ++ DPRINT("RootHubInitNotification %x\n", HubDeviceExtension->HubInterface.RootHubInitNotification); + - for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) ++ // ++ // init root hub notification ++ // ++ if (HubDeviceExtension->HubInterface.RootHubInitNotification) ++ { ++ Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext, ++ DeviceObject, ++ RootHubInitCallbackFunction); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to set callback\n"); ++ } ++ } ++ else ++ { ++ // ++ // Send the first SCE Request ++ // ++ QueryStatusChangeEndpoint(DeviceObject); ++ ++ // ++ // reset ports ++ // ++ for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) + { - DPRINT1("Port %x\n", PortLoop); - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN, - 0, - USB_REQUEST_SET_FEATURE, - PORT_POWER, - 1, - 0, - 0, - 0, - 0); - - Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1; - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - DPRINT1("Status %x\n", Status); - - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_OTHER, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_OUT, - 0, - USB_REQUEST_GET_STATUS, - 0, - PortLoop + 1, - &PortStatusAndChange, - 0, - sizeof(PortStatusAndChange), - 0); - Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - DPRINT1("Status %x\n", Status); - DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]); - DPRINT1("PortChange = %x\n", PortStatusAndChange[1]); ++ // ++ // get port status ++ // ++ Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange); ++ if (NT_SUCCESS(Status)) ++ { ++ // ++ // is there a device connected ++ // ++ if (StatusChange.Status & USB_PORT_STATUS_CONNECT) ++ { ++ // ++ // reset port ++ // ++ Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("Failed to reset on port %d\n", PortId); ++ } ++ else ++ { ++ // ++ // wait for the reset to be handled since we want to enumerate synchronously ++ // ++ KeWaitForSingleObject(&HubDeviceExtension->ResetComplete, ++ Executive, ++ KernelMode, ++ FALSE, ++ NULL); ++ KeClearEvent(&HubDeviceExtension->ResetComplete); ++ } ++ } ++ } + } + } + + ExFreePool(Urb); + break; + } + - case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ ++ case IRP_MN_QUERY_DEVICE_RELATIONS: + { - switch (IrpSp->Parameters.QueryDeviceRelations.Type) ++ switch (Stack->Parameters.QueryDeviceRelations.Type) + { + case BusRelations: + { + PDEVICE_RELATIONS DeviceRelations = NULL; - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); + - Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations); ++ Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations); + + Information = (ULONG_PTR)DeviceRelations; + break; + } + case RemovalRelations: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); + return ForwardIrpAndForget(DeviceObject, Irp); + } + default: - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", - IrpSp->Parameters.QueryDeviceRelations.Type); ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", ++ Stack->Parameters.QueryDeviceRelations.Type); + return ForwardIrpAndForget(DeviceObject, Irp); + } + break; + } - case IRP_MN_QUERY_BUS_INFORMATION: - { - DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n"); - break; - } - case IRP_MN_QUERY_ID: - { - DPRINT1("IRP_MN_QUERY_ID\n"); - break; - } - case IRP_MN_QUERY_CAPABILITIES: - { - DPRINT1("IRP_MN_QUERY_CAPABILITIES\n"); - break; - } - default: ++ case IRP_MN_QUERY_REMOVE_DEVICE: ++ case IRP_MN_QUERY_STOP_DEVICE: + { - DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); ++ Irp->IoStatus.Status = STATUS_SUCCESS; + return ForwardIrpAndForget(DeviceObject, Irp); + } - } - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - NTSTATUS - UsbhubDeviceControlFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) - { - PIO_STACK_LOCATION Stack; - ULONG IoControlCode; - PHUB_DEVICE_EXTENSION DeviceExtension; - ULONG LengthIn, LengthOut; - ULONG_PTR Information = 0; - PVOID BufferIn, BufferOut; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - Stack = IoGetCurrentIrpStackLocation(Irp); - LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; - LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; - UsbhubGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut); - - switch (IoControlCode) - { - case IOCTL_USB_GET_NODE_INFORMATION: ++ case IRP_MN_REMOVE_DEVICE: + { - //PUSB_NODE_INFORMATION NodeInformation; ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); + - DPRINT1("Usbhub: IOCTL_USB_GET_NODE_INFORMATION\n"); - if (LengthOut < sizeof(USB_NODE_INFORMATION)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (BufferOut == NULL) - Status = STATUS_INVALID_PARAMETER; - else - { - /*NodeInformation = (PUSB_NODE_INFORMATION)BufferOut; - dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev; - NodeInformation->NodeType = UsbHub; - RtlCopyMemory( - &NodeInformation->u.HubInformation.HubDescriptor, - ((struct usb_hub *)usb_get_intfdata(to_usb_interface(&dev->actconfig->interface[0].dev)))->descriptor, - sizeof(USB_HUB_DESCRIPTOR)); - NodeInformation->u.HubInformation.HubIsBusPowered = dev->actconfig->desc.bmAttributes & 0x80; - Information = sizeof(USB_NODE_INFORMATION);*/ - Status = STATUS_SUCCESS; - } - break; - } - case IOCTL_USB_GET_NODE_CONNECTION_NAME: - { - PHUB_DEVICE_EXTENSION DeviceExtension; - PUSB_NODE_CONNECTION_NAME ConnectionName; - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - ConnectionName = (PUSB_NODE_CONNECTION_NAME)BufferOut; - - DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME\n"); - if (LengthOut < sizeof(USB_NODE_CONNECTION_NAME)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (BufferOut == NULL) - Status = STATUS_INVALID_PARAMETER; - else if (ConnectionName->ConnectionIndex < 1 - || ConnectionName->ConnectionIndex > USB_MAXCHILDREN) - Status = STATUS_INVALID_PARAMETER; - else if (DeviceExtension->Children[ConnectionName->ConnectionIndex - 1] == NULL) - Status = STATUS_INVALID_PARAMETER; - else - { - ULONG NeededStructureSize; - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceExtension->Children[ConnectionName->ConnectionIndex - 1]->DeviceExtension; - NeededStructureSize = DeviceExtension->SymbolicLinkName.Length + sizeof(UNICODE_NULL) + FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName); - if (ConnectionName->ActualLength < NeededStructureSize / sizeof(WCHAR) - || LengthOut < NeededStructureSize) - { - /* Buffer too small */ - ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR); - Information = sizeof(USB_NODE_CONNECTION_NAME); - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - RtlCopyMemory( - ConnectionName->NodeName, - DeviceExtension->SymbolicLinkName.Buffer, - DeviceExtension->SymbolicLinkName.Length); - ConnectionName->NodeName[DeviceExtension->SymbolicLinkName.Length / sizeof(WCHAR)] = UNICODE_NULL; - DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME returns '%S'\n", ConnectionName->NodeName); - ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR); - Information = NeededStructureSize; - Status = STATUS_SUCCESS; - } - Information = LengthOut; - } - break; ++ IoDetachDevice(HubDeviceExtension->LowerDeviceObject); ++ IoDeleteDevice(DeviceObject); ++ ++ return STATUS_SUCCESS; + } - case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION: ++ case IRP_MN_QUERY_BUS_INFORMATION: + { - PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation; - /* - ULONG i, j, k; - struct usb_device* dev; - ULONG NumberOfOpenPipes = 0; - ULONG SizeOfOpenPipesArray; - */ - ConnectionInformation = (PUSB_NODE_CONNECTION_INFORMATION)BufferOut; - - DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n"); - if (LengthOut < sizeof(USB_NODE_CONNECTION_INFORMATION)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (BufferOut == NULL) - Status = STATUS_INVALID_PARAMETER; - else if (ConnectionInformation->ConnectionIndex < 1 - || ConnectionInformation->ConnectionIndex > USB_MAXCHILDREN) - Status = STATUS_INVALID_PARAMETER; - else - { - DPRINT1("Usbhub: We should succeed\n"); - } ++ DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); + break; + } - case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION: ++ case IRP_MN_QUERY_ID: + { - //PUSB_DESCRIPTOR_REQUEST Descriptor; - DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n"); - Information = 0; - Status = STATUS_NOT_IMPLEMENTED; ++ DPRINT("IRP_MN_QUERY_ID\n"); + break; + } - case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME: ++ case IRP_MN_QUERY_CAPABILITIES: + { - PHUB_DEVICE_EXTENSION DeviceExtension; - PUSB_NODE_CONNECTION_DRIVERKEY_NAME StringDescriptor; - DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n"); - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - StringDescriptor = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)BufferOut; - if (LengthOut < sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (StringDescriptor == NULL) - Status = STATUS_INVALID_PARAMETER; - else if (StringDescriptor->ConnectionIndex < 1 - || StringDescriptor->ConnectionIndex > USB_MAXCHILDREN) - Status = STATUS_INVALID_PARAMETER; - else if (DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1] == NULL) - Status = STATUS_INVALID_PARAMETER; - else - { - ULONG StringSize; - Status = IoGetDeviceProperty( - DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1], - DevicePropertyDriverKeyName, - LengthOut - FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName), - StringDescriptor->DriverKeyName, - &StringSize); - if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) - { - StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName); - Information = LengthOut; - Status = STATUS_SUCCESS; - } - } ++ DPRINT("IRP_MN_QUERY_CAPABILITIES\n"); + break; + } + default: + { - /* Pass Irp to lower driver */ - DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); ++ DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } ++ ++ NTSTATUS ++ USBHUB_FdoHandleDeviceControl( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ DPRINT1("FdoHandleDeviceControl\n"); ++ UNIMPLEMENTED ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ diff --cc reactos/drivers/usb/usbhub/pdo.c index f217c6da0a1,00000000000,d5d2d3e0d05..d5d2d3e0d05 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbhub/pdo.c +++ b/reactos/drivers/usb/usbhub/pdo.c @@@@ -1,314 -1,0 -1,662 +1,662 @@@@ - /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: USB hub driver - * FILE: drivers/usb/cromwell/hub/pdo.c - * PURPOSE: IRP_MJ_PNP operations for PDOs - * - * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) - * 2010 Michael Martin (michael.martin@reactos.org) ++ /* ++ * PROJECT: ReactOS Universal Serial Bus Hub Driver ++ * LICENSE: GPL - See COPYING in the top level directory ++ * FILE: drivers/usb/usbhub/fdo.c ++ * PURPOSE: Handle PDO ++ * PROGRAMMERS: ++ * Hervé Poussineau (hpoussin@reactos.org) ++ * Michael Martin (michael.martin@reactos.org) ++ * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + - #define NDEBUG - #include + #include "usbhub.h" + + #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) + + NTSTATUS - UsbhubInternalDeviceControlPdo( ++ NTAPI ++ UrbCompletion( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp, ++ PVOID Context) ++ { ++ PIRP OriginalIrp; ++ DPRINT("Entered Urb Completion\n"); ++ ++ // ++ // Get the original Irp ++ // ++ OriginalIrp = (PIRP)Context; ++ ++ // ++ // Update it to match what was returned for the IRP that was passed to RootHub ++ // ++ OriginalIrp->IoStatus.Status = Irp->IoStatus.Status; ++ OriginalIrp->IoStatus.Information = Irp->IoStatus.Information; ++ DPRINT("Status %x, Information %x\n", Irp->IoStatus.Status, Irp->IoStatus.Information); ++ ++ // ++ // Complete the original Irp ++ // ++ IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT); ++ ++ // ++ // Return this status so the IO Manager doesnt mess with the Irp ++ // ++ return STATUS_MORE_PROCESSING_REQUIRED; ++ } ++ ++ NTSTATUS ++ FowardUrbToRootHub( ++ PDEVICE_OBJECT RootHubDeviceObject, ++ IN ULONG IoControlCode, ++ PIRP Irp, ++ OUT PVOID OutParameter1, ++ OUT PVOID OutParameter2) ++ { ++ NTSTATUS Status; ++ PIRP ForwardIrp; ++ IO_STATUS_BLOCK IoStatus; ++ PIO_STACK_LOCATION ForwardStack, CurrentStack; ++ PURB Urb; ++ ++ // ++ // Get the current stack location for the Irp ++ // ++ CurrentStack = IoGetCurrentIrpStackLocation(Irp); ++ ASSERT(CurrentStack); ++ ++ // ++ // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub ++ // ++ Urb = (PURB)CurrentStack->Parameters.Others.Argument1; ++ ASSERT(Urb); ++ ++ // ++ // Create the Irp to forward to RootHub ++ // ++ ForwardIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN, ++ RootHubDeviceObject, ++ NULL, ++ 0, ++ 0, ++ &IoStatus); ++ if (!ForwardIrp) ++ { ++ DPRINT1("Failed to allocate IRP\n"); ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } ++ ++ // ++ // Get the new Irps next stack ++ // ++ ForwardStack = IoGetNextIrpStackLocation(ForwardIrp); ++ ++ // ++ // Copy the stack for the current irp into the next stack of new irp ++ // ++ RtlCopyMemory(ForwardStack, CurrentStack, sizeof(IO_STACK_LOCATION)); ++ ++ IoStatus.Status = STATUS_NOT_SUPPORTED; ++ IoStatus.Information = 0; ++ ++ // ++ // Mark the Irp from upper driver as pending ++ // ++ IoMarkIrpPending(Irp); ++ ++ // ++ // Now set the completion routine for the new Irp. ++ // ++ IoSetCompletionRoutine(ForwardIrp, ++ UrbCompletion, ++ Irp, ++ TRUE, ++ TRUE, ++ TRUE); ++ ++ Status = IoCallDriver(RootHubDeviceObject, ForwardIrp); ++ ++ // ++ // Always return pending as the completion routine will take care of it ++ // ++ return STATUS_PENDING; ++ } ++ ++ NTSTATUS ++ USBHUB_PdoHandleInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { ++ NTSTATUS Status; + PIO_STACK_LOCATION Stack; + ULONG_PTR Information = 0; - NTSTATUS Status; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; ++ PDEVICE_OBJECT RootHubDeviceObject; ++ PURB Urb; + - DPRINT1("Usbhub: UsbhubInternalDeviceControlPdo() called\n"); ++ //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject); + ++ // ++ // get current stack location ++ // + Stack = IoGetCurrentIrpStackLocation(Irp); ++ ASSERT(Stack); ++ ++ // ++ // Set default status ++ // + Status = Irp->IoStatus.Status; + ++ ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; ++ RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; ++ + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: + { + PHUB_DEVICE_EXTENSION DeviceExtension; + - DPRINT1("Usbhub: IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n"); ++ DPRINT("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n"); + if (Irp->AssociatedIrp.SystemBuffer == NULL + || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PVOID* pHubPointer; + DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer; - *pHubPointer = DeviceExtension->dev; ++ // FIXME ++ *pHubPointer = NULL; + Information = sizeof(PVOID); + Status = STATUS_SUCCESS; + } + break; + } ++ case IOCTL_INTERNAL_USB_SUBMIT_URB: ++ { ++ //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n"); ++ ++ // ++ // Get the Urb ++ // ++ Urb = (PURB)Stack->Parameters.Others.Argument1; ++ ASSERT(Urb); ++ ++ // ++ // Set the real device handle ++ // ++ //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle); ++ ++ Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle; ++ ++ // ++ // Submit to RootHub ++ // ++ switch (Urb->UrbHeader.Function) ++ { ++ // ++ // Debugging only ++ // ++ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: ++ DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n"); ++ break; ++ case URB_FUNCTION_CLASS_DEVICE: ++ DPRINT1("URB_FUNCTION_CLASS_DEVICE\n"); ++ break; ++ case URB_FUNCTION_GET_STATUS_FROM_DEVICE: ++ DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n"); ++ break; ++ case URB_FUNCTION_SELECT_CONFIGURATION: ++ DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n"); ++ break; ++ case URB_FUNCTION_SELECT_INTERFACE: ++ DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n"); ++ break; ++ case URB_FUNCTION_CLASS_OTHER: ++ DPRINT1("URB_FUNCTION_CLASS_OTHER\n"); ++ break; ++ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: ++ { ++ /* ++ DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n"); ++ DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle); ++ DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags); ++ DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer); ++ DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); ++ DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); ++ DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink); ++ DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca); ++ if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK) ++ { ++ } ++ */ ++ break; ++ ++ } ++ case URB_FUNCTION_CLASS_INTERFACE: ++ DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n"); ++ break; ++ default: ++ DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function); ++ break; ++ } ++ Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle; ++ //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine); ++ // ++ // Send the request to RootHub ++ // ++ Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL); ++ return Status; ++ break; ++ } ++ // ++ // FIXME: Can these be sent to RootHub? ++ // ++ case IOCTL_INTERNAL_USB_RESET_PORT: ++ DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n"); ++ break; ++ case IOCTL_INTERNAL_USB_GET_PORT_STATUS: ++ { ++ PORT_STATUS_CHANGE PortStatus; ++ LONG PortId; ++ PUCHAR PortStatusBits; ++ ++ PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1; ++ // ++ // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1) ++ // ++ DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n"); ++ DPRINT("Arg1 %x\n", *PortStatusBits); ++ *PortStatusBits = 0; ++ if (Stack->Parameters.Others.Argument1) ++ { ++ for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++) ++ { ++ Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); ++ if (NT_SUCCESS(Status)) ++ { ++ DPRINT("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)); ++ DPRINT("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2)); ++ *PortStatusBits += ++ (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) + ++ (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2)); ++ ++ } ++ } ++ } ++ ++ DPRINT1("Arg1 %x\n", *PortStatusBits); ++ Status = STATUS_SUCCESS; ++ break; ++ } ++ case IOCTL_INTERNAL_USB_ENABLE_PORT: ++ DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n"); ++ break; ++ case IOCTL_INTERNAL_USB_CYCLE_PORT: ++ DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n"); ++ break; ++ case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: ++ DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); ++ break; + default: + { - DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); ++ DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + } + } + - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ if (Status != STATUS_PENDING) ++ { ++ Irp->IoStatus.Information = Information; ++ Irp->IoStatus.Status = Status; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ } + return Status; + } + - static NTSTATUS - UsbhubPdoStartDevice( ++ NTSTATUS ++ USBHUB_PdoStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { - PHUB_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - - DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* Register and activate device interface */ - /* - Status = IoRegisterDeviceInterface( - DeviceObject, - DeviceExtension->dev->descriptor.bDeviceClass == USB_CLASS_HUB ? - &GUID_DEVINTERFACE_USB_HUB : - &GUID_DEVINTERFACE_USB_DEVICE, - NULL, - &DeviceExtension->SymbolicLinkName); - */ - if (!NT_SUCCESS(Status)) - { - DPRINT1("Usbhub: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status); - return Status; - } ++ PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; ++ //NTSTATUS Status; ++ DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject); ++ ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + - //Status = IoSetDeviceInterfaceState(&DeviceExtension->SymbolicLinkName, TRUE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Usbhub: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status); - return Status; - } ++ // ++ // This should be a PDO ++ // ++ ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); ++ ++ // ++ // FIXME: Fow now assume success ++ // + ++ UNIMPLEMENTED + return STATUS_SUCCESS; + } + - static NTSTATUS - UsbhubPdoQueryId( ++ NTSTATUS ++ USBHUB_PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + OUT ULONG_PTR* Information) + { - PHUB_CHILDDEVICE_EXTENSION DeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + ULONG IdType; - PWCHAR SourceString = NULL; ++ PUNICODE_STRING SourceString = NULL; ++ PWCHAR ReturnString = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; - DeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + switch (IdType) + { - case BusQueryDeviceID: ++ case BusQueryDeviceID: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); - SourceString = DeviceExtension->DeviceId; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); ++ SourceString = &ChildDeviceExtension->usDeviceId; + break; + } - /* FIXME: Implement */ + case BusQueryHardwareIDs: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); - SourceString = DeviceExtension->HardwareIds; - Status = STATUS_NOT_SUPPORTED; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); ++ SourceString = &ChildDeviceExtension->usHardwareIds; + break; + } - /* FIXME: Implement */ + case BusQueryCompatibleIDs: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); - SourceString = DeviceExtension->CompatibleIds; - Status = STATUS_NOT_SUPPORTED; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); ++ SourceString = &ChildDeviceExtension->usCompatibleIds; + break; + } + case BusQueryInstanceID: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); - SourceString = DeviceExtension->InstanceId; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); ++ SourceString = &ChildDeviceExtension->usInstanceId; + break; + } + default: - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); ++ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); + return STATUS_NOT_SUPPORTED; + } + - *Information = (ULONG_PTR)SourceString; ++ if (SourceString) ++ { ++ // ++ // allocate buffer ++ // ++ ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength); ++ if (!ReturnString) ++ { ++ // ++ // no memory ++ // ++ return STATUS_INSUFFICIENT_RESOURCES; ++ } ++ ++ // ++ // copy buffer ++ // ++ RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength); ++ } ++ ++ *Information = (ULONG_PTR)ReturnString; ++ + return Status; + } + - static NTSTATUS - UsbhubPdoQueryDeviceText( ++ NTSTATUS ++ USBHUB_PdoQueryDeviceText( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + OUT ULONG_PTR* Information) + { - PHUB_CHILDDEVICE_EXTENSION DeviceExtension; ++ PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + DEVICE_TEXT_TYPE DeviceTextType; ++ PUNICODE_STRING SourceString = NULL; ++ PWCHAR ReturnString = NULL; ++ NTSTATUS Status = STATUS_SUCCESS; + LCID LocaleId; + + DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType; + LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId; - DeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ++ // ++ // FIXME: LocaleId ++ // + + switch (DeviceTextType) + { + case DeviceTextDescription: + case DeviceTextLocationInformation: + { - if (DeviceTextType == DeviceTextDescription) ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); ++ ++ // ++ // does the device provide a text description ++ // ++ if (ChildDeviceExtension->usTextDescription.Buffer && ChildDeviceExtension->usTextDescription.Length) + { - *Information = (ULONG_PTR)DeviceExtension->TextDescription; - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); ++ // ++ // use device text ++ // ++ SourceString = &ChildDeviceExtension->usTextDescription; + } - else - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n"); - - /* if (!DeviceExtension->dev->descriptor.iProduct) - return STATUS_NOT_SUPPORTED;*/ - - return STATUS_SUCCESS; ++ break; + } + default: - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType); - return STATUS_NOT_SUPPORTED; ++ { ++ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType); ++ Status = STATUS_NOT_SUPPORTED; ++ break; ++ } ++ } ++ ++ if (SourceString) ++ { ++ ReturnString = ExAllocatePool(PagedPool, SourceString->Length); ++ RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length); ++ DPRINT1("%S\n", ReturnString); ++ *Information = (ULONG_PTR)ReturnString; + } ++ ++ return Status; + } + - NTSTATUS NTAPI - UsbhubPnpPdo( ++ NTSTATUS ++ USBHUB_PdoHandlePnp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { ++ NTSTATUS Status; + ULONG MinorFunction; + PIO_STACK_LOCATION Stack; + ULONG_PTR Information = 0; - NTSTATUS Status; ++ PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; ++ ULONG Index; ++ ULONG bFound; ++ PDEVICE_RELATIONS DeviceRelation; + ++ UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + MinorFunction = Stack->MinorFunction; + + switch (MinorFunction) + { - case IRP_MN_START_DEVICE: /* 0x0 */ ++ case IRP_MN_START_DEVICE: + { - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); - Status = UsbhubPdoStartDevice(DeviceObject, Irp); ++ DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); ++ Status = USBHUB_PdoStartDevice(DeviceObject, Irp); + break; + } - case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */ ++ case IRP_MN_QUERY_CAPABILITIES: + { + PDEVICE_CAPABILITIES DeviceCapabilities; + ULONG i; - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); + + DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; - /* FIXME: capabilities can change with connected device */ - DeviceCapabilities->LockSupported = TRUE; ++ // FIXME: capabilities can change with connected device ++ DeviceCapabilities->LockSupported = FALSE; + DeviceCapabilities->EjectSupported = FALSE; - DeviceCapabilities->Removable = FALSE; ++ DeviceCapabilities->Removable = TRUE; + DeviceCapabilities->DockDevice = FALSE; + DeviceCapabilities->UniqueID = FALSE; - DeviceCapabilities->SilentInstall = TRUE; ++ DeviceCapabilities->SilentInstall = FALSE; + DeviceCapabilities->RawDeviceOK = FALSE; + DeviceCapabilities->SurpriseRemovalOK = FALSE; - DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */ - //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */ - DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */ - for (i = 0; i < PowerSystemMaximum; i++) - DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */ - //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */ - DeviceCapabilities->D1Latency = 0; /* FIXME */ - DeviceCapabilities->D2Latency = 0; /* FIXME */ - DeviceCapabilities->D3Latency = 0; /* FIXME */ ++ DeviceCapabilities->HardwareDisabled = FALSE; ++ //DeviceCapabilities->NoDisplayInUI = FALSE; ++ DeviceCapabilities->Address = UsbChildExtension->PortNumber; ++ DeviceCapabilities->UINumber = 0; ++ DeviceCapabilities->DeviceState[0] = PowerDeviceD0; ++ for (i = 1; i < PowerSystemMaximum; i++) ++ DeviceCapabilities->DeviceState[i] = PowerDeviceD3; ++ //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; ++ DeviceCapabilities->D1Latency = 0; ++ DeviceCapabilities->D2Latency = 0; ++ DeviceCapabilities->D3Latency = 0; + Status = STATUS_SUCCESS; + break; + } - case IRP_MN_QUERY_RESOURCES: /* 0x0a */ ++ case IRP_MN_QUERY_RESOURCES: + { - PCM_RESOURCE_LIST ResourceList; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); + - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); - ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST)); - if (!ResourceList) - { - DPRINT1("Usbhub: ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - ResourceList->Count = 0; - Information = (ULONG_PTR)ResourceList; - Status = STATUS_SUCCESS; - } ++ Information = Irp->IoStatus.Information; ++ Status = Irp->IoStatus.Status; + break; + } - case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */ ++ case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + { - PIO_RESOURCE_REQUIREMENTS_LIST ResourceList; ++ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); ++ ++ Information = Irp->IoStatus.Information; ++ Status = Irp->IoStatus.Status; ++ break; ++ } ++ case IRP_MN_QUERY_DEVICE_TEXT: ++ { ++ Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information); ++ break; ++ } ++ case IRP_MN_QUERY_ID: ++ { ++ Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information); ++ break; ++ } ++ case IRP_MN_QUERY_BUS_INFORMATION: ++ { ++ PPNP_BUS_INFORMATION BusInfo; ++ BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); ++ RtlCopyMemory(&BusInfo->BusTypeGuid, ++ &GUID_BUS_TYPE_USB, ++ sizeof(BusInfo->BusTypeGuid)); ++ BusInfo->LegacyBusType = PNPBus; ++ // FIXME ++ BusInfo->BusNumber = 0; ++ Information = (ULONG_PTR)BusInfo; ++ Status = STATUS_SUCCESS; ++ break; ++ } ++ case IRP_MN_REMOVE_DEVICE: ++ { ++ PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension; ++ PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface; ++ ++ DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); + - DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); - ResourceList = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST)); - if (!ResourceList) ++ /* remove us from pdo list */ ++ bFound = FALSE; ++ for(Index = 0; Index < USB_MAXCHILDREN; Index++) + { - DPRINT1("Usbhub: ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; ++ if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject) ++ { ++ /* Remove the device */ ++ Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0); ++ ++ /* FIXME handle error */ ++ ASSERT(Status == STATUS_SUCCESS); ++ ++ /* remove us */ ++ HubDeviceExtension->ChildDeviceObject[Index] = NULL; ++ bFound = TRUE; ++ break; ++ } + } - else ++ ++ /* Complete the IRP */ ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ ++ if (bFound) + { - RtlZeroMemory(ResourceList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST)); - ResourceList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); - ResourceList->AlternativeLists = 1; - ResourceList->List->Version = 1; - ResourceList->List->Revision = 1; - ResourceList->List->Count = 0; - Information = (ULONG_PTR)ResourceList; - Status = STATUS_SUCCESS; ++ /* Delete the device object */ ++ IoDeleteDevice(DeviceObject); + } - break; ++ ++ return STATUS_SUCCESS; + } - case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */ ++ case IRP_MN_QUERY_DEVICE_RELATIONS: + { - Status = UsbhubPdoQueryDeviceText(DeviceObject, Irp, &Information); ++ /* only target relations are supported */ ++ if (Stack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) ++ { ++ /* not supported */ ++ Status = Irp->IoStatus.Status; ++ break; ++ } ++ ++ /* allocate device relations */ ++ DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS)); ++ if (!DeviceRelation) ++ { ++ /* no memory */ ++ Status = STATUS_INSUFFICIENT_RESOURCES; ++ break; ++ } ++ ++ /* init device relation */ ++ DeviceRelation->Count = 1; ++ DeviceRelation->Objects[0] = DeviceObject; ++ ObReferenceObject(DeviceRelation->Objects[0]); ++ ++ /* store result */ ++ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; ++ Status = STATUS_SUCCESS; + break; + } - case IRP_MN_QUERY_ID: /* 0x13 */ ++ case IRP_MN_QUERY_STOP_DEVICE: ++ case IRP_MN_QUERY_REMOVE_DEVICE: + { - Status = UsbhubPdoQueryId(DeviceObject, Irp, &Information); ++ /* Sure, no problem */ ++ Status = STATUS_SUCCESS; ++ Information = 0; + break; + } + default: + { - /* We can't forward request to the lower driver, because - * we are a Pdo, so we don't have lower driver... - */ - DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); ++ DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + diff --cc reactos/drivers/usb/usbhub/usbhub.c index 2a9e54b8894,00000000000,5e14a97d984..5e14a97d984 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbhub/usbhub.c +++ b/reactos/drivers/usb/usbhub/usbhub.c @@@@ -1,159 -1,0 -1,220 +1,220 @@@@ + /* - * ReactOS USB hub driver - * Copyright (C) 2004 Aleksey Bragin - * (C) 2005 Mark Tempel - * (C) 2005 Herv� Poussineau - * (C) 2010 Michael Martin - * - * 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. - * ++ * PROJECT: ReactOS Universal Serial Bus Hub Driver ++ * LICENSE: GPL - See COPYING in the top level directory ++ * FILE: drivers/usb/usbhub/fdo.c ++ * PURPOSE: UsbHub Driver ++ * PROGRAMMERS: ++ * Hervé Poussineau (hpoussin@reactos.org) ++ * Michael Martin (michael.martin@reactos.org) ++ * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + - /* INCLUDES *******************************************************************/ - //#define NDEBUG + #include "usbhub.h" + - /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ ++ NTSTATUS NTAPI ++ USBHUB_Create( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ DPRINT("USBHUB: IRP_MJ_CREATE\n"); ++ ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ Irp->IoStatus.Information = 0; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_SUCCESS; ++ } ++ ++ NTSTATUS NTAPI ++ USBHUB_Close( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ DPRINT("USBHUB: IRP_MJ_CLOSE\n"); ++ ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ Irp->IoStatus.Information = 0; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_SUCCESS; ++ } ++ ++ NTSTATUS NTAPI ++ USBHUB_Cleanup( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp) ++ { ++ DPRINT("USBHUB: IRP_MJ_CLEANUP\n"); ++ ++ Irp->IoStatus.Status = STATUS_SUCCESS; ++ Irp->IoStatus.Information = 0; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_SUCCESS; ++ } ++ + + NTSTATUS NTAPI - UsbhubAddDevice( ++ USBHUB_AddDevice( + IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo) ++ IN PDEVICE_OBJECT PhysicalDeviceObject) + { - PDEVICE_OBJECT Fdo; - PHUB_DEVICE_EXTENSION DeviceExtension; ++ PDEVICE_OBJECT DeviceObject; ++ PHUB_DEVICE_EXTENSION HubDeviceExtension; + NTSTATUS Status; - ++ DPRINT("USBHUB: AddDevice\n"); ++ // ++ // Create the Device Object ++ // + Status = IoCreateDevice(DriverObject, - sizeof(HUB_DEVICE_EXTENSION), - NULL, /* DeviceName */ - FILE_DEVICE_BUS_EXTENDER, - FILE_AUTOGENERATED_DEVICE_NAME, - FALSE, - &Fdo); ++ sizeof(HUB_DEVICE_EXTENSION), ++ NULL, ++ FILE_DEVICE_BUS_EXTENDER, ++ FILE_AUTOGENERATED_DEVICE_NAME, ++ FALSE, ++ &DeviceObject); + + if (!NT_SUCCESS(Status)) + { - DPRINT1("Usbhub: IoCreateDevice() failed with status 0x%08lx\n", Status); ++ DPRINT1("USBHUB: IoCreateDevice() failed with status 0x%08lx\n", Status); + return Status; + } + - // zerofill device extension - DeviceExtension = (PHUB_DEVICE_EXTENSION)Fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(HUB_DEVICE_EXTENSION)); - - DeviceExtension->IsFDO = TRUE; - Fdo->Flags |= DO_POWER_PAGABLE; ++ // ++ // Zero Hub Extension ++ // ++ HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ RtlZeroMemory(HubDeviceExtension, sizeof(HUB_DEVICE_EXTENSION)); ++ ++ // ++ // Set this to Fdo ++ // ++ HubDeviceExtension->Common.IsFDO = TRUE; ++ DeviceObject->Flags |= DO_POWER_PAGABLE; ++ ++ // ++ // initialize reset complete event ++ // ++ KeInitializeEvent(&HubDeviceExtension->ResetComplete, NotificationEvent, FALSE); ++ ++ // ++ // Attached to lower device ++ // + //Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); - DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo); ++ HubDeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); + if (!NT_SUCCESS(Status)) + { - DPRINT("Usbhub: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); - IoDeleteDevice(Fdo); ++ DPRINT1("USBHUB: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); ++ IoDeleteDevice(DeviceObject); + return Status; + } - Fdo->Flags |= DO_BUFFERED_IO; + - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; ++ DeviceObject->Flags |= DO_BUFFERED_IO; ++ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; + } + + static NTSTATUS NTAPI - IrpStub( ++ USBHUB_IrpStub( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) + { + NTSTATUS Status; + - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) ++ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + { + DPRINT1("Usbhub: FDO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + return ForwardIrpAndForget(DeviceObject, Irp); + } + else + { - /* We can't forward request to the lower driver, because - * we are a Pdo, so we don't have lower driver... - */ - DPRINT1("Usbhub: PDO stub for major function 0x%lx\n", ++ // ++ // Cant forward as we are the PDO! ++ // ++ DPRINT1("USBHUB: ERROR- PDO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + #ifndef NDEBUG + DbgBreakPoint(); + #endif + } + + Status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + - static NTSTATUS NTAPI - DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ ++ NTSTATUS NTAPI ++ USBHUB_DispatchDeviceControl( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - DPRINT1("Usbhub: DispatchDeviceControl\n"); - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbhubDeviceControlFdo(DeviceObject, Irp); ++ DPRINT("Usbhub: DispatchDeviceControl\n"); ++ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) ++ return USBHUB_FdoHandleDeviceControl(DeviceObject, Irp); + else - return IrpStub(DeviceObject, Irp); ++ return USBHUB_IrpStub(DeviceObject, Irp); + } + - static NTSTATUS NTAPI - DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS NTAPI ++ USBHUB_DispatchInternalDeviceControl( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - DPRINT1("Usbhub: DispatchInternalDeviceControl\n"); - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return IrpStub(DeviceObject, Irp); ++ DPRINT("Usbhub: DispatchInternalDeviceControl\n"); ++ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) ++ return USBHUB_IrpStub(DeviceObject, Irp); + else - return UsbhubInternalDeviceControlPdo(DeviceObject, Irp); ++ return USBHUB_PdoHandleInternalDeviceControl(DeviceObject, Irp); + } + - static NTSTATUS NTAPI - DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS NTAPI ++ USBHUB_DispatchPnp( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - DPRINT1("Usbhub: DispatchPnp\n"); - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbhubPnpFdo(DeviceObject, Irp); ++ DPRINT("USBHUB: DispatchPnp\n"); ++ if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) ++ return USBHUB_FdoHandlePnp(DeviceObject, Irp); + else - return UsbhubPnpPdo(DeviceObject, Irp); ++ return USBHUB_PdoHandlePnp(DeviceObject, Irp); + } + - /* - * Standard DriverEntry method. - */ + NTSTATUS NTAPI - DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath) ++ USBHUB_DispatchPower( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - ULONG i; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_NOT_SUPPORTED; ++ } + - DriverObject->DriverExtension->AddDevice = UsbhubAddDevice; - DPRINT1("Usbhub: DriverEntry\n"); ++ VOID ++ NTAPI ++ USBHUB_Unload( ++ IN PDRIVER_OBJECT DriverObject) ++ { ++ UNIMPLEMENTED ++ } + - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - DriverObject->MajorFunction[i] = IrpStub; + - DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbhubCreate; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbhubClose; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = UsbhubCleanup; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl; - DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; ++ NTSTATUS NTAPI ++ DriverEntry( ++ IN PDRIVER_OBJECT DriverObject, ++ IN PUNICODE_STRING RegistryPath) ++ { ++ DriverObject->DriverExtension->AddDevice = USBHUB_AddDevice; ++ DriverObject->DriverUnload = USBHUB_Unload; ++ ++ DPRINT("USBHUB: DriverEntry\n"); ++ ++ DriverObject->MajorFunction[IRP_MJ_CREATE] = USBHUB_Create; ++ DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBHUB_Close; ++ DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBHUB_Cleanup; ++ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBHUB_DispatchDeviceControl; ++ DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBHUB_DispatchInternalDeviceControl; ++ DriverObject->MajorFunction[IRP_MJ_PNP] = USBHUB_DispatchPnp; ++ DriverObject->MajorFunction[IRP_MJ_POWER] =USBHUB_DispatchPower; + + return STATUS_SUCCESS; + } + diff --cc reactos/drivers/usb/usbhub/usbhub.rbuild index c4c3bbd29a7,00000000000,8b9543c7ef3..8b9543c7ef3 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbhub/usbhub.rbuild +++ b/reactos/drivers/usb/usbhub/usbhub.rbuild @@@@ -1,13 -1,0 -1,16 +1,16 @@@@ + + + ++ ++ ++ include + ntoskrnl + hal + usbd - createclose.c ++ pseh + fdo.c + misc.c + pdo.c + usbhub.c + usbhub.rc + diff --cc reactos/drivers/usb/usbohci/CMakeLists.txt index 00000000000,53d605c7832,53d605c7832..53d605c7832 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/CMakeLists.txt +++ b/reactos/drivers/usb/usbohci/CMakeLists.txt diff --cc reactos/drivers/usb/usbohci/hardware.cpp index 00000000000,00000000000,87eb79f554f..87eb79f554f mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/hardware.cpp +++ b/reactos/drivers/usb/usbohci/hardware.cpp diff --cc reactos/drivers/usb/usbohci/hardware.h index 00000000000,e88c0941bbc,e88c0941bbc..e88c0941bbc mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/hardware.h +++ b/reactos/drivers/usb/usbohci/hardware.h diff --cc reactos/drivers/usb/usbohci/hcd_controller.cpp index 00000000000,00000000000,4e8019334ca..4e8019334ca mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/hcd_controller.cpp +++ b/reactos/drivers/usb/usbohci/hcd_controller.cpp diff --cc reactos/drivers/usb/usbohci/hub_controller.cpp index 00000000000,00000000000,1888564a7cd..1888564a7cd mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/hub_controller.cpp +++ b/reactos/drivers/usb/usbohci/hub_controller.cpp diff --cc reactos/drivers/usb/usbohci/interfaces.h index 00000000000,c8b50ffc54f,c8b50ffc54f..c8b50ffc54f mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/interfaces.h +++ b/reactos/drivers/usb/usbohci/interfaces.h diff --cc reactos/drivers/usb/usbohci/memory_manager.cpp index 00000000000,0f2885ab05a,0f2885ab05a..0f2885ab05a mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/memory_manager.cpp +++ b/reactos/drivers/usb/usbohci/memory_manager.cpp diff --cc reactos/drivers/usb/usbohci/misc.cpp index 00000000000,d4380da3eca,d4380da3eca..d4380da3eca mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/misc.cpp +++ b/reactos/drivers/usb/usbohci/misc.cpp diff --cc reactos/drivers/usb/usbohci/purecall.cpp index 00000000000,75bc6f8e819,75bc6f8e819..75bc6f8e819 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/purecall.cpp +++ b/reactos/drivers/usb/usbohci/purecall.cpp diff --cc reactos/drivers/usb/usbohci/usb_device.cpp index 00000000000,00000000000,09482f9ca09..09482f9ca09 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/usb_device.cpp +++ b/reactos/drivers/usb/usbohci/usb_device.cpp diff --cc reactos/drivers/usb/usbohci/usb_queue.cpp index 00000000000,00000000000,2132bec89ca..2132bec89ca mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/usb_queue.cpp +++ b/reactos/drivers/usb/usbohci/usb_queue.cpp diff --cc reactos/drivers/usb/usbohci/usb_request.cpp index 00000000000,00000000000,b667554068f..b667554068f mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/usb_request.cpp +++ b/reactos/drivers/usb/usbohci/usb_request.cpp diff --cc reactos/drivers/usb/usbohci/usbohci.cpp index 00000000000,00000000000,caf3067974b..caf3067974b mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/usbohci.cpp +++ b/reactos/drivers/usb/usbohci/usbohci.cpp diff --cc reactos/drivers/usb/usbohci/usbohci.h index 00000000000,6eab4ba6045,6eab4ba6045..6eab4ba6045 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/usbohci.h +++ b/reactos/drivers/usb/usbohci/usbohci.h diff --cc reactos/drivers/usb/usbohci/usbohci.rbuild index 00000000000,00000000000,1b96cc7fece..1b96cc7fece mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbohci/usbohci.rbuild +++ b/reactos/drivers/usb/usbohci/usbohci.rbuild diff --cc reactos/drivers/usb/usbohci/usbohci.rc index 00000000000,000ffdee9f9,000ffdee9f9..000ffdee9f9 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbohci/usbohci.rc +++ b/reactos/drivers/usb/usbohci/usbohci.rc diff --cc reactos/drivers/usb/usbstor/descriptor.c index 00000000000,28b7ead3332,28b7ead3332..28b7ead3332 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbstor/descriptor.c +++ b/reactos/drivers/usb/usbstor/descriptor.c diff --cc reactos/drivers/usb/usbstor/disk.c index 00000000000,00000000000,8a11d828258..8a11d828258 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/disk.c +++ b/reactos/drivers/usb/usbstor/disk.c diff --cc reactos/drivers/usb/usbstor/error.c index 00000000000,00000000000,23d7f88c671..23d7f88c671 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/error.c +++ b/reactos/drivers/usb/usbstor/error.c diff --cc reactos/drivers/usb/usbstor/fdo.c index 00000000000,00000000000,56ad612ad41..56ad612ad41 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/fdo.c +++ b/reactos/drivers/usb/usbstor/fdo.c diff --cc reactos/drivers/usb/usbstor/misc.c index 00000000000,00000000000,4c49e7587fa..4c49e7587fa mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/misc.c +++ b/reactos/drivers/usb/usbstor/misc.c diff --cc reactos/drivers/usb/usbstor/pdo.c index 00000000000,00000000000,2c42744f208..2c42744f208 mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/pdo.c +++ b/reactos/drivers/usb/usbstor/pdo.c diff --cc reactos/drivers/usb/usbstor/queue.c index 00000000000,cda2d28d2e3,cda2d28d2e3..cda2d28d2e3 mode 000000,100644,100644..100644 --- a/reactos/drivers/usb/usbstor/queue.c +++ b/reactos/drivers/usb/usbstor/queue.c diff --cc reactos/drivers/usb/usbstor/scsi.c index 00000000000,00000000000,b335309840a..b335309840a mode 000000,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/scsi.c +++ b/reactos/drivers/usb/usbstor/scsi.c diff --cc reactos/drivers/usb/usbstor/usbstor.c index ef8cd7e307e,00000000000,50fb0bf2670..50fb0bf2670 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/usbstor.c +++ b/reactos/drivers/usb/usbstor/usbstor.c @@@@ -1,138 -1,0 -1,278 +1,278 @@@@ + /* + * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbstor/usbstor.c + * PURPOSE: USB block storage device driver. + * PROGRAMMERS: + * James Tabor ++ Johannes Anderwald + */ + + /* INCLUDES ******************************************************************/ + + #define NDEBUG + #define INITGUID + #include "usbstor.h" + + /* PUBLIC AND PRIVATE FUNCTIONS **********************************************/ + - NTSTATUS NTAPI - IrpStub(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_AddDevice( ++ IN PDRIVER_OBJECT DriverObject, ++ IN PDEVICE_OBJECT PhysicalDeviceObject) + { - NTSTATUS Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } ++ NTSTATUS Status; ++ PDEVICE_OBJECT DeviceObject; ++ PFDO_DEVICE_EXTENSION DeviceExtension; + - NTSTATUS NTAPI - AddDevice(IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT pdo) - { - return STATUS_SUCCESS; - } ++ // ++ // lets create the device ++ // ++ Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), 0, FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject); + - VOID NTAPI - DriverUnload(PDRIVER_OBJECT DriverObject) - { ++ // ++ // check for success ++ // ++ if (!NT_SUCCESS(Status)) ++ { ++ DPRINT1("USBSTOR_AddDevice: Failed to create FDO Status %x\n", Status); ++ return Status; ++ } ++ ++ // ++ // get device extension ++ // ++ DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ASSERT(DeviceExtension); ++ ++ // ++ // zero device extension ++ // ++ RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION)); ++ ++ // ++ // initialize device extension ++ // ++ DeviceExtension->Common.IsFDO = TRUE; ++ DeviceExtension->FunctionalDeviceObject = DeviceObject; ++ DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; ++ DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); ++ ++ // ++ // did attaching fail ++ // ++ if (!DeviceExtension->LowerDeviceObject) ++ { ++ // ++ // device removed ++ // ++ IoDeleteDevice(DeviceObject); ++ ++ return STATUS_DEVICE_REMOVED; ++ } ++ ++ // ++ // set device flags ++ // ++ DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; ++ ++ // ++ // device is initialized ++ // ++ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; ++ ++ ++ // ++ // done ++ // ++ return STATUS_SUCCESS; + } + - VOID NTAPI - StartIo(PUSBSTOR_DEVICE_EXTENSION DeviceExtension, - PIRP Irp) ++ VOID ++ NTAPI ++ USBSTOR_Unload( ++ PDRIVER_OBJECT DriverObject) + { ++ // ++ // no-op ++ // + } + - static NTSTATUS NTAPI - DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchClose( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { ++ // ++ // function always succeeds ;) ++ // ++ DPRINT("USBSTOR_DispatchClose\n"); + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + - static NTSTATUS NTAPI - DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp) - { - return STATUS_SUCCESS; - } + - static NTSTATUS NTAPI - DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchDeviceControl( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - return STATUS_SUCCESS; - } ++ NTSTATUS Status; + ++ // ++ // handle requests ++ // ++ Status = USBSTOR_HandleDeviceControl(DeviceObject, Irp); + - static NTSTATUS NTAPI - DispatchScsi(PDEVICE_OBJECT DeviceObject, PIRP Irp) - { - return STATUS_SUCCESS; ++ // ++ // complete request ++ // ++ Irp->IoStatus.Status = Status; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ ++ // ++ // done ++ // ++ return Status; + } + - static NTSTATUS NTAPI - DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchScsi( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - return STATUS_SUCCESS; ++ // ++ // handle requests ++ // ++ return USBSTOR_HandleInternalDeviceControl(DeviceObject, Irp); + } + - static NTSTATUS NTAPI - DispatchSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchReadWrite( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - return STATUS_SUCCESS; ++ // ++ // read write ioctl is not supported ++ // ++ Irp->IoStatus.Information = 0; ++ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ++ IoCompleteRequest(Irp, IO_NO_INCREMENT); ++ return STATUS_INVALID_PARAMETER; + } + - static NTSTATUS NTAPI - DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchPnp( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - return STATUS_SUCCESS; ++ PUSBSTOR_COMMON_DEVICE_EXTENSION DeviceExtension; ++ ++ // ++ // get common device extension ++ // ++ DeviceExtension = (PUSBSTOR_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ++ ++ // ++ // is it for the FDO ++ // ++ if (DeviceExtension->IsFDO) ++ { ++ // ++ // dispatch pnp request to fdo pnp handler ++ // ++ return USBSTOR_FdoHandlePnp(DeviceObject, Irp); ++ } ++ else ++ { ++ // ++ // dispatch request to pdo pnp handler ++ // ++ return USBSTOR_PdoHandlePnp(DeviceObject, Irp); ++ } + } + - static NTSTATUS NTAPI - DispatchPower(PDEVICE_OBJECT fido, PIRP Irp) ++ NTSTATUS ++ NTAPI ++ USBSTOR_DispatchPower( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp) + { - DPRINT1("USBSTOR: IRP_MJ_POWER unimplemented\n"); ++ UNIMPLEMENTED ++ + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + + - /* - * Standard DriverEntry method. - */ - NTSTATUS NTAPI - DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath) ++ NTSTATUS ++ NTAPI ++ DriverEntry( ++ IN PDRIVER_OBJECT DriverObject, ++ IN PUNICODE_STRING RegPath) + { - ULONG i; + + DPRINT("********* USB Storage *********\n"); + - DriverObject->DriverUnload = DriverUnload; - DriverObject->DriverExtension->AddDevice = AddDevice; ++ // ++ // driver unload routine ++ // ++ DriverObject->DriverUnload = USBSTOR_Unload; ++ ++ // ++ // add device function ++ // ++ DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice; ++ ++ // ++ // driver start i/o routine ++ // ++ DriverObject->DriverStartIo = USBSTOR_StartIo; ++ ++ // ++ // create / close ++ // ++ DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_DispatchClose; ++ DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_DispatchClose; + - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - DriverObject->MajorFunction[i] = IrpStub; ++ // ++ // scsi pass through requests ++ // ++ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DispatchDeviceControl; + - DriverObject->DriverStartIo = (PVOID)StartIo; ++ // ++ // irp dispatch read / write ++ // ++ DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_DispatchReadWrite; ++ DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_DispatchReadWrite; + - DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchClose; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; - DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite; - DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWrite; ++ // ++ // scsi queue ioctl ++ // ++ DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_DispatchScsi; + - /* Scsi Miniport support */ - DriverObject->MajorFunction[IRP_MJ_SCSI] = DispatchScsi; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchSystemControl; ++ // ++ // pnp processing ++ // ++ DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_DispatchPnp; + - DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; - DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; ++ // ++ // power processing ++ // ++ DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_DispatchPower; + + return STATUS_SUCCESS; + } + diff --cc reactos/drivers/usb/usbstor/usbstor.h index 9793db758b9,00000000000,dbc8ef51ae7..dbc8ef51ae7 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/usbstor.h +++ b/reactos/drivers/usb/usbstor/usbstor.h @@@@ -1,83 -1,0 -1,460 +1,460 @@@@ ++ ++ #pragma once ++ + #include ++ #define NDEBUG ++ #include + #include ++ #include ++ #include ++ #include + #include - #include - #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include + + #define USB_STOR_TAG 'sbsu' + #define USB_MAXCHILDREN (16) + - NTSTATUS NTAPI - IoAttachDeviceToDeviceStackSafe( - IN PDEVICE_OBJECT SourceDevice, - IN PDEVICE_OBJECT TargetDevice, - OUT PDEVICE_OBJECT *AttachedToDeviceObject); + - typedef struct _USBSTOR_DEVICE_EXTENSION ++ ++ #define HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8)) ++ #define NTOHS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8)) ++ ++ #define HTONL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \ ++ ((((unsigned long)(n) & 0xFF00)) << 8) | \ ++ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \ ++ ((((unsigned long)(n) & 0xFF000000)) >> 24)) ++ ++ ++ #define NTOHL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \ ++ ((((unsigned long)(n) & 0xFF00)) << 8) | \ ++ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \ ++ ((((unsigned long)(n) & 0xFF000000)) >> 24)) ++ ++ #define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \ ++ | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH) ++ ++ typedef struct __COMMON_DEVICE_EXTENSION__ ++ { ++ BOOLEAN IsFDO; ++ ++ }USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION; ++ ++ typedef struct ++ { ++ USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension ++ ++ PDEVICE_OBJECT FunctionalDeviceObject; // functional device object ++ PDEVICE_OBJECT PhysicalDeviceObject; // physical device object ++ PDEVICE_OBJECT LowerDeviceObject; // lower device object ++ USB_BUS_INTERFACE_USBDI_V2 BusInterface; // bus interface of device ++ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor ++ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor ++ PUSB_STRING_DESCRIPTOR SerialNumber; // usb serial number ++ PUSBD_INTERFACE_INFORMATION InterfaceInformation; // usb interface information ++ USBD_CONFIGURATION_HANDLE ConfigurationHandle; // usb configuration handle ++ UCHAR BulkInPipeIndex; // bulk in pipe index ++ UCHAR BulkOutPipeIndex; // bulk out pipe index ++ UCHAR MaxLUN; // max lun for device ++ PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices ++ KSPIN_LOCK IrpListLock; // irp list lock ++ LIST_ENTRY IrpListHead; // irp list head ++ BOOLEAN IrpListFreeze; // if true the irp list is freezed ++ BOOLEAN ResetInProgress; // if hard reset is in progress ++ ULONG IrpPendingCount; // count of irp pending ++ PSCSI_REQUEST_BLOCK ActiveSrb; // stores the current active SRB ++ KEVENT NoPendingRequests; // set if no pending or in progress requests ++ }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; ++ ++ typedef struct ++ { ++ USBSTOR_COMMON_DEVICE_EXTENSION Common; ++ PDEVICE_OBJECT LowerDeviceObject; // points to FDO ++ UCHAR LUN; // lun id ++ PVOID InquiryData; // USB SCSI inquiry data ++ UCHAR Claimed; // indicating if it has been claimed by upper driver ++ ULONG BlockLength; // length of block ++ ULONG LastLogicBlockAddress; // last block address ++ PDEVICE_OBJECT *PDODeviceObject; // entry in pdo list ++ }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; ++ ++ // ++ // max lun command identifier ++ // ++ #define USB_BULK_GET_MAX_LUN 0xFE ++ #define USB_BULK_RESET_DEVICE 0xFF ++ ++ #include ++ typedef struct ++ { ++ ULONG Signature; // CBW signature ++ ULONG Tag; // CBW Tag of operation ++ ULONG DataTransferLength; // data transfer length ++ UCHAR Flags; // CBW Flags endpoint direction ++ UCHAR LUN; // lun unit ++ UCHAR CommandBlockLength; // Command block length ++ UCHAR CommandBlock[16]; ++ }CBW, *PCBW; ++ ++ C_ASSERT(sizeof(CBW) == 31); ++ ++ ++ #define CBW_SIGNATURE 0x43425355 ++ #define CSW_SIGNATURE 0x53425355 ++ ++ #define MAX_LUN 0xF ++ ++ typedef struct ++ { ++ ULONG Signature; // CSW signature ++ ULONG Tag; // CSW tag ++ ULONG DataResidue; // CSW data transfer diff ++ UCHAR Status; // CSW status ++ }CSW, *PCSW; ++ ++ //-------------------------------------------------------------------------------------------------------------------------------------------- ++ // ++ // UFI INQUIRY command ++ // ++ typedef struct ++ { ++ UCHAR Code; // operation code 0x12 ++ UCHAR LUN; // lun address ++ UCHAR PageCode; // product data information, always 0x00 ++ UCHAR Reserved; // reserved 0x00 ++ UCHAR AllocationLength; // length of inquiry data to be returned, default 36 bytes ++ UCHAR Reserved1[7]; //reserved bytes 0x00 ++ }UFI_INQUIRY_CMD, *PUFI_INQUIRY_CMD; ++ ++ C_ASSERT(sizeof(UFI_INQUIRY_CMD) == 12); ++ ++ #define UFI_INQUIRY_CMD_LEN 0x6 ++ ++ // ++ // UFI INQUIRY command response ++ // ++ typedef struct ++ { ++ UCHAR DeviceType; // device type ++ UCHAR RMB; // removable media bit ++ UCHAR Version; // contains version 0x00 ++ UCHAR Format; // response format ++ UCHAR Length; // additional length ++ UCHAR Reserved[3]; // reserved ++ UCHAR Vendor[8]; // vendor identification string ++ UCHAR Product[16]; // product identification string ++ UCHAR Revision[4]; // product revision code ++ }UFI_INQUIRY_RESPONSE, *PUFI_INQUIRY_RESPONSE; ++ ++ C_ASSERT(sizeof(UFI_INQUIRY_RESPONSE) == 36); ++ ++ //-------------------------------------------------------------------------------------------------------------------------------------------- ++ // ++ // UFI read cmd ++ // ++ typedef struct ++ { ++ UCHAR Code; // operation code ++ UCHAR LUN; // lun ++ UCHAR LogicalBlockByte0; // lba byte 0 ++ UCHAR LogicalBlockByte1; // lba byte 1 ++ UCHAR LogicalBlockByte2; // lba byte 2 ++ UCHAR LogicalBlockByte3; // lba byte 3 ++ UCHAR Reserved; // reserved 0x00 ++ UCHAR ContiguousLogicBlocksByte0; // msb contigious logic blocks byte ++ UCHAR ContiguousLogicBlocksByte1; // msb contigious logic blocks ++ UCHAR Reserved1[3]; // reserved 0x00 ++ }UFI_READ_WRITE_CMD; ++ ++ C_ASSERT(sizeof(UFI_READ_WRITE_CMD) == 12); ++ ++ #define UFI_READ_WRITE_CMD_LEN (0xA) ++ ++ //-------------------------------------------------------------------------------------------------------------------------------------------- ++ // ++ // UFI read capacity cmd ++ // ++ typedef struct ++ { ++ UCHAR Code; // operation code 0x25 ++ UCHAR LUN; // lun address ++ UCHAR LBA[4]; // logical block address, should be zero ++ UCHAR Reserved1[2]; // reserved 0x00 ++ UCHAR PMI; // PMI = 0x00 ++ UCHAR Reserved2[3]; // reserved 0x00 ++ }UFI_CAPACITY_CMD, *PUFI_CAPACITY_CMD; ++ ++ C_ASSERT(sizeof(UFI_CAPACITY_CMD) == 12); ++ ++ #define UFI_CAPACITY_CMD_LEN 0xA //FIXME support length 16 too if requested ++ ++ // ++ // UFI Read Capcacity command response ++ // ++ typedef struct ++ { ++ ULONG LastLogicalBlockAddress; // last logical block address ++ ULONG BlockLength; // block length in bytes ++ }UFI_CAPACITY_RESPONSE, *PUFI_CAPACITY_RESPONSE; ++ ++ #define UFI_READ_CAPACITY_CMD_LEN 0xA ++ C_ASSERT(sizeof(UFI_CAPACITY_RESPONSE) == 8); ++ ++ //-------------------------------------------------------------------------------------------------------------------------------------------- ++ // ++ // UFI sense mode cmd ++ // ++ typedef struct ++ { ++ UCHAR Code; // operation code ++ UCHAR LUN; // lun address ++ UCHAR PageCode:6; // page code selector ++ UCHAR PC:2; // type of parameters to be returned ++ UCHAR Reserved[4]; // reserved 0x00 ++ USHORT AllocationLength; // parameters length ++ UCHAR Reserved1[3]; ++ }UFI_SENSE_CMD, *PUFI_SENSE_CMD; ++ ++ C_ASSERT(sizeof(UFI_SENSE_CMD) == 12); ++ ++ #define UFI_SENSE_CMD_LEN (6) ++ ++ typedef struct ++ { ++ USHORT ModeDataLength; // length of parameters for sense cmd ++ UCHAR MediumTypeCode; // 00 for mass storage, 0x94 for floppy ++ UCHAR WP:1; // write protect bit ++ UCHAR Reserved1:2; // reserved 00 ++ UCHAR DPOFUA:1; // should be zero ++ UCHAR Reserved2:4; // reserved ++ UCHAR Reserved[4]; // reserved ++ }UFI_MODE_PARAMETER_HEADER, *PUFI_MODE_PARAMETER_HEADER; ++ ++ ++ C_ASSERT(sizeof(UFI_MODE_PARAMETER_HEADER) == 8); ++ ++ typedef struct ++ { ++ UCHAR PC; ++ UCHAR PageLength; ++ UCHAR Reserved1; ++ UCHAR ITM; ++ UCHAR Flags; ++ UCHAR Reserved[3]; ++ }UFI_TIMER_PROTECT_PAGE, *PUFI_TIMER_PROTECT_PAGE; ++ C_ASSERT(sizeof(UFI_TIMER_PROTECT_PAGE) == 8); ++ ++ //-------------------------------------------------------------------------------------------------------------------------------------------- ++ // ++ // UFI test unit command ++ // ++ ++ typedef struct + { - BOOLEAN IsFDO; - struct usb_device* dev; - PDEVICE_OBJECT LowerDevice; ++ UCHAR Code; // operation code 0x00 ++ UCHAR LUN; // lun ++ UCHAR Reserved[10]; // reserved 0x00 ++ }UFI_TEST_UNIT_CMD, *PUFI_TEST_UNIT_CMD; ++ ++ C_ASSERT(sizeof(UFI_TEST_UNIT_CMD) == 12); ++ ++ #define UFI_TEST_UNIT_CMD_LEN (6) ++ ++ typedef struct ++ { ++ union ++ { ++ PCBW cbw; ++ PCSW csw; ++ }; ++ URB Urb; ++ PIRP Irp; ++ ULONG TransferDataLength; ++ PUCHAR TransferData; ++ PFDO_DEVICE_EXTENSION FDODeviceExtension; ++ PPDO_DEVICE_EXTENSION PDODeviceExtension; ++ PMDL TransferBufferMDL; ++ PKEVENT Event; ++ }IRP_CONTEXT, *PIRP_CONTEXT; ++ ++ typedef struct _ERRORHANDLER_WORKITEM_DATA ++ { ++ PDEVICE_OBJECT DeviceObject; ++ PIRP_CONTEXT Context; ++ WORK_QUEUE_ITEM WorkQueueItem; ++ } ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA; ++ ++ ++ //--------------------------------------------------------------------- ++ // ++ // fdo.c routines ++ // ++ NTSTATUS ++ USBSTOR_FdoHandlePnp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN OUT PIRP Irp); ++ ++ //--------------------------------------------------------------------- ++ // ++ // pdo.c routines ++ // ++ NTSTATUS ++ USBSTOR_PdoHandlePnp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN OUT PIRP Irp); ++ ++ NTSTATUS ++ USBSTOR_CreatePDO( ++ IN PDEVICE_OBJECT DeviceObject, ++ OUT PDEVICE_OBJECT *ChildDeviceObject); + - PDEVICE_OBJECT Children[USB_MAXCHILDREN]; ++ //--------------------------------------------------------------------- ++ // ++ // misc.c routines ++ // ++ NTSTATUS ++ NTAPI ++ USBSTOR_SyncForwardIrp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN OUT PIRP Irp); ++ ++ NTSTATUS ++ NTAPI ++ USBSTOR_GetBusInterface( ++ IN PDEVICE_OBJECT DeviceObject, ++ OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface); ++ ++ PVOID ++ AllocateItem( ++ IN POOL_TYPE PoolType, ++ IN ULONG ItemSize); ++ ++ VOID ++ FreeItem( ++ IN PVOID Item); ++ ++ NTSTATUS ++ USBSTOR_SyncUrbRequest( ++ IN PDEVICE_OBJECT DeviceObject, ++ OUT PURB UrbRequest); + - /* Fields valid only when IsFDO == FALSE */ - UNICODE_STRING DeviceDescription; // REG_SZ - UNICODE_STRING DeviceId; // REG_SZ - UNICODE_STRING InstanceId; // REG_SZ - UNICODE_STRING HardwareIds; // REG_MULTI_SZ - UNICODE_STRING CompatibleIds; // REG_MULTI_SZ - UNICODE_STRING SymbolicLinkName; - } USBSTOR_DEVICE_EXTENSION, *PUSBSTOR_DEVICE_EXTENSION; ++ NTSTATUS ++ USBSTOR_GetMaxLUN( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PFDO_DEVICE_EXTENSION DeviceExtension); + ++ NTSTATUS ++ NTAPI ++ USBSTOR_SyncForwardIrpCompletionRoutine( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp, ++ PVOID Context); + - /* cleanup.c */ - NTSTATUS NTAPI - UsbStorCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ NTSTATUS ++ USBSTOR_ResetDevice( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PFDO_DEVICE_EXTENSION DeviceExtension); + - /* fdo.c */ - NTSTATUS NTAPI - UsbStorPnpFdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ //--------------------------------------------------------------------- ++ // ++ // descriptor.c routines ++ // + + NTSTATUS - UsbStorDeviceControlFdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ USBSTOR_GetDescriptors( ++ IN PDEVICE_OBJECT DeviceObject); + - /* misc.c */ + NTSTATUS - ForwardIrpAndWait( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ USBSTOR_SelectConfigurationAndInterface( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PFDO_DEVICE_EXTENSION DeviceExtension); + - NTSTATUS NTAPI - ForwardIrpAndForget( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ NTSTATUS ++ USBSTOR_GetPipeHandles( ++ IN PFDO_DEVICE_EXTENSION DeviceExtension); + ++ //--------------------------------------------------------------------- ++ // ++ // scsi.c routines ++ // + NTSTATUS - UsbStorDuplicateUnicodeString( - OUT PUNICODE_STRING Destination, - IN PUNICODE_STRING Source, - IN POOL_TYPE PoolType); ++ USBSTOR_HandleExecuteSCSI( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); + + NTSTATUS - UsbStorInitMultiSzString( - OUT PUNICODE_STRING Destination, - ... /* list of PCSZ */); ++ USBSTOR_SendInquiryCmd( ++ IN PDEVICE_OBJECT DeviceObject); ++ ++ //--------------------------------------------------------------------- ++ // ++ // disk.c routines ++ // ++ NTSTATUS ++ USBSTOR_HandleInternalDeviceControl( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); ++ ++ NTSTATUS ++ USBSTOR_HandleDeviceControl( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); ++ ++ //--------------------------------------------------------------------- ++ // ++ // queue.c routines ++ // ++ VOID ++ NTAPI ++ USBSTOR_StartIo( ++ PDEVICE_OBJECT DeviceObject, ++ PIRP Irp); ++ ++ VOID ++ USBSTOR_QueueWaitForPendingRequests( ++ IN PDEVICE_OBJECT DeviceObject); ++ ++ VOID ++ USBSTOR_QueueRelease( ++ IN PDEVICE_OBJECT DeviceObject); ++ ++ BOOLEAN ++ USBSTOR_QueueAddIrp( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); ++ ++ VOID ++ NTAPI ++ USBSTOR_CancelIo( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); ++ ++ VOID ++ USBSTOR_QueueInitialize( ++ PFDO_DEVICE_EXTENSION FDODeviceExtension); ++ ++ VOID ++ NTAPI ++ ErrorHandlerWorkItemRoutine( ++ PVOID Context); ++ ++ VOID ++ USBSTOR_QueueNextRequest( ++ IN PDEVICE_OBJECT DeviceObject); + - /* pdo.c */ - NTSTATUS NTAPI - UsbStorPnpPdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ VOID ++ USBSTOR_QueueTerminateRequest( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN PIRP Irp); + ++ /* error.c */ + NTSTATUS - UsbStorDeviceControlPdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); ++ USBSTOR_GetEndpointStatus( ++ IN PDEVICE_OBJECT DeviceObject, ++ IN UCHAR bEndpointAddress, ++ OUT PUSHORT Value); + diff --cc reactos/drivers/usb/usbstor/usbstor.rbuild index d7215fc8e92,00000000000,ac4f9e62f68..ac4f9e62f68 mode 100644,000000,100644..100644 --- a/reactos/drivers/usb/usbstor/usbstor.rbuild +++ b/reactos/drivers/usb/usbstor/usbstor.rbuild @@@@ -1,10 -1,0 -1,20 +1,20 @@@@ + + + ++ + + include + ntoskrnl + hal ++ usbd ++ descriptor.c ++ disk.c ++ fdo.c ++ misc.c ++ pdo.c ++ queue.c ++ error.c ++ scsi.c + usbstor.c + usbstor.rc + diff --cc reactos/include/ddk/hidclass.h index 69975003693,00000000000,cdcc3eaa31a..cdcc3eaa31a mode 100644,000000,100644..100644 --- a/reactos/include/ddk/hidclass.h +++ b/reactos/include/ddk/hidclass.h @@@@ -1,167 -1,0 -1,160 +1,160 @@@@ + /* + * hidclass.h + * + * HID class driver interface + * + * This file is part of the w32api package. + * + * Contributors: + * Created by Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + #ifndef __HIDCLASS_H + #define __HIDCLASS_H + + #include "hidpi.h" + + #ifdef __cplusplus + extern "C" { + #endif + + #define HID_REVISION 0x00000001 + + DEFINE_GUID (GUID_DEVINTERFACE_HID, \ + 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30); + DEFINE_GUID (GUID_HID_INTERFACE_NOTIFY, \ + 0x2c4e2e88L, 0x25e6, 0x4c33, 0x88, 0x2f, 0x3d, 0x82, 0xe6, 0x07, 0x36, 0x81); + DEFINE_GUID (GUID_HID_INTERFACE_HIDPARSE, \ + 0xf5c315a5, 0x69ac, 0x4bc2, 0x92, 0x79, 0xd0, 0xb6, 0x45, 0x76, 0xf4, 0x4b); + + #define GUID_CLASS_INPUT GUID_DEVINTERFACE_HID + + #define GUID_CLASS_INPUT_STR "4D1E55B2-F16F-11CF-88CB-001111000030" + + + #define HID_CTL_CODE(id) \ + CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS) + #define HID_BUFFER_CTL_CODE(id) \ + CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) + #define HID_IN_CTL_CODE(id) \ + CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) + #define HID_OUT_CTL_CODE(id) \ + CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + + + #define IOCTL_GET_PHYSICAL_DESCRIPTOR HID_OUT_CTL_CODE(102) + #define IOCTL_HID_FLUSH_QUEUE HID_CTL_CODE(101) + #define IOCTL_HID_GET_COLLECTION_DESCRIPTOR HID_CTL_CODE(100) + #define IOCTL_HID_GET_COLLECTION_INFORMATION HID_BUFFER_CTL_CODE(106) + #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) + #define IOCTL_HID_GET_HARDWARE_ID HID_OUT_CTL_CODE(103) + #define IOCTL_HID_GET_INDEXED_STRING HID_OUT_CTL_CODE(120) + #define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) + #define IOCTL_HID_GET_MANUFACTURER_STRING HID_OUT_CTL_CODE(110) + #define IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS HID_BUFFER_CTL_CODE(104) + #define IOCTL_HID_GET_POLL_FREQUENCY_MSEC HID_BUFFER_CTL_CODE(102) + #define IOCTL_HID_GET_PRODUCT_STRING HID_OUT_CTL_CODE(111) + #define IOCTL_HID_GET_SERIALNUMBER_STRING HID_OUT_CTL_CODE(112) + #define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100) + #define IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS HID_BUFFER_CTL_CODE(105) + #define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101) + #define IOCTL_HID_SET_POLL_FREQUENCY_MSEC HID_BUFFER_CTL_CODE(103) + + #define IOCTL_HID_GET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(100) + #define IOCTL_HID_SET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(101) ++ #define IOCTL_HID_GET_INDEXED_STRING HID_OUT_CTL_CODE(120) + #define IOCTL_HID_GET_MS_GENRE_DESCRIPTOR HID_OUT_CTL_CODE(121) + - /* FIXME: these values are wrong! */ - #define IOCTL_HID_GET_STRING 0 - #define IOCTL_HID_GET_DEVICE_ATTRIBUTES 1 - #define IOCTL_HID_GET_DEVICE_DESCRIPTOR 2 - #define IOCTL_HID_READ_REPORT 3 - #define IOCTL_HID_WRITE_REPORT 4 - #define IOCTL_HID_GET_REPORT_DESCRIPTOR 5 - + typedef enum _HID_STRING_TYPE + { + HID_STRING_INDEXED = 0, + HID_STRING_ID_IMANUFACTURER, + HID_STRING_ID_IPRODUCT, + HID_STRING_ID_ISERIALNUMBER, + HID_STRING_MAX + } HID_STRING_TYPE; + + enum DeviceObjectState { + DeviceObjectStarted = 0, + DeviceObjectStopped, + DeviceObjectRemoved + }; + + typedef VOID + (NTAPI *PHID_STATUS_CHANGE)( + _In_ PVOID Context, + _In_ enum DeviceObjectState State); + + _Must_inspect_result_ + typedef NTSTATUS + (NTAPI *PHIDP_GETCAPS)( + _In_ PHIDP_PREPARSED_DATA PreparsedData, + _Out_ PHIDP_CAPS Capabilities); + + typedef struct _HID_COLLECTION_INFORMATION { + ULONG DescriptorSize; + BOOLEAN Polled; + UCHAR Reserved1[1]; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HID_COLLECTION_INFORMATION, *PHID_COLLECTION_INFORMATION; + + typedef struct _HID_DRIVER_CONFIG { + ULONG Size; + ULONG RingBufferSize; + } HID_DRIVER_CONFIG, *PHID_DRIVER_CONFIG; + + typedef struct _HID_INTERFACE_HIDPARSE { + #ifdef __cplusplus + INTERFACE i; + #else + /* GCC doesn't support including unnamed structs, so INTERFACE is + expanded here */ + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + #endif + PHIDP_GETCAPS HidpGetCaps; + } HID_INTERFACE_HIDPARSE, *PHID_INTERFACE_HIDPARSE; + + typedef struct _HID_INTERFACE_NOTIFY_PNP { + #ifdef __cplusplus + INTERFACE i; + #else + /* GCC doesn't support including unnamed structs, so INTERFACE is + expanded here */ + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + #endif + PHID_STATUS_CHANGE StatusChangeFn; + PVOID CallbackContext; + } HID_INTERFACE_NOTIFY_PNP, *PHID_INTERFACE_NOTIFY_PNP; + + typedef struct _HID_XFER_PACKET { + PUCHAR reportBuffer; + ULONG reportBufferLen; + UCHAR reportId; + } HID_XFER_PACKET, *PHID_XFER_PACKET; + + #ifdef __cplusplus + } + #endif + + #endif /* __HIDCLASS_H */ diff --cc reactos/include/ddk/hidpddi.h index 00000000000,3f142308530,3f142308530..3f142308530 mode 000000,100644,100644..100644 --- a/reactos/include/ddk/hidpddi.h +++ b/reactos/include/ddk/hidpddi.h diff --cc reactos/include/ddk/hidport.h index 00000000000,e6819e9b52d,e6819e9b52d..e6819e9b52d mode 000000,100644,100644..100644 --- a/reactos/include/ddk/hidport.h +++ b/reactos/include/ddk/hidport.h diff --cc reactos/include/ddk/ntddk.h index 74d2987aa78,00000000000,b648308c084..b648308c084 mode 100644,000000,100644..100644 --- a/reactos/include/ddk/ntddk.h +++ b/reactos/include/ddk/ntddk.h @@@@ -1,5968 -1,0 -1,5971 +1,5971 @@@@ + /* + * ntddk.h + * + * Windows NT Device Driver Kit + * + * This file is part of the ReactOS DDK package. + * + * Contributors: + * Amine Khaldi + * Timo Kreuzer (timo.kreuzer@reactos.org) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + #pragma once + + #define _NTDDK_ + + #if !defined(_NTHAL_) && !defined(_NTIFS_) + #define _NTDDK_INCLUDED_ + #define _DDK_DRIVER_ + #endif + + /* Dependencies */ + + #define NT_INCLUDED + #define _CTYPE_DISABLE_MACROS + + #include + #include + #include + #include + #include + #include + #include + + #include // FIXME + #include // FIXME + + + #ifdef __cplusplus + extern "C" { + #endif + + /* GUID and UUID */ + #ifndef _NTLSA_IFS_ + #ifndef _NTLSA_AUDIT_ + #define _NTLSA_AUDIT_ + + #ifndef GUID_DEFINED + #include + #endif + + #endif /* _NTLSA_AUDIT_ */ + #endif /* _NTLSA_IFS_ */ + + typedef GUID UUID; + + struct _LOADER_PARAMETER_BLOCK; + struct _CREATE_DISK; + struct _DRIVE_LAYOUT_INFORMATION_EX; + struct _SET_PARTITION_INFORMATION_EX; + + typedef struct _BUS_HANDLER *PBUS_HANDLER; + typedef struct _DEVICE_HANDLER_OBJECT *PDEVICE_HANDLER_OBJECT; + #if defined(_NTHAL_INCLUDED_) + typedef struct _KAFFINITY_EX *PKAFFINITY_EX; + #endif + typedef struct _PEB *PPEB; + + #ifndef _NTIMAGE_ + + typedef struct _IMAGE_NT_HEADERS *PIMAGE_NT_HEADERS32; + typedef struct _IMAGE_NT_HEADERS64 *PIMAGE_NT_HEADERS64; + + #ifdef _WIN64 + typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; + #else + typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; + #endif + + #endif /* _NTIMAGE_ */ + + /****************************************************************************** + * Executive Types * + ******************************************************************************/ + typedef struct _ZONE_SEGMENT_HEADER { + SINGLE_LIST_ENTRY SegmentList; + PVOID Reserved; + } ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER; + + typedef struct _ZONE_HEADER { + SINGLE_LIST_ENTRY FreeList; + SINGLE_LIST_ENTRY SegmentList; + ULONG BlockSize; + ULONG TotalSegmentSize; + } ZONE_HEADER, *PZONE_HEADER; + + #define PROTECTED_POOL 0x80000000 + + /****************************************************************************** + * I/O Manager Types * + ******************************************************************************/ + + /* DEVICE_OBJECT.Flags */ + #define DO_DEVICE_HAS_NAME 0x00000040 + #define DO_SYSTEM_BOOT_PARTITION 0x00000100 + #define DO_LONG_TERM_REQUESTS 0x00000200 + #define DO_NEVER_LAST_DEVICE 0x00000400 + #define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 + #define DO_SUPPORTS_TRANSACTIONS 0x00040000 + #define DO_FORCE_NEITHER_IO 0x00080000 + #define DO_VOLUME_DEVICE_OBJECT 0x00100000 + #define DO_SYSTEM_SYSTEM_PARTITION 0x00200000 + #define DO_SYSTEM_CRITICAL_PARTITION 0x00400000 + #define DO_DISALLOW_EXECUTE 0x00800000 + + #ifndef _ARC_DDK_ + #define _ARC_DDK_ + typedef enum _CONFIGURATION_TYPE { + ArcSystem, + CentralProcessor, + FloatingPointProcessor, + PrimaryIcache, + PrimaryDcache, + SecondaryIcache, + SecondaryDcache, + SecondaryCache, + EisaAdapter, + TcAdapter, + ScsiAdapter, + DtiAdapter, + MultiFunctionAdapter, + DiskController, + TapeController, + CdromController, + WormController, + SerialController, + NetworkController, + DisplayController, + ParallelController, + PointerController, + KeyboardController, + AudioController, + OtherController, + DiskPeripheral, + FloppyDiskPeripheral, + TapePeripheral, + ModemPeripheral, + MonitorPeripheral, + PrinterPeripheral, + PointerPeripheral, + KeyboardPeripheral, + TerminalPeripheral, + OtherPeripheral, + LinePeripheral, + NetworkPeripheral, + SystemMemory, + DockingInformation, + RealModeIrqRoutingTable, + RealModePCIEnumeration, + MaximumType + } CONFIGURATION_TYPE, *PCONFIGURATION_TYPE; + #endif /* !_ARC_DDK_ */ + + /* + ** IRP function codes + */ + + #define IRP_MN_QUERY_DIRECTORY 0x01 + #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 + + #define IRP_MN_USER_FS_REQUEST 0x00 + #define IRP_MN_MOUNT_VOLUME 0x01 + #define IRP_MN_VERIFY_VOLUME 0x02 + #define IRP_MN_LOAD_FILE_SYSTEM 0x03 + #define IRP_MN_TRACK_LINK 0x04 + #define IRP_MN_KERNEL_CALL 0x04 + + #define IRP_MN_LOCK 0x01 + #define IRP_MN_UNLOCK_SINGLE 0x02 + #define IRP_MN_UNLOCK_ALL 0x03 + #define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 + + #define IRP_MN_FLUSH_AND_PURGE 0x01 + + #define IRP_MN_NORMAL 0x00 + #define IRP_MN_DPC 0x01 + #define IRP_MN_MDL 0x02 + #define IRP_MN_COMPLETE 0x04 + #define IRP_MN_COMPRESSED 0x08 + + #define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC) + #define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL) + #define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC) + + #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 + + #define IO_CHECK_CREATE_PARAMETERS 0x0200 + #define IO_ATTACH_DEVICE 0x0400 + #define IO_IGNORE_SHARE_ACCESS_CHECK 0x0800 + + typedef NTSTATUS + (NTAPI *PIO_QUERY_DEVICE_ROUTINE)( + _In_ PVOID Context, + _In_ PUNICODE_STRING PathName, + _In_ INTERFACE_TYPE BusType, + _In_ ULONG BusNumber, + _In_ PKEY_VALUE_FULL_INFORMATION *BusInformation, + _In_ CONFIGURATION_TYPE ControllerType, + _In_ ULONG ControllerNumber, + _In_ PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + _In_ CONFIGURATION_TYPE PeripheralType, + _In_ ULONG PeripheralNumber, + _In_ PKEY_VALUE_FULL_INFORMATION *PeripheralInformation); + + typedef enum _IO_QUERY_DEVICE_DATA_FORMAT { + IoQueryDeviceIdentifier = 0, + IoQueryDeviceConfigurationData, + IoQueryDeviceComponentInformation, + IoQueryDeviceMaxData + } IO_QUERY_DEVICE_DATA_FORMAT, *PIO_QUERY_DEVICE_DATA_FORMAT; + + typedef VOID + (NTAPI *PDRIVER_REINITIALIZE)( + _In_ struct _DRIVER_OBJECT *DriverObject, + _In_opt_ PVOID Context, + _In_ ULONG Count); + + typedef struct _CONTROLLER_OBJECT { + CSHORT Type; + CSHORT Size; + PVOID ControllerExtension; + KDEVICE_QUEUE DeviceWaitQueue; + ULONG Spare1; + LARGE_INTEGER Spare2; + } CONTROLLER_OBJECT, *PCONTROLLER_OBJECT; + + #define DRVO_REINIT_REGISTERED 0x00000008 + #define DRVO_INITIALIZED 0x00000010 + #define DRVO_BOOTREINIT_REGISTERED 0x00000020 + #define DRVO_LEGACY_RESOURCES 0x00000040 + + typedef struct _CONFIGURATION_INFORMATION { + ULONG DiskCount; + ULONG FloppyCount; + ULONG CdRomCount; + ULONG TapeCount; + ULONG ScsiPortCount; + ULONG SerialCount; + ULONG ParallelCount; + BOOLEAN AtDiskPrimaryAddressClaimed; + BOOLEAN AtDiskSecondaryAddressClaimed; + ULONG Version; + ULONG MediumChangerCount; + } CONFIGURATION_INFORMATION, *PCONFIGURATION_INFORMATION; + + typedef struct _DISK_SIGNATURE { + ULONG PartitionStyle; + _ANONYMOUS_UNION union { + struct { + ULONG Signature; + ULONG CheckSum; + } Mbr; + struct { + GUID DiskId; + } Gpt; + } DUMMYUNIONNAME; + } DISK_SIGNATURE, *PDISK_SIGNATURE; + + typedef struct _TXN_PARAMETER_BLOCK { + USHORT Length; + USHORT TxFsContext; + PVOID TransactionObject; + } TXN_PARAMETER_BLOCK, *PTXN_PARAMETER_BLOCK; + + #define TXF_MINIVERSION_DEFAULT_VIEW (0xFFFE) + + typedef struct _IO_DRIVER_CREATE_CONTEXT { + CSHORT Size; + struct _ECP_LIST *ExtraCreateParameter; + PVOID DeviceObjectHint; + PTXN_PARAMETER_BLOCK TxnParameters; + } IO_DRIVER_CREATE_CONTEXT, *PIO_DRIVER_CREATE_CONTEXT; + + typedef struct _AGP_TARGET_BUS_INTERFACE_STANDARD { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PGET_SET_DEVICE_DATA SetBusData; + PGET_SET_DEVICE_DATA GetBusData; + UCHAR CapabilityID; + } AGP_TARGET_BUS_INTERFACE_STANDARD, *PAGP_TARGET_BUS_INTERFACE_STANDARD; + + _IRQL_requires_max_(PASSIVE_LEVEL) + _Must_inspect_result_ + typedef NTSTATUS + (NTAPI *PGET_LOCATION_STRING)( + _Inout_opt_ PVOID Context, + _Outptr_ + _At_(*LocationStrings, + _When_(return == 0, __drv_allocatesMem(Mem))) + PZZWSTR *LocationStrings); + + typedef struct _PNP_LOCATION_INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PGET_LOCATION_STRING GetLocationString; + } PNP_LOCATION_INTERFACE, *PPNP_LOCATION_INTERFACE; + + typedef enum _ARBITER_ACTION { + ArbiterActionTestAllocation, + ArbiterActionRetestAllocation, + ArbiterActionCommitAllocation, + ArbiterActionRollbackAllocation, + ArbiterActionQueryAllocatedResources, + ArbiterActionWriteReservedResources, + ArbiterActionQueryConflict, + ArbiterActionQueryArbitrate, + ArbiterActionAddReserved, + ArbiterActionBootAllocation + } ARBITER_ACTION, *PARBITER_ACTION; + + typedef struct _ARBITER_CONFLICT_INFO { + PDEVICE_OBJECT OwningObject; + ULONGLONG Start; + ULONGLONG End; + } ARBITER_CONFLICT_INFO, *PARBITER_CONFLICT_INFO; + + typedef struct _ARBITER_TEST_ALLOCATION_PARAMETERS { + _Inout_ PLIST_ENTRY ArbitrationList; + _In_ ULONG AllocateFromCount; + _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR AllocateFrom; + } ARBITER_TEST_ALLOCATION_PARAMETERS, *PARBITER_TEST_ALLOCATION_PARAMETERS; + + typedef struct _ARBITER_RETEST_ALLOCATION_PARAMETERS { + _Inout_ PLIST_ENTRY ArbitrationList; + _In_ ULONG AllocateFromCount; + _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR AllocateFrom; + } ARBITER_RETEST_ALLOCATION_PARAMETERS, *PARBITER_RETEST_ALLOCATION_PARAMETERS; + + typedef struct _ARBITER_BOOT_ALLOCATION_PARAMETERS { + _Inout_ PLIST_ENTRY ArbitrationList; + } ARBITER_BOOT_ALLOCATION_PARAMETERS, *PARBITER_BOOT_ALLOCATION_PARAMETERS; + + typedef struct _ARBITER_QUERY_ALLOCATED_RESOURCES_PARAMETERS { + _Out_ PCM_PARTIAL_RESOURCE_LIST *AllocatedResources; + } ARBITER_QUERY_ALLOCATED_RESOURCES_PARAMETERS, *PARBITER_QUERY_ALLOCATED_RESOURCES_PARAMETERS; + + typedef struct _ARBITER_QUERY_CONFLICT_PARAMETERS { + _In_ PDEVICE_OBJECT PhysicalDeviceObject; + _In_ PIO_RESOURCE_DESCRIPTOR ConflictingResource; + _Out_ PULONG ConflictCount; + _Out_ PARBITER_CONFLICT_INFO *Conflicts; + } ARBITER_QUERY_CONFLICT_PARAMETERS, *PARBITER_QUERY_CONFLICT_PARAMETERS; + + typedef struct _ARBITER_QUERY_ARBITRATE_PARAMETERS { + _In_ PLIST_ENTRY ArbitrationList; + } ARBITER_QUERY_ARBITRATE_PARAMETERS, *PARBITER_QUERY_ARBITRATE_PARAMETERS; + + typedef struct _ARBITER_ADD_RESERVED_PARAMETERS { + _In_ PDEVICE_OBJECT ReserveDevice; + } ARBITER_ADD_RESERVED_PARAMETERS, *PARBITER_ADD_RESERVED_PARAMETERS; + + typedef struct _ARBITER_PARAMETERS { + union { + ARBITER_TEST_ALLOCATION_PARAMETERS TestAllocation; + ARBITER_RETEST_ALLOCATION_PARAMETERS RetestAllocation; + ARBITER_BOOT_ALLOCATION_PARAMETERS BootAllocation; + ARBITER_QUERY_ALLOCATED_RESOURCES_PARAMETERS QueryAllocatedResources; + ARBITER_QUERY_CONFLICT_PARAMETERS QueryConflict; + ARBITER_QUERY_ARBITRATE_PARAMETERS QueryArbitrate; + ARBITER_ADD_RESERVED_PARAMETERS AddReserved; + } Parameters; + } ARBITER_PARAMETERS, *PARBITER_PARAMETERS; + + typedef enum _ARBITER_REQUEST_SOURCE { + ArbiterRequestUndefined = -1, + ArbiterRequestLegacyReported, + ArbiterRequestHalReported, + ArbiterRequestLegacyAssigned, + ArbiterRequestPnpDetected, + ArbiterRequestPnpEnumerated + } ARBITER_REQUEST_SOURCE; + + typedef enum _ARBITER_RESULT { + ArbiterResultUndefined = -1, + ArbiterResultSuccess, + ArbiterResultExternalConflict, + ArbiterResultNullRequest + } ARBITER_RESULT; + + #define ARBITER_FLAG_BOOT_CONFIG 0x00000001 + + typedef struct _ARBITER_LIST_ENTRY { + LIST_ENTRY ListEntry; + ULONG AlternativeCount; + PIO_RESOURCE_DESCRIPTOR Alternatives; + PDEVICE_OBJECT PhysicalDeviceObject; + ARBITER_REQUEST_SOURCE RequestSource; + ULONG Flags; + LONG_PTR WorkSpace; + INTERFACE_TYPE InterfaceType; + ULONG SlotNumber; + ULONG BusNumber; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Assignment; + PIO_RESOURCE_DESCRIPTOR SelectedAlternative; + ARBITER_RESULT Result; + } ARBITER_LIST_ENTRY, *PARBITER_LIST_ENTRY; + + typedef NTSTATUS + (NTAPI *PARBITER_HANDLER)( + _Inout_opt_ PVOID Context, + _In_ ARBITER_ACTION Action, + _Inout_ PARBITER_PARAMETERS Parameters); + + #define ARBITER_PARTIAL 0x00000001 + + typedef struct _ARBITER_INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PARBITER_HANDLER ArbiterHandler; + ULONG Flags; + } ARBITER_INTERFACE, *PARBITER_INTERFACE; + + typedef enum _RESOURCE_TRANSLATION_DIRECTION { + TranslateChildToParent, + TranslateParentToChild + } RESOURCE_TRANSLATION_DIRECTION; + + typedef NTSTATUS + (NTAPI *PTRANSLATE_RESOURCE_HANDLER)( + _Inout_opt_ PVOID Context, + _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Source, + _In_ RESOURCE_TRANSLATION_DIRECTION Direction, + _In_opt_ ULONG AlternativesCount, + _In_reads_opt_(AlternativesCount) IO_RESOURCE_DESCRIPTOR Alternatives[], + _In_ PDEVICE_OBJECT PhysicalDeviceObject, + _Out_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Target); + + typedef NTSTATUS + (NTAPI *PTRANSLATE_RESOURCE_REQUIREMENTS_HANDLER)( + _Inout_opt_ PVOID Context, + _In_ PIO_RESOURCE_DESCRIPTOR Source, + _In_ PDEVICE_OBJECT PhysicalDeviceObject, + _Out_ PULONG TargetCount, + _Out_writes_(*TargetCount) PIO_RESOURCE_DESCRIPTOR *Target); + + typedef struct _TRANSLATOR_INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PTRANSLATE_RESOURCE_HANDLER TranslateResources; + PTRANSLATE_RESOURCE_REQUIREMENTS_HANDLER TranslateResourceRequirements; + } TRANSLATOR_INTERFACE, *PTRANSLATOR_INTERFACE; + + typedef struct _PCI_AGP_CAPABILITY { + PCI_CAPABILITIES_HEADER Header; + USHORT Minor:4; + USHORT Major:4; + USHORT Rsvd1:8; + struct _PCI_AGP_STATUS { + ULONG Rate:3; + ULONG Agp3Mode:1; + ULONG FastWrite:1; + ULONG FourGB:1; + ULONG HostTransDisable:1; + ULONG Gart64:1; + ULONG ITA_Coherent:1; + ULONG SideBandAddressing:1; + ULONG CalibrationCycle:3; + ULONG AsyncRequestSize:3; + ULONG Rsvd1:1; + ULONG Isoch:1; + ULONG Rsvd2:6; + ULONG RequestQueueDepthMaximum:8; + } AGPStatus; + struct _PCI_AGP_COMMAND { + ULONG Rate:3; + ULONG Rsvd1:1; + ULONG FastWriteEnable:1; + ULONG FourGBEnable:1; + ULONG Rsvd2:1; + ULONG Gart64:1; + ULONG AGPEnable:1; + ULONG SBAEnable:1; + ULONG CalibrationCycle:3; + ULONG AsyncReqSize:3; + ULONG Rsvd3:8; + ULONG RequestQueueDepth:8; + } AGPCommand; + } PCI_AGP_CAPABILITY, *PPCI_AGP_CAPABILITY; + + typedef enum _EXTENDED_AGP_REGISTER { + IsochStatus, + AgpControl, + ApertureSize, + AperturePageSize, + GartLow, + GartHigh, + IsochCommand + } EXTENDED_AGP_REGISTER, *PEXTENDED_AGP_REGISTER; + + typedef struct _PCI_AGP_ISOCH_STATUS { + ULONG ErrorCode:2; + ULONG Rsvd1:1; + ULONG Isoch_L:3; + ULONG Isoch_Y:2; + ULONG Isoch_N:8; + ULONG Rsvd2:16; + } PCI_AGP_ISOCH_STATUS, *PPCI_AGP_ISOCH_STATUS; + + typedef struct _PCI_AGP_CONTROL { + ULONG Rsvd1:7; + ULONG GTLB_Enable:1; + ULONG AP_Enable:1; + ULONG CAL_Disable:1; + ULONG Rsvd2:22; + } PCI_AGP_CONTROL, *PPCI_AGP_CONTROL; + + typedef struct _PCI_AGP_APERTURE_PAGE_SIZE { + USHORT PageSizeMask:11; + USHORT Rsvd1:1; + USHORT PageSizeSelect:4; + } PCI_AGP_APERTURE_PAGE_SIZE, *PPCI_AGP_APERTURE_PAGE_SIZE; + + typedef struct _PCI_AGP_ISOCH_COMMAND { + USHORT Rsvd1:6; + USHORT Isoch_Y:2; + USHORT Isoch_N:8; + } PCI_AGP_ISOCH_COMMAND, *PPCI_AGP_ISOCH_COMMAND; + + typedef struct PCI_AGP_EXTENDED_CAPABILITY { + PCI_AGP_ISOCH_STATUS IsochStatus; + PCI_AGP_CONTROL AgpControl; + USHORT ApertureSize; + PCI_AGP_APERTURE_PAGE_SIZE AperturePageSize; + ULONG GartLow; + ULONG GartHigh; + PCI_AGP_ISOCH_COMMAND IsochCommand; + } PCI_AGP_EXTENDED_CAPABILITY, *PPCI_AGP_EXTENDED_CAPABILITY; + + #define PCI_AGP_RATE_1X 0x1 + #define PCI_AGP_RATE_2X 0x2 + #define PCI_AGP_RATE_4X 0x4 + + #define PCIX_MODE_CONVENTIONAL_PCI 0x0 + #define PCIX_MODE1_66MHZ 0x1 + #define PCIX_MODE1_100MHZ 0x2 + #define PCIX_MODE1_133MHZ 0x3 + #define PCIX_MODE2_266_66MHZ 0x9 + #define PCIX_MODE2_266_100MHZ 0xA + #define PCIX_MODE2_266_133MHZ 0xB + #define PCIX_MODE2_533_66MHZ 0xD + #define PCIX_MODE2_533_100MHZ 0xE + #define PCIX_MODE2_533_133MHZ 0xF + + #define PCIX_VERSION_MODE1_ONLY 0x0 + #define PCIX_VERSION_MODE2_ECC 0x1 + #define PCIX_VERSION_DUAL_MODE_ECC 0x2 + + typedef struct _PCIX_BRIDGE_CAPABILITY { + PCI_CAPABILITIES_HEADER Header; + union { + _ANONYMOUS_STRUCT struct { + USHORT Bus64Bit:1; + USHORT Bus133MHzCapable:1; + USHORT SplitCompletionDiscarded:1; + USHORT UnexpectedSplitCompletion:1; + USHORT SplitCompletionOverrun:1; + USHORT SplitRequestDelayed:1; + USHORT BusModeFrequency:4; + USHORT Rsvd:2; + USHORT Version:2; + USHORT Bus266MHzCapable:1; + USHORT Bus533MHzCapable:1; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } SecondaryStatus; + union { + _ANONYMOUS_STRUCT struct { + ULONG FunctionNumber:3; + ULONG DeviceNumber:5; + ULONG BusNumber:8; + ULONG Device64Bit:1; + ULONG Device133MHzCapable:1; + ULONG SplitCompletionDiscarded:1; + ULONG UnexpectedSplitCompletion:1; + ULONG SplitCompletionOverrun:1; + ULONG SplitRequestDelayed:1; + ULONG Rsvd:7; + ULONG DIMCapable:1; + ULONG Device266MHzCapable:1; + ULONG Device533MHzCapable:1; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } BridgeStatus; + USHORT UpstreamSplitTransactionCapacity; + USHORT UpstreamSplitTransactionLimit; + USHORT DownstreamSplitTransactionCapacity; + USHORT DownstreamSplitTransactionLimit; + union { + _ANONYMOUS_STRUCT struct { + ULONG SelectSecondaryRegisters:1; + ULONG ErrorPresentInOtherBank:1; + ULONG AdditionalCorrectableError:1; + ULONG AdditionalUncorrectableError:1; + ULONG ErrorPhase:3; + ULONG ErrorCorrected:1; + ULONG Syndrome:8; + ULONG ErrorFirstCommand:4; + ULONG ErrorSecondCommand:4; + ULONG ErrorUpperAttributes:4; + ULONG ControlUpdateEnable:1; + ULONG Rsvd:1; + ULONG DisableSingleBitCorrection:1; + ULONG EccMode:1; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } EccControlStatus; + ULONG EccFirstAddress; + ULONG EccSecondAddress; + ULONG EccAttribute; + } PCIX_BRIDGE_CAPABILITY, *PPCIX_BRIDGE_CAPABILITY; + + typedef struct _PCI_SUBSYSTEM_IDS_CAPABILITY { + PCI_CAPABILITIES_HEADER Header; + USHORT Reserved; + USHORT SubVendorID; + USHORT SubSystemID; + } PCI_SUBSYSTEM_IDS_CAPABILITY, *PPCI_SUBSYSTEM_IDS_CAPABILITY; + + #define OSC_FIRMWARE_FAILURE 0x02 + #define OSC_UNRECOGNIZED_UUID 0x04 + #define OSC_UNRECOGNIZED_REVISION 0x08 + #define OSC_CAPABILITIES_MASKED 0x10 + + #define PCI_ROOT_BUS_OSC_METHOD_CAPABILITY_REVISION 0x01 + + typedef struct _PCI_ROOT_BUS_OSC_SUPPORT_FIELD { + union { + _ANONYMOUS_STRUCT struct { + ULONG ExtendedConfigOpRegions:1; + ULONG ActiveStatePowerManagement:1; + ULONG ClockPowerManagement:1; + ULONG SegmentGroups:1; + ULONG MessageSignaledInterrupts:1; + ULONG WindowsHardwareErrorArchitecture:1; + ULONG Reserved:26; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } u; + } PCI_ROOT_BUS_OSC_SUPPORT_FIELD, *PPCI_ROOT_BUS_OSC_SUPPORT_FIELD; + + typedef struct _PCI_ROOT_BUS_OSC_CONTROL_FIELD { + union { + _ANONYMOUS_STRUCT struct { + ULONG ExpressNativeHotPlug:1; + ULONG ShpcNativeHotPlug:1; + ULONG ExpressNativePME:1; + ULONG ExpressAdvancedErrorReporting:1; + ULONG ExpressCapabilityStructure:1; + ULONG Reserved:27; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } u; + } PCI_ROOT_BUS_OSC_CONTROL_FIELD, *PPCI_ROOT_BUS_OSC_CONTROL_FIELD; + + typedef enum _PCI_HARDWARE_INTERFACE { + PciConventional, + PciXMode1, + PciXMode2, + PciExpress + } PCI_HARDWARE_INTERFACE, *PPCI_HARDWARE_INTERFACE; + + typedef enum { + BusWidth32Bits, + BusWidth64Bits + } PCI_BUS_WIDTH; + + typedef struct _PCI_ROOT_BUS_HARDWARE_CAPABILITY { + PCI_HARDWARE_INTERFACE SecondaryInterface; + _ANONYMOUS_STRUCT struct { + BOOLEAN BusCapabilitiesFound; + ULONG CurrentSpeedAndMode; + ULONG SupportedSpeedsAndModes; + BOOLEAN DeviceIDMessagingCapable; + PCI_BUS_WIDTH SecondaryBusWidth; + } DUMMYSTRUCTNAME; + PCI_ROOT_BUS_OSC_SUPPORT_FIELD OscFeatureSupport; + PCI_ROOT_BUS_OSC_CONTROL_FIELD OscControlRequest; + PCI_ROOT_BUS_OSC_CONTROL_FIELD OscControlGranted; + } PCI_ROOT_BUS_HARDWARE_CAPABILITY, *PPCI_ROOT_BUS_HARDWARE_CAPABILITY; + + typedef union _PCI_EXPRESS_CAPABILITIES_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT CapabilityVersion:4; + USHORT DeviceType:4; + USHORT SlotImplemented:1; + USHORT InterruptMessageNumber:5; + USHORT Rsvd:2; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_CAPABILITIES_REGISTER, *PPCI_EXPRESS_CAPABILITIES_REGISTER; + + typedef union _PCI_EXPRESS_DEVICE_CAPABILITIES_REGISTER { + _ANONYMOUS_STRUCT struct { + ULONG MaxPayloadSizeSupported:3; + ULONG PhantomFunctionsSupported:2; + ULONG ExtendedTagSupported:1; + ULONG L0sAcceptableLatency:3; + ULONG L1AcceptableLatency:3; + ULONG Undefined:3; + ULONG RoleBasedErrorReporting:1; + ULONG Rsvd1:2; + ULONG CapturedSlotPowerLimit:8; + ULONG CapturedSlotPowerLimitScale:2; + ULONG Rsvd2:4; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } PCI_EXPRESS_DEVICE_CAPABILITIES_REGISTER, *PPCI_EXPRESS_DEVICE_CAPABILITIES_REGISTER; + + #define PCI_EXPRESS_AER_DEVICE_CONTROL_MASK 0x07; + + typedef union _PCI_EXPRESS_DEVICE_CONTROL_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT CorrectableErrorEnable:1; + USHORT NonFatalErrorEnable:1; + USHORT FatalErrorEnable:1; + USHORT UnsupportedRequestErrorEnable:1; + USHORT EnableRelaxedOrder:1; + USHORT MaxPayloadSize:3; + USHORT ExtendedTagEnable:1; + USHORT PhantomFunctionsEnable:1; + USHORT AuxPowerEnable:1; + USHORT NoSnoopEnable:1; + USHORT MaxReadRequestSize:3; + USHORT BridgeConfigRetryEnable:1; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_DEVICE_CONTROL_REGISTER, *PPCI_EXPRESS_DEVICE_CONTROL_REGISTER; + + #define PCI_EXPRESS_AER_DEVICE_STATUS_MASK 0x0F; + + typedef union _PCI_EXPRESS_DEVICE_STATUS_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT CorrectableErrorDetected:1; + USHORT NonFatalErrorDetected:1; + USHORT FatalErrorDetected:1; + USHORT UnsupportedRequestDetected:1; + USHORT AuxPowerDetected:1; + USHORT TransactionsPending:1; + USHORT Rsvd:10; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_DEVICE_STATUS_REGISTER, *PPCI_EXPRESS_DEVICE_STATUS_REGISTER; + + typedef union _PCI_EXPRESS_LINK_CAPABILITIES_REGISTER { + _ANONYMOUS_STRUCT struct { + ULONG MaximumLinkSpeed:4; + ULONG MaximumLinkWidth:6; + ULONG ActiveStatePMSupport:2; + ULONG L0sExitLatency:3; + ULONG L1ExitLatency:3; + ULONG ClockPowerManagement:1; + ULONG SurpriseDownErrorReportingCapable:1; + ULONG DataLinkLayerActiveReportingCapable:1; + ULONG Rsvd:3; + ULONG PortNumber:8; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } PCI_EXPRESS_LINK_CAPABILITIES_REGISTER, *PPCI_EXPRESS_LINK_CAPABILITIES_REGISTER; + + typedef union _PCI_EXPRESS_LINK_CONTROL_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT ActiveStatePMControl:2; + USHORT Rsvd1:1; + USHORT ReadCompletionBoundary:1; + USHORT LinkDisable:1; + USHORT RetrainLink:1; + USHORT CommonClockConfig:1; + USHORT ExtendedSynch:1; + USHORT EnableClockPowerManagement:1; + USHORT Rsvd2:7; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_LINK_CONTROL_REGISTER, *PPCI_EXPRESS_LINK_CONTROL_REGISTER; + + typedef union _PCI_EXPRESS_LINK_STATUS_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT LinkSpeed:4; + USHORT LinkWidth:6; + USHORT Undefined:1; + USHORT LinkTraining:1; + USHORT SlotClockConfig:1; + USHORT DataLinkLayerActive:1; + USHORT Rsvd:2; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_LINK_STATUS_REGISTER, *PPCI_EXPRESS_LINK_STATUS_REGISTER; + + typedef union _PCI_EXPRESS_SLOT_CAPABILITIES_REGISTER { + _ANONYMOUS_STRUCT struct { + ULONG AttentionButtonPresent:1; + ULONG PowerControllerPresent:1; + ULONG MRLSensorPresent:1; + ULONG AttentionIndicatorPresent:1; + ULONG PowerIndicatorPresent:1; + ULONG HotPlugSurprise:1; + ULONG HotPlugCapable:1; + ULONG SlotPowerLimit:8; + ULONG SlotPowerLimitScale:2; + ULONG ElectromechanicalLockPresent:1; + ULONG NoCommandCompletedSupport:1; + ULONG PhysicalSlotNumber:13; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } PCI_EXPRESS_SLOT_CAPABILITIES_REGISTER, *PPCI_EXPRESS_SLOT_CAPABILITIES_REGISTER; + + typedef union _PCI_EXPRESS_SLOT_CONTROL_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT AttentionButtonEnable:1; + USHORT PowerFaultDetectEnable:1; + USHORT MRLSensorEnable:1; + USHORT PresenceDetectEnable:1; + USHORT CommandCompletedEnable:1; + USHORT HotPlugInterruptEnable:1; + USHORT AttentionIndicatorControl:2; + USHORT PowerIndicatorControl:2; + USHORT PowerControllerControl:1; + USHORT ElectromechanicalLockControl:1; + USHORT DataLinkStateChangeEnable:1; + USHORT Rsvd:3; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_SLOT_CONTROL_REGISTER, *PPCI_EXPRESS_SLOT_CONTROL_REGISTER; + + typedef union _PCI_EXPRESS_SLOT_STATUS_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT AttentionButtonPressed:1; + USHORT PowerFaultDetected:1; + USHORT MRLSensorChanged:1; + USHORT PresenceDetectChanged:1; + USHORT CommandCompleted:1; + USHORT MRLSensorState:1; + USHORT PresenceDetectState:1; + USHORT ElectromechanicalLockEngaged:1; + USHORT DataLinkStateChanged:1; + USHORT Rsvd:7; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_SLOT_STATUS_REGISTER, *PPCI_EXPRESS_SLOT_STATUS_REGISTER; + + typedef union _PCI_EXPRESS_ROOT_CONTROL_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT CorrectableSerrEnable:1; + USHORT NonFatalSerrEnable:1; + USHORT FatalSerrEnable:1; + USHORT PMEInterruptEnable:1; + USHORT CRSSoftwareVisibilityEnable:1; + USHORT Rsvd:11; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_ROOT_CONTROL_REGISTER, *PPCI_EXPRESS_ROOT_CONTROL_REGISTER; + + typedef union _PCI_EXPRESS_ROOT_CAPABILITIES_REGISTER { + _ANONYMOUS_STRUCT struct { + USHORT CRSSoftwareVisibility:1; + USHORT Rsvd:15; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_ROOT_CAPABILITIES_REGISTER, *PPCI_EXPRESS_ROOT_CAPABILITIES_REGISTER; + + typedef union _PCI_EXPRESS_ROOT_STATUS_REGISTER { + _ANONYMOUS_STRUCT struct { + ULONG PMERequestorId:16; + ULONG PMEStatus:1; + ULONG PMEPending:1; + ULONG Rsvd:14; + } DUMMYSTRUCTNAME; + ULONG AsULONG; + } PCI_EXPRESS_ROOT_STATUS_REGISTER, *PPCI_EXPRESS_ROOT_STATUS_REGISTER; + + typedef struct _PCI_EXPRESS_CAPABILITY { + PCI_CAPABILITIES_HEADER Header; + PCI_EXPRESS_CAPABILITIES_REGISTER ExpressCapabilities; + PCI_EXPRESS_DEVICE_CAPABILITIES_REGISTER DeviceCapabilities; + PCI_EXPRESS_DEVICE_CONTROL_REGISTER DeviceControl; + PCI_EXPRESS_DEVICE_STATUS_REGISTER DeviceStatus; + PCI_EXPRESS_LINK_CAPABILITIES_REGISTER LinkCapabilities; + PCI_EXPRESS_LINK_CONTROL_REGISTER LinkControl; + PCI_EXPRESS_LINK_STATUS_REGISTER LinkStatus; + PCI_EXPRESS_SLOT_CAPABILITIES_REGISTER SlotCapabilities; + PCI_EXPRESS_SLOT_CONTROL_REGISTER SlotControl; + PCI_EXPRESS_SLOT_STATUS_REGISTER SlotStatus; + PCI_EXPRESS_ROOT_CONTROL_REGISTER RootControl; + PCI_EXPRESS_ROOT_CAPABILITIES_REGISTER RootCapabilities; + PCI_EXPRESS_ROOT_STATUS_REGISTER RootStatus; + } PCI_EXPRESS_CAPABILITY, *PPCI_EXPRESS_CAPABILITY; + + typedef enum { + MRLClosed = 0, + MRLOpen + } PCI_EXPRESS_MRL_STATE; + + typedef enum { + SlotEmpty = 0, + CardPresent + } PCI_EXPRESS_CARD_PRESENCE; + + typedef enum { + IndicatorOn = 1, + IndicatorBlink, + IndicatorOff + } PCI_EXPRESS_INDICATOR_STATE; + + typedef enum { + PowerOn = 0, + PowerOff + } PCI_EXPRESS_POWER_STATE; + + typedef enum { + L0sEntrySupport = 1, + L0sAndL1EntrySupport = 3 + } PCI_EXPRESS_ASPM_SUPPORT; + + typedef enum { + L0sAndL1EntryDisabled, + L0sEntryEnabled, + L1EntryEnabled, + L0sAndL1EntryEnabled + } PCI_EXPRESS_ASPM_CONTROL; + + typedef enum { + L0s_Below64ns = 0, + L0s_64ns_128ns, + L0s_128ns_256ns, + L0s_256ns_512ns, + L0s_512ns_1us, + L0s_1us_2us, + L0s_2us_4us, + L0s_Above4us + } PCI_EXPRESS_L0s_EXIT_LATENCY; + + typedef enum { + L1_Below1us = 0, + L1_1us_2us, + L1_2us_4us, + L1_4us_8us, + L1_8us_16us, + L1_16us_32us, + L1_32us_64us, + L1_Above64us + } PCI_EXPRESS_L1_EXIT_LATENCY; + + typedef enum { + PciExpressEndpoint = 0, + PciExpressLegacyEndpoint, + PciExpressRootPort = 4, + PciExpressUpstreamSwitchPort, + PciExpressDownstreamSwitchPort, + PciExpressToPciXBridge, + PciXToExpressBridge, + PciExpressRootComplexIntegratedEndpoint, + PciExpressRootComplexEventCollector + } PCI_EXPRESS_DEVICE_TYPE; + + typedef enum { + MaxPayload128Bytes = 0, + MaxPayload256Bytes, + MaxPayload512Bytes, + MaxPayload1024Bytes, + MaxPayload2048Bytes, + MaxPayload4096Bytes + } PCI_EXPRESS_MAX_PAYLOAD_SIZE; + + typedef union _PCI_EXPRESS_PME_REQUESTOR_ID { + _ANONYMOUS_STRUCT struct { + USHORT FunctionNumber:3; + USHORT DeviceNumber:5; + USHORT BusNumber:8; + } DUMMYSTRUCTNAME; + USHORT AsUSHORT; + } PCI_EXPRESS_PME_REQUESTOR_ID, *PPCI_EXPRESS_PME_REQUESTOR_ID; + + typedef enum _PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR_TYPE { + ResourceTypeSingle = 0, + ResourceTypeRange, + ResourceTypeExtendedCounterConfiguration, + ResourceTypeOverflow, + ResourceTypeMax + } PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR_TYPE; + + typedef struct _PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR { + PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR_TYPE Type; + ULONG Flags; + union { + ULONG CounterIndex; + ULONG ExtendedRegisterAddress; + struct { + ULONG Begin; + ULONG End; + } Range; + } u; + } PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR, *PPHYSICAL_COUNTER_RESOURCE_DESCRIPTOR; + + typedef struct _PHYSICAL_COUNTER_RESOURCE_LIST { + ULONG Count; + PHYSICAL_COUNTER_RESOURCE_DESCRIPTOR Descriptors[ANYSIZE_ARRAY]; + } PHYSICAL_COUNTER_RESOURCE_LIST, *PPHYSICAL_COUNTER_RESOURCE_LIST; + + typedef VOID + (NTAPI *PciPin2Line)( + _In_ struct _BUS_HANDLER *BusHandler, + _In_ struct _BUS_HANDLER *RootHandler, + _In_ PCI_SLOT_NUMBER SlotNumber, + _In_ PPCI_COMMON_CONFIG PciData); + + typedef VOID + (NTAPI *PciLine2Pin)( + _In_ struct _BUS_HANDLER *BusHandler, + _In_ struct _BUS_HANDLER *RootHandler, + _In_ PCI_SLOT_NUMBER SlotNumber, + _In_ PPCI_COMMON_CONFIG PciNewData, + _In_ PPCI_COMMON_CONFIG PciOldData); + + typedef VOID + (NTAPI *PciReadWriteConfig)( + _In_ struct _BUS_HANDLER *BusHandler, + _In_ PCI_SLOT_NUMBER Slot, + _In_reads_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + + #define PCI_DATA_TAG ' ICP' + #define PCI_DATA_VERSION 1 + + typedef struct _PCIBUSDATA { + ULONG Tag; + ULONG Version; + PciReadWriteConfig ReadConfig; + PciReadWriteConfig WriteConfig; + PciPin2Line Pin2Line; + PciLine2Pin Line2Pin; + PCI_SLOT_NUMBER ParentSlot; + PVOID Reserved[4]; + } PCIBUSDATA, *PPCIBUSDATA; + + #ifndef _PCIINTRF_X_ + #define _PCIINTRF_X_ + + typedef ULONG + (NTAPI *PCI_READ_WRITE_CONFIG)( + _In_ PVOID Context, + _In_ ULONG BusOffset, + _In_ ULONG Slot, + _In_reads_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + + typedef VOID + (NTAPI *PCI_PIN_TO_LINE)( + _In_ PVOID Context, + _In_ PPCI_COMMON_CONFIG PciData); + + typedef VOID + (NTAPI *PCI_LINE_TO_PIN)( + _In_ PVOID Context, + _In_ PPCI_COMMON_CONFIG PciNewData, + _In_ PPCI_COMMON_CONFIG PciOldData); + + typedef VOID + (NTAPI *PCI_ROOT_BUS_CAPABILITY)( + _In_ PVOID Context, + _Out_ PPCI_ROOT_BUS_HARDWARE_CAPABILITY HardwareCapability); + + typedef VOID + (NTAPI *PCI_EXPRESS_WAKE_CONTROL)( + _In_ PVOID Context, + _In_ BOOLEAN EnableWake); + + typedef struct _PCI_BUS_INTERFACE_STANDARD { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PCI_READ_WRITE_CONFIG ReadConfig; + PCI_READ_WRITE_CONFIG WriteConfig; + PCI_PIN_TO_LINE PinToLine; + PCI_LINE_TO_PIN LineToPin; + PCI_ROOT_BUS_CAPABILITY RootBusCapability; + PCI_EXPRESS_WAKE_CONTROL ExpressWakeControl; + } PCI_BUS_INTERFACE_STANDARD, *PPCI_BUS_INTERFACE_STANDARD; + + #define PCI_BUS_INTERFACE_STANDARD_VERSION 1 + + #endif /* _PCIINTRF_X_ */ + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + #define FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL_EX 0x00004000 + #define FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL_EX 0x00008000 + #define FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK_EX \ + (FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL_EX | \ + FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL_EX) + + #define FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL_DEPRECATED 0x00000200 + #define FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL_DEPRECATED 0x00000300 + #define FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK_DEPRECATED 0x00000300 + + #else + + #define FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL 0x00000200 + #define FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL 0x00000300 + #define FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK 0x00000300 + + #define FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL_EX FILE_CHARACTERISTICS_EXPECT_ORDERLY_REMOVAL + #define FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL_EX FILE_CHARACTERISTICS_EXPECT_SURPRISE_REMOVAL + #define FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK_EX FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + #define FILE_CHARACTERISTICS_PROPAGATED (FILE_REMOVABLE_MEDIA | \ + FILE_READ_ONLY_DEVICE | \ + FILE_FLOPPY_DISKETTE | \ + FILE_WRITE_ONCE_MEDIA | \ + FILE_DEVICE_SECURE_OPEN) + + typedef struct _FILE_ALIGNMENT_INFORMATION { + ULONG AlignmentRequirement; + } FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; + + typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[1]; + } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + + + typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { + ULONG FileAttributes; + ULONG ReparseTag; + } FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; + + typedef struct _FILE_DISPOSITION_INFORMATION { + BOOLEAN DeleteFile; + } FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + + typedef struct _FILE_END_OF_FILE_INFORMATION { + LARGE_INTEGER EndOfFile; + } FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + + typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { + LARGE_INTEGER ValidDataLength; + } FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; + + typedef struct _FILE_FS_LABEL_INFORMATION { + ULONG VolumeLabelLength; + WCHAR VolumeLabel[1]; + } FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; + + typedef struct _FILE_FS_VOLUME_INFORMATION { + LARGE_INTEGER VolumeCreationTime; + ULONG VolumeSerialNumber; + ULONG VolumeLabelLength; + BOOLEAN SupportsObjects; + WCHAR VolumeLabel[1]; + } FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; + + typedef struct _FILE_FS_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER AvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; + } FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; + + typedef struct _FILE_FS_FULL_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER CallerAvailableAllocationUnits; + LARGE_INTEGER ActualAvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; + } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; + + typedef struct _FILE_FS_OBJECTID_INFORMATION { + UCHAR ObjectId[16]; + UCHAR ExtendedInfo[48]; + } FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; + + typedef union _FILE_SEGMENT_ELEMENT { + PVOID64 Buffer; + ULONGLONG Alignment; + }FILE_SEGMENT_ELEMENT, *PFILE_SEGMENT_ELEMENT; + + #define IOCTL_AVIO_ALLOCATE_STREAM CTL_CODE(FILE_DEVICE_AVIO, 1, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + #define IOCTL_AVIO_FREE_STREAM CTL_CODE(FILE_DEVICE_AVIO, 2, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + #define IOCTL_AVIO_MODIFY_STREAM CTL_CODE(FILE_DEVICE_AVIO, 3, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + + typedef enum _BUS_DATA_TYPE { + ConfigurationSpaceUndefined = -1, + Cmos, + EisaConfiguration, + Pos, + CbusConfiguration, + PCIConfiguration, + VMEConfiguration, + NuBusConfiguration, + PCMCIAConfiguration, + MPIConfiguration, + MPSAConfiguration, + PNPISAConfiguration, + SgiInternalConfiguration, + MaximumBusDataType + } BUS_DATA_TYPE, *PBUS_DATA_TYPE; + + /* Some Server 2003 DDK definitions */ + #define PCI_INT_ROUTE_INTRF_STANDARD_VER 1 + + typedef NTSTATUS + (NTAPI *PLEGACY_DEVICE_DETECTION_HANDLER)( + IN PVOID Context, + IN INTERFACE_TYPE LegacyBusType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + OUT PDEVICE_OBJECT *PhysicalDeviceObject); + + typedef struct _ROUTING_TOKEN { + PVOID LinkNode; + ULONG StaticVector; + UCHAR Flags; + } ROUTING_TOKEN, *PROUTING_TOKEN; + + typedef NTSTATUS + (NTAPI *PGET_INTERRUPT_ROUTING)( + IN PDEVICE_OBJECT Pdo, + OUT ULONG *Bus, + OUT ULONG *PciSlot, + OUT UCHAR *InterruptLine, + OUT UCHAR *InterruptPin, + OUT UCHAR *ClassCode, + OUT UCHAR *SubClassCode, + OUT PDEVICE_OBJECT *ParentPdo, + OUT ROUTING_TOKEN *RoutingToken, + OUT UCHAR *Flags); + + typedef NTSTATUS + (NTAPI *PSET_INTERRUPT_ROUTING_TOKEN)( + IN PDEVICE_OBJECT Pdo, + IN PROUTING_TOKEN RoutingToken); + + typedef VOID + (NTAPI *PUPDATE_INTERRUPT_LINE)( + IN PDEVICE_OBJECT Pdo, + IN UCHAR LineRegister); + + typedef struct _INT_ROUTE_INTERFACE_STANDARD { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PGET_INTERRUPT_ROUTING GetInterruptRouting; + PSET_INTERRUPT_ROUTING_TOKEN SetInterruptRoutingToken; + PUPDATE_INTERRUPT_LINE UpdateInterruptLine; + } INT_ROUTE_INTERFACE_STANDARD, *PINT_ROUTE_INTERFACE_STANDARD; + + typedef struct _LEGACY_DEVICE_DETECTION_INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PLEGACY_DEVICE_DETECTION_HANDLER LegacyDeviceDetection; + } LEGACY_DEVICE_DETECTION_INTERFACE, *PLEGACY_DEVICE_DETECTION_INTERFACE; + + /* FIXME : These definitions don't exist in public headers */ + + #define PCI_CB_INTRF_VERSION 1 + #define PCI_PME_INTRF_STANDARD_VER 1 + #define PNP_LOCATION_INTERFACE_VERSION 1 + + DEFINE_GUID(GUID_PCI_CARDBUS_INTERFACE_PRIVATE, 0xcca82f31, 0x54d6, 0x11d1, 0x82, 0x24, 0x00, 0xa0, 0xc9, 0x32, 0x43, 0x85); + DEFINE_GUID(GUID_PCI_PME_INTERFACE, 0xaac7e6ac, 0xbb0b, 0x11d2, 0xb4, 0x84, 0x00, 0xc0, 0x4f, 0x72, 0xde, 0x8b); + + typedef NTSTATUS + (NTAPI *PCARDBUSADD)( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PVOID *DeviceContext); + + typedef NTSTATUS + (NTAPI *PCARDBUSDELETE)( + IN PVOID DeviceContext); + + typedef NTSTATUS + (NTAPI *PCARDBUSPCIDISPATCH)( + IN PVOID DeviceContext, + IN PIRP Irp); + + typedef VOID + (NTAPI *PPME_SET_PME_ENABLE)( + IN PDEVICE_OBJECT Pdo, + IN BOOLEAN PmeEnable); + + typedef VOID + (NTAPI *PPME_CLEAR_PME_STATUS)( + IN PDEVICE_OBJECT Pdo); + + typedef VOID + (NTAPI *PPME_GET_INFORMATION)( + IN PDEVICE_OBJECT Pdo, + OUT PBOOLEAN PmeCapable, + OUT PBOOLEAN PmeStatus, + OUT PBOOLEAN PmeEnable); + + typedef struct _PCI_CARDBUS_INTERFACE_PRIVATE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PDRIVER_OBJECT DriverObject; + PCARDBUSADD AddCardBus; + PCARDBUSDELETE DeleteCardBus; + PCARDBUSPCIDISPATCH DispatchPnp; + } PCI_CARDBUS_INTERFACE_PRIVATE, *PPCI_CARDBUS_INTERFACE_PRIVATE; + + typedef struct _PCI_PME_INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + PPME_GET_INFORMATION GetPmeInformation; + PPME_CLEAR_PME_STATUS ClearPmeStatus; + PPME_SET_PME_ENABLE UpdateEnable; + } PCI_PME_INTERFACE, *PPCI_PME_INTERFACE; + + /* Hardware Abstraction Layer Types */ + + typedef BOOLEAN + (NTAPI *PHAL_RESET_DISPLAY_PARAMETERS)( + _In_ ULONG Columns, + _In_ ULONG Rows); + + typedef PBUS_HANDLER + (FASTCALL *pHalHandlerForBus)( + _In_ INTERFACE_TYPE InterfaceType, + _In_ ULONG BusNumber); + + typedef VOID + (FASTCALL *pHalReferenceBusHandler)( + _In_ PBUS_HANDLER BusHandler); + + typedef enum _HAL_QUERY_INFORMATION_CLASS { + HalInstalledBusInformation, + HalProfileSourceInformation, + HalInformationClassUnused1, + HalPowerInformation, + HalProcessorSpeedInformation, + HalCallbackInformation, + HalMapRegisterInformation, + HalMcaLogInformation, + HalFrameBufferCachingInformation, + HalDisplayBiosInformation, + HalProcessorFeatureInformation, + HalNumaTopologyInterface, + HalErrorInformation, + HalCmcLogInformation, + HalCpeLogInformation, + HalQueryMcaInterface, + HalQueryAMLIIllegalIOPortAddresses, + HalQueryMaxHotPlugMemoryAddress, + HalPartitionIpiInterface, + HalPlatformInformation, + HalQueryProfileSourceList, + HalInitLogInformation, + HalFrequencyInformation, + HalProcessorBrandString, + HalHypervisorInformation, + HalPlatformTimerInformation, + HalAcpiAuditInformation + } HAL_QUERY_INFORMATION_CLASS, *PHAL_QUERY_INFORMATION_CLASS; + + typedef enum _HAL_SET_INFORMATION_CLASS { + HalProfileSourceInterval, + HalProfileSourceInterruptHandler, + HalMcaRegisterDriver, + HalKernelErrorHandler, + HalCmcRegisterDriver, + HalCpeRegisterDriver, + HalMcaLog, + HalCmcLog, + HalCpeLog, + HalGenerateCmcInterrupt, + HalProfileSourceTimerHandler, + HalEnlightenment, + HalProfileDpgoSourceInterruptHandler + } HAL_SET_INFORMATION_CLASS, *PHAL_SET_INFORMATION_CLASS; + + typedef NTSTATUS + (NTAPI *pHalQuerySystemInformation)( + _In_ HAL_QUERY_INFORMATION_CLASS InformationClass, + _In_ ULONG BufferSize, + _Inout_updates_bytes_to_(BufferSize, *ReturnedLength) PVOID Buffer, + _Out_ PULONG ReturnedLength); + + typedef NTSTATUS + (NTAPI *pHalSetSystemInformation)( + _In_ HAL_SET_INFORMATION_CLASS InformationClass, + _In_ ULONG BufferSize, + _In_ PVOID Buffer); + + typedef VOID + (FASTCALL *pHalExamineMBR)( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG MBRTypeIdentifier, + _Out_ PVOID *Buffer); + + typedef NTSTATUS + (FASTCALL *pHalIoReadPartitionTable)( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ BOOLEAN ReturnRecognizedPartitions, + _Out_ struct _DRIVE_LAYOUT_INFORMATION **PartitionBuffer); + + typedef NTSTATUS + (FASTCALL *pHalIoSetPartitionInformation)( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _In_ ULONG PartitionType); + + typedef NTSTATUS + (FASTCALL *pHalIoWritePartitionTable)( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG SectorsPerTrack, + _In_ ULONG NumberOfHeads, + _In_ struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer); + + typedef NTSTATUS + (NTAPI *pHalQueryBusSlots)( + _In_ PBUS_HANDLER BusHandler, + _In_ ULONG BufferSize, + _Out_ PULONG SlotNumbers, + _Out_ PULONG ReturnedLength); + + typedef NTSTATUS + (NTAPI *pHalInitPnpDriver)(VOID); + + typedef struct _PM_DISPATCH_TABLE { + ULONG Signature; + ULONG Version; + PVOID Function[1]; + } PM_DISPATCH_TABLE, *PPM_DISPATCH_TABLE; + + typedef NTSTATUS + (NTAPI *pHalInitPowerManagement)( + _In_ PPM_DISPATCH_TABLE PmDriverDispatchTable, + _Out_ PPM_DISPATCH_TABLE *PmHalDispatchTable); + + typedef struct _DMA_ADAPTER* + (NTAPI *pHalGetDmaAdapter)( + _In_ PVOID Context, + _In_ struct _DEVICE_DESCRIPTION *DeviceDescriptor, + _Out_ PULONG NumberOfMapRegisters); + + typedef NTSTATUS + (NTAPI *pHalGetInterruptTranslator)( + _In_ INTERFACE_TYPE ParentInterfaceType, + _In_ ULONG ParentBusNumber, + _In_ INTERFACE_TYPE BridgeInterfaceType, + _In_ USHORT Size, + _In_ USHORT Version, + _Out_ PTRANSLATOR_INTERFACE Translator, + _Out_ PULONG BridgeBusNumber); + + typedef NTSTATUS + (NTAPI *pHalStartMirroring)(VOID); + + typedef NTSTATUS + (NTAPI *pHalEndMirroring)( + _In_ ULONG PassNumber); + + typedef NTSTATUS + (NTAPI *pHalMirrorPhysicalMemory)( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ LARGE_INTEGER NumberOfBytes); + + typedef NTSTATUS + (NTAPI *pHalMirrorVerify)( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ LARGE_INTEGER NumberOfBytes); + + typedef BOOLEAN + (NTAPI *pHalTranslateBusAddress)( + _In_ INTERFACE_TYPE InterfaceType, + _In_ ULONG BusNumber, + _In_ PHYSICAL_ADDRESS BusAddress, + _Inout_ PULONG AddressSpace, + _Out_ PPHYSICAL_ADDRESS TranslatedAddress); + + typedef NTSTATUS + (NTAPI *pHalAssignSlotResources)( + _In_ PUNICODE_STRING RegistryPath, + _In_opt_ PUNICODE_STRING DriverClassName, + _In_ PDRIVER_OBJECT DriverObject, + _In_ PDEVICE_OBJECT DeviceObject, + _In_ INTERFACE_TYPE BusType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _Inout_ PCM_RESOURCE_LIST *AllocatedResources); + + typedef VOID + (NTAPI *pHalHaltSystem)(VOID); + + typedef BOOLEAN + (NTAPI *pHalResetDisplay)(VOID); + + typedef struct _MAP_REGISTER_ENTRY { + PVOID MapRegister; + BOOLEAN WriteToDevice; + } MAP_REGISTER_ENTRY, *PMAP_REGISTER_ENTRY; + + typedef UCHAR + (NTAPI *pHalVectorToIDTEntry)( + ULONG Vector); + + typedef BOOLEAN + (NTAPI *pHalFindBusAddressTranslation)( + _In_ PHYSICAL_ADDRESS BusAddress, + _Inout_ PULONG AddressSpace, + _Out_ PPHYSICAL_ADDRESS TranslatedAddress, + _Inout_ PULONG_PTR Context, + _In_ BOOLEAN NextBus); + + typedef VOID + (NTAPI *pHalEndOfBoot)(VOID); + + typedef PVOID + (NTAPI *pHalGetAcpiTable)( + _In_ ULONG Signature, + _In_opt_ PCSTR OemId, + _In_opt_ PCSTR OemTableId); + + #if defined(_IA64_) + typedef NTSTATUS + (*pHalGetErrorCapList)( + _Inout_ PULONG CapsListLength, + _Inout_updates_bytes_(*CapsListLength) PUCHAR ErrorCapList); + + typedef NTSTATUS + (*pHalInjectError)( + _In_ ULONG BufferLength, + _In_reads_bytes_(BufferLength) PUCHAR Buffer); + #endif + + typedef VOID + (NTAPI *PCI_ERROR_HANDLER_CALLBACK)(VOID); + + typedef VOID + (NTAPI *pHalSetPciErrorHandlerCallback)( + _In_ PCI_ERROR_HANDLER_CALLBACK Callback); + + #if 1 /* Not present in WDK 7600 */ + typedef VOID + (FASTCALL *pHalIoAssignDriveLetters)( + _In_ struct _LOADER_PARAMETER_BLOCK *LoaderBlock, + _In_ PSTRING NtDeviceName, + _Out_ PUCHAR NtSystemPath, + _Out_ PSTRING NtSystemPathString); + #endif + + typedef struct { + ULONG Version; + pHalQuerySystemInformation HalQuerySystemInformation; + pHalSetSystemInformation HalSetSystemInformation; + pHalQueryBusSlots HalQueryBusSlots; + ULONG Spare1; + pHalExamineMBR HalExamineMBR; + #if 1 /* Not present in WDK 7600 */ + pHalIoAssignDriveLetters HalIoAssignDriveLetters; + #endif + pHalIoReadPartitionTable HalIoReadPartitionTable; + pHalIoSetPartitionInformation HalIoSetPartitionInformation; + pHalIoWritePartitionTable HalIoWritePartitionTable; + pHalHandlerForBus HalReferenceHandlerForBus; + pHalReferenceBusHandler HalReferenceBusHandler; + pHalReferenceBusHandler HalDereferenceBusHandler; + pHalInitPnpDriver HalInitPnpDriver; + pHalInitPowerManagement HalInitPowerManagement; + pHalGetDmaAdapter HalGetDmaAdapter; + pHalGetInterruptTranslator HalGetInterruptTranslator; + pHalStartMirroring HalStartMirroring; + pHalEndMirroring HalEndMirroring; + pHalMirrorPhysicalMemory HalMirrorPhysicalMemory; + pHalEndOfBoot HalEndOfBoot; + pHalMirrorVerify HalMirrorVerify; + pHalGetAcpiTable HalGetCachedAcpiTable; + pHalSetPciErrorHandlerCallback HalSetPciErrorHandlerCallback; + #if defined(_IA64_) + pHalGetErrorCapList HalGetErrorCapList; + pHalInjectError HalInjectError; + #endif + } HAL_DISPATCH, *PHAL_DISPATCH; + + /* GCC/MSVC and WDK compatible declaration */ + extern NTKERNELAPI HAL_DISPATCH HalDispatchTable; + + #if defined(_NTOSKRNL_) || defined(_BLDR_) + #define HALDISPATCH (&HalDispatchTable) + #else + /* This is a WDK compatibility definition */ + #define HalDispatchTable (&HalDispatchTable) + #define HALDISPATCH HalDispatchTable + #endif + + #define HAL_DISPATCH_VERSION 3 /* FIXME: when to use 4? */ + #define HalDispatchTableVersion HALDISPATCH->Version + #define HalQuerySystemInformation HALDISPATCH->HalQuerySystemInformation + #define HalSetSystemInformation HALDISPATCH->HalSetSystemInformation + #define HalQueryBusSlots HALDISPATCH->HalQueryBusSlots + #define HalReferenceHandlerForBus HALDISPATCH->HalReferenceHandlerForBus + #define HalReferenceBusHandler HALDISPATCH->HalReferenceBusHandler + #define HalDereferenceBusHandler HALDISPATCH->HalDereferenceBusHandler + #define HalInitPnpDriver HALDISPATCH->HalInitPnpDriver + #define HalInitPowerManagement HALDISPATCH->HalInitPowerManagement + #define HalGetDmaAdapter HALDISPATCH->HalGetDmaAdapter + #define HalGetInterruptTranslator HALDISPATCH->HalGetInterruptTranslator + #define HalStartMirroring HALDISPATCH->HalStartMirroring + #define HalEndMirroring HALDISPATCH->HalEndMirroring + #define HalMirrorPhysicalMemory HALDISPATCH->HalMirrorPhysicalMemory + #define HalEndOfBoot HALDISPATCH->HalEndOfBoot + #define HalMirrorVerify HALDISPATCH->HalMirrorVerify + #define HalGetCachedAcpiTable HALDISPATCH->HalGetCachedAcpiTable + #define HalSetPciErrorHandlerCallback HALDISPATCH->HalSetPciErrorHandlerCallback + #if defined(_IA64_) + #define HalGetErrorCapList HALDISPATCH->HalGetErrorCapList + #define HalInjectError HALDISPATCH->HalInjectError + #endif + + typedef struct _HAL_BUS_INFORMATION { + INTERFACE_TYPE BusType; + BUS_DATA_TYPE ConfigurationType; + ULONG BusNumber; + ULONG Reserved; + } HAL_BUS_INFORMATION, *PHAL_BUS_INFORMATION; + + typedef struct _HAL_PROFILE_SOURCE_INFORMATION { + KPROFILE_SOURCE Source; + BOOLEAN Supported; + ULONG Interval; + } HAL_PROFILE_SOURCE_INFORMATION, *PHAL_PROFILE_SOURCE_INFORMATION; + + typedef struct _HAL_PROFILE_SOURCE_INFORMATION_EX { + KPROFILE_SOURCE Source; + BOOLEAN Supported; + ULONG_PTR Interval; + ULONG_PTR DefInterval; + ULONG_PTR MaxInterval; + ULONG_PTR MinInterval; + } HAL_PROFILE_SOURCE_INFORMATION_EX, *PHAL_PROFILE_SOURCE_INFORMATION_EX; + + typedef struct _HAL_PROFILE_SOURCE_INTERVAL { + KPROFILE_SOURCE Source; + ULONG_PTR Interval; + } HAL_PROFILE_SOURCE_INTERVAL, *PHAL_PROFILE_SOURCE_INTERVAL; + + typedef struct _HAL_PROFILE_SOURCE_LIST { + KPROFILE_SOURCE Source; + PWSTR Description; + } HAL_PROFILE_SOURCE_LIST, *PHAL_PROFILE_SOURCE_LIST; + + typedef enum _HAL_DISPLAY_BIOS_INFORMATION { + HalDisplayInt10Bios, + HalDisplayEmulatedBios, + HalDisplayNoBios + } HAL_DISPLAY_BIOS_INFORMATION, *PHAL_DISPLAY_BIOS_INFORMATION; + + typedef struct _HAL_POWER_INFORMATION { + ULONG TBD; + } HAL_POWER_INFORMATION, *PHAL_POWER_INFORMATION; + + typedef struct _HAL_PROCESSOR_SPEED_INFO { + ULONG ProcessorSpeed; + } HAL_PROCESSOR_SPEED_INFORMATION, *PHAL_PROCESSOR_SPEED_INFORMATION; + + typedef struct _HAL_CALLBACKS { + PCALLBACK_OBJECT SetSystemInformation; + PCALLBACK_OBJECT BusCheck; + } HAL_CALLBACKS, *PHAL_CALLBACKS; + + typedef struct _HAL_PROCESSOR_FEATURE { + ULONG UsableFeatureBits; + } HAL_PROCESSOR_FEATURE; + + typedef NTSTATUS + (NTAPI *PHALIOREADWRITEHANDLER)( + _In_ BOOLEAN fRead, + _In_ ULONG dwAddr, + _In_ ULONG dwSize, + _Inout_ PULONG pdwData); + + typedef struct _HAL_AMLI_BAD_IO_ADDRESS_LIST { + ULONG BadAddrBegin; + ULONG BadAddrSize; + ULONG OSVersionTrigger; + PHALIOREADWRITEHANDLER IOHandler; + } HAL_AMLI_BAD_IO_ADDRESS_LIST, *PHAL_AMLI_BAD_IO_ADDRESS_LIST; + + #if defined(_X86_) || defined(_IA64_) || defined(_AMD64_) + + typedef VOID + (NTAPI *PHALMCAINTERFACELOCK)(VOID); + + typedef VOID + (NTAPI *PHALMCAINTERFACEUNLOCK)(VOID); + + typedef NTSTATUS + (NTAPI *PHALMCAINTERFACEREADREGISTER)( + _In_ UCHAR BankNumber, + _Inout_ PVOID Exception); + + typedef struct _HAL_MCA_INTERFACE { + PHALMCAINTERFACELOCK Lock; + PHALMCAINTERFACEUNLOCK Unlock; + PHALMCAINTERFACEREADREGISTER ReadRegister; + } HAL_MCA_INTERFACE; + + typedef enum { + ApicDestinationModePhysical = 1, + ApicDestinationModeLogicalFlat, + ApicDestinationModeLogicalClustered, + ApicDestinationModeUnknown + } HAL_APIC_DESTINATION_MODE, *PHAL_APIC_DESTINATION_MODE; + + #if defined(_AMD64_) + + struct _KTRAP_FRAME; + struct _KEXCEPTION_FRAME; + + typedef ERROR_SEVERITY + (NTAPI *PDRIVER_EXCPTN_CALLBACK)( + _In_ PVOID Context, + _In_ struct _KTRAP_FRAME *TrapFrame, + _In_ struct _KEXCEPTION_FRAME *ExceptionFrame, + _In_ PMCA_EXCEPTION Exception); + + #endif + + #if defined(_X86_) || defined(_IA64_) + typedef + #if defined(_IA64_) + ERROR_SEVERITY + #else + VOID + #endif + (NTAPI *PDRIVER_EXCPTN_CALLBACK)( + _In_ PVOID Context, + _In_ PMCA_EXCEPTION BankLog); + #endif + + typedef PDRIVER_EXCPTN_CALLBACK PDRIVER_MCA_EXCEPTION_CALLBACK; + + typedef struct _MCA_DRIVER_INFO { + PDRIVER_MCA_EXCEPTION_CALLBACK ExceptionCallback; + PKDEFERRED_ROUTINE DpcCallback; + PVOID DeviceContext; + } MCA_DRIVER_INFO, *PMCA_DRIVER_INFO; + + typedef struct _HAL_ERROR_INFO { + ULONG Version; + ULONG InitMaxSize; + ULONG McaMaxSize; + ULONG McaPreviousEventsCount; + ULONG McaCorrectedEventsCount; + ULONG McaKernelDeliveryFails; + ULONG McaDriverDpcQueueFails; + ULONG McaReserved; + ULONG CmcMaxSize; + ULONG CmcPollingInterval; + ULONG CmcInterruptsCount; + ULONG CmcKernelDeliveryFails; + ULONG CmcDriverDpcQueueFails; + ULONG CmcGetStateFails; + ULONG CmcClearStateFails; + ULONG CmcReserved; + ULONGLONG CmcLogId; + ULONG CpeMaxSize; + ULONG CpePollingInterval; + ULONG CpeInterruptsCount; + ULONG CpeKernelDeliveryFails; + ULONG CpeDriverDpcQueueFails; + ULONG CpeGetStateFails; + ULONG CpeClearStateFails; + ULONG CpeInterruptSources; + ULONGLONG CpeLogId; + ULONGLONG KernelReserved[4]; + } HAL_ERROR_INFO, *PHAL_ERROR_INFO; + + #define HAL_MCE_INTERRUPTS_BASED ((ULONG)-1) + #define HAL_MCE_DISABLED ((ULONG)0) + + #define HAL_CMC_INTERRUPTS_BASED HAL_MCE_INTERRUPTS_BASED + #define HAL_CMC_DISABLED HAL_MCE_DISABLED + + #define HAL_CPE_INTERRUPTS_BASED HAL_MCE_INTERRUPTS_BASED + #define HAL_CPE_DISABLED HAL_MCE_DISABLED + + #define HAL_MCA_INTERRUPTS_BASED HAL_MCE_INTERRUPTS_BASED + #define HAL_MCA_DISABLED HAL_MCE_DISABLED + + typedef VOID + (NTAPI *PDRIVER_CMC_EXCEPTION_CALLBACK)( + _In_ PVOID Context, + _In_ PCMC_EXCEPTION CmcLog); + + typedef VOID + (NTAPI *PDRIVER_CPE_EXCEPTION_CALLBACK)( + _In_ PVOID Context, + _In_ PCPE_EXCEPTION CmcLog); + + typedef struct _CMC_DRIVER_INFO { + PDRIVER_CMC_EXCEPTION_CALLBACK ExceptionCallback; + PKDEFERRED_ROUTINE DpcCallback; + PVOID DeviceContext; + } CMC_DRIVER_INFO, *PCMC_DRIVER_INFO; + + typedef struct _CPE_DRIVER_INFO { + PDRIVER_CPE_EXCEPTION_CALLBACK ExceptionCallback; + PKDEFERRED_ROUTINE DpcCallback; + PVOID DeviceContext; + } CPE_DRIVER_INFO, *PCPE_DRIVER_INFO; + + #endif // defined(_X86_) || defined(_IA64_) || defined(_AMD64_) + + #if defined(_IA64_) + + typedef NTSTATUS + (*HALSENDCROSSPARTITIONIPI)( + _In_ USHORT ProcessorID, + _In_ UCHAR HardwareVector); + + typedef NTSTATUS + (*HALRESERVECROSSPARTITIONINTERRUPTVECTOR)( + _Out_ PULONG Vector, + _Out_ PKIRQL Irql, + _Inout_ PGROUP_AFFINITY Affinity, + _Out_ PUCHAR HardwareVector); + + typedef VOID + (*HALFREECROSSPARTITIONINTERRUPTVECTOR)( + _In_ ULONG Vector, + _In_ PGROUP_AFFINITY Affinity); + + typedef struct _HAL_CROSS_PARTITION_IPI_INTERFACE { + HALSENDCROSSPARTITIONIPI HalSendCrossPartitionIpi; + HALRESERVECROSSPARTITIONINTERRUPTVECTOR HalReserveCrossPartitionInterruptVector; + HALFREECROSSPARTITIONINTERRUPTVECTOR HalFreeCrossPartitionInterruptVector; + } HAL_CROSS_PARTITION_IPI_INTERFACE; + + #define HAL_CROSS_PARTITION_IPI_INTERFACE_MINIMUM_SIZE \ + FIELD_OFFSET(HAL_CROSS_PARTITION_IPI_INTERFACE, \ + HalFreeCrossPartitionInterruptVector) + + #endif /* defined(_IA64_) */ + + typedef struct _HAL_PLATFORM_INFORMATION { + ULONG PlatformFlags; + } HAL_PLATFORM_INFORMATION, *PHAL_PLATFORM_INFORMATION; + + #define HAL_PLATFORM_DISABLE_WRITE_COMBINING 0x01L + #define HAL_PLATFORM_DISABLE_PTCG 0x04L + #define HAL_PLATFORM_DISABLE_UC_MAIN_MEMORY 0x08L + #define HAL_PLATFORM_ENABLE_WRITE_COMBINING_MMIO 0x10L + #define HAL_PLATFORM_ACPI_TABLES_CACHED 0x20L + + /****************************************************************************** + * Kernel Types * + ******************************************************************************/ + + #define NX_SUPPORT_POLICY_ALWAYSOFF 0 + #define NX_SUPPORT_POLICY_ALWAYSON 1 + #define NX_SUPPORT_POLICY_OPTIN 2 + #define NX_SUPPORT_POLICY_OPTOUT 3 + + _IRQL_requires_same_ + _Function_class_(EXPAND_STACK_CALLOUT) + typedef VOID + (NTAPI EXPAND_STACK_CALLOUT)( + _In_opt_ PVOID Parameter); + typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT; + + typedef VOID + (NTAPI *PTIMER_APC_ROUTINE)( + _In_ PVOID TimerContext, + _In_ ULONG TimerLowValue, + _In_ LONG TimerHighValue); + + typedef enum _TIMER_SET_INFORMATION_CLASS { + TimerSetCoalescableTimer, + MaxTimerInfoClass + } TIMER_SET_INFORMATION_CLASS; + + #if (NTDDI_VERSION >= NTDDI_WIN7) + typedef struct _TIMER_SET_COALESCABLE_TIMER_INFO { + _In_ LARGE_INTEGER DueTime; + _In_opt_ PTIMER_APC_ROUTINE TimerApcRoutine; + _In_opt_ PVOID TimerContext; + _In_opt_ struct _COUNTED_REASON_CONTEXT *WakeContext; + _In_opt_ ULONG Period; + _In_ ULONG TolerableDelay; + _Out_opt_ PBOOLEAN PreviousState; + } TIMER_SET_COALESCABLE_TIMER_INFO, *PTIMER_SET_COALESCABLE_TIMER_INFO; + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + #define XSTATE_LEGACY_FLOATING_POINT 0 + #define XSTATE_LEGACY_SSE 1 + #define XSTATE_GSSE 2 + + #define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64 << (XSTATE_LEGACY_FLOATING_POINT)) + #define XSTATE_MASK_LEGACY_SSE (1i64 << (XSTATE_LEGACY_SSE)) + #define XSTATE_MASK_LEGACY (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE) + #define XSTATE_MASK_GSSE (1i64 << (XSTATE_GSSE)) + + #define MAXIMUM_XSTATE_FEATURES 64 + + typedef struct _XSTATE_FEATURE { + ULONG Offset; + ULONG Size; + } XSTATE_FEATURE, *PXSTATE_FEATURE; + + typedef struct _XSTATE_CONFIGURATION { + ULONG64 EnabledFeatures; + ULONG Size; + ULONG OptimizedSave:1; + XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES]; + } XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; + + #define MAX_WOW64_SHARED_ENTRIES 16 + + typedef struct _KUSER_SHARED_DATA { + ULONG TickCountLowDeprecated; + ULONG TickCountMultiplier; + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + WCHAR NtSystemRoot[260]; + ULONG MaxStackTraceDepth; + ULONG CryptoExponent; + ULONG TimeZoneId; + ULONG LargePageMinimum; + ULONG Reserved2[7]; + NT_PRODUCT_TYPE NtProductType; + BOOLEAN ProductTypeIsValid; + ULONG NtMajorVersion; + ULONG NtMinorVersion; + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; + ULONG Reserved1; + ULONG Reserved3; + volatile ULONG TimeSlip; + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + ULONG AltArchitecturePad[1]; + LARGE_INTEGER SystemExpirationDate; + ULONG SuiteMask; + BOOLEAN KdDebuggerEnabled; + #if (NTDDI_VERSION >= NTDDI_WINXPSP2) + UCHAR NXSupportPolicy; + #endif + volatile ULONG ActiveConsoleId; + volatile ULONG DismountCount; + ULONG ComPlusPackage; + ULONG LastSystemRITEventTickCount; + ULONG NumberOfPhysicalPages; + BOOLEAN SafeBootMode; + #if (NTDDI_VERSION >= NTDDI_WIN7) + _ANONYMOUS_UNION union { + UCHAR TscQpcData; + _ANONYMOUS_STRUCT struct { + UCHAR TscQpcEnabled:1; + UCHAR TscQpcSpareFlag:1; + UCHAR TscQpcShift:6; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + UCHAR TscQpcPad[2]; + #endif + #if (NTDDI_VERSION >= NTDDI_VISTA) + _ANONYMOUS_UNION union { + ULONG SharedDataFlags; + _ANONYMOUS_STRUCT struct { + ULONG DbgErrorPortPresent:1; + ULONG DbgElevationEnabled:1; + ULONG DbgVirtEnabled:1; + ULONG DbgInstallerDetectEnabled:1; + ULONG DbgSystemDllRelocated:1; + ULONG DbgDynProcessorEnabled:1; + ULONG DbgSEHValidationEnabled:1; + ULONG SpareBits:25; + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME2; + #else + ULONG TraceLogging; + #endif + ULONG DataFlagsPad[1]; + ULONGLONG TestRetInstruction; + ULONG SystemCall; + ULONG SystemCallReturn; + ULONGLONG SystemCallPad[3]; + _ANONYMOUS_UNION union { + volatile KSYSTEM_TIME TickCount; + volatile ULONG64 TickCountQuad; + _ANONYMOUS_STRUCT struct { + ULONG ReservedTickCountOverlay[3]; + ULONG TickCountPad[1]; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME3; + ULONG Cookie; + ULONG CookiePad[1]; + #if (NTDDI_VERSION >= NTDDI_WS03) + LONGLONG ConsoleSessionForegroundProcessId; + ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES]; + #endif + #if (NTDDI_VERSION >= NTDDI_VISTA) + #if (NTDDI_VERSION >= NTDDI_WIN7) + USHORT UserModeGlobalLogger[16]; + #else + USHORT UserModeGlobalLogger[8]; + ULONG HeapTracingPid[2]; + ULONG CritSecTracingPid[2]; + #endif + ULONG ImageFileExecutionOptions; + #if (NTDDI_VERSION >= NTDDI_VISTASP1) + ULONG LangGenerationCount; + #else + /* 4 bytes padding */ + #endif + ULONGLONG Reserved5; + volatile ULONG64 InterruptTimeBias; + #endif + #if (NTDDI_VERSION >= NTDDI_WIN7) + volatile ULONG64 TscQpcBias; + volatile ULONG ActiveProcessorCount; + volatile USHORT ActiveGroupCount; + USHORT Reserved4; + volatile ULONG AitSamplingValue; + volatile ULONG AppCompatFlag; + ULONGLONG SystemDllNativeRelocation; + ULONG SystemDllWowRelocation; + ULONG XStatePad[1]; + XSTATE_CONFIGURATION XState; + #endif + } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; + + #if (NTDDI_VERSION >= NTDDI_VISTA) + extern NTSYSAPI volatile CCHAR KeNumberProcessors; + #elif (NTDDI_VERSION >= NTDDI_WINXP) + extern NTSYSAPI CCHAR KeNumberProcessors; + #else + extern PCCHAR KeNumberProcessors; + #endif + + + /****************************************************************************** + * Kernel Debugger Types * + ******************************************************************************/ + typedef struct _DEBUG_DEVICE_ADDRESS { + UCHAR Type; + BOOLEAN Valid; + UCHAR Reserved[2]; + PUCHAR TranslatedAddress; + ULONG Length; + } DEBUG_DEVICE_ADDRESS, *PDEBUG_DEVICE_ADDRESS; + + typedef struct _DEBUG_MEMORY_REQUIREMENTS { + PHYSICAL_ADDRESS Start; + PHYSICAL_ADDRESS MaxEnd; + PVOID VirtualAddress; + ULONG Length; + BOOLEAN Cached; + BOOLEAN Aligned; + } DEBUG_MEMORY_REQUIREMENTS, *PDEBUG_MEMORY_REQUIREMENTS; + + typedef struct _DEBUG_DEVICE_DESCRIPTOR { + ULONG Bus; + ULONG Slot; + USHORT Segment; + USHORT VendorID; + USHORT DeviceID; + UCHAR BaseClass; + UCHAR SubClass; + UCHAR ProgIf; + BOOLEAN Initialized; + BOOLEAN Configured; + DEBUG_DEVICE_ADDRESS BaseAddress[6]; + DEBUG_MEMORY_REQUIREMENTS Memory; + } DEBUG_DEVICE_DESCRIPTOR, *PDEBUG_DEVICE_DESCRIPTOR; + + typedef NTSTATUS + (NTAPI *pKdSetupPciDeviceForDebugging)( + _In_opt_ PVOID LoaderBlock, + _Inout_ PDEBUG_DEVICE_DESCRIPTOR PciDevice); + + typedef NTSTATUS + (NTAPI *pKdReleasePciDeviceForDebugging)( + _Inout_ PDEBUG_DEVICE_DESCRIPTOR PciDevice); + + typedef PVOID + (NTAPI *pKdGetAcpiTablePhase0)( + _In_ struct _LOADER_PARAMETER_BLOCK *LoaderBlock, + _In_ ULONG Signature); + + typedef VOID + (NTAPI *pKdCheckPowerButton)(VOID); + + #if (NTDDI_VERSION >= NTDDI_VISTA) + typedef PVOID + (NTAPI *pKdMapPhysicalMemory64)( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG NumberPages, + _In_ BOOLEAN FlushCurrentTLB); + + typedef VOID + (NTAPI *pKdUnmapVirtualAddress)( + _In_ PVOID VirtualAddress, + _In_ ULONG NumberPages, + _In_ BOOLEAN FlushCurrentTLB); + #else + typedef PVOID + (NTAPI *pKdMapPhysicalMemory64)( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ ULONG NumberPages); + + typedef VOID + (NTAPI *pKdUnmapVirtualAddress)( + _In_ PVOID VirtualAddress, + _In_ ULONG NumberPages); + #endif + + typedef ULONG + (NTAPI *pKdGetPciDataByOffset)( + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _Out_writes_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + + typedef ULONG + (NTAPI *pKdSetPciDataByOffset)( + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _In_reads_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + /****************************************************************************** + * Memory manager Types * + ******************************************************************************/ + + typedef struct _PHYSICAL_MEMORY_RANGE { + PHYSICAL_ADDRESS BaseAddress; + LARGE_INTEGER NumberOfBytes; + } PHYSICAL_MEMORY_RANGE, *PPHYSICAL_MEMORY_RANGE; + + typedef NTSTATUS + (NTAPI *PMM_ROTATE_COPY_CALLBACK_FUNCTION)( + _In_ PMDL DestinationMdl, + _In_ PMDL SourceMdl, + _In_ PVOID Context); + + typedef enum _MM_ROTATE_DIRECTION { + MmToFrameBuffer, + MmToFrameBufferNoCopy, + MmToRegularMemory, + MmToRegularMemoryNoCopy, + MmMaximumRotateDirection + } MM_ROTATE_DIRECTION, *PMM_ROTATE_DIRECTION; + + + /****************************************************************************** + * Process Manager Types * + ******************************************************************************/ + + #define QUOTA_LIMITS_HARDWS_MIN_ENABLE 0x00000001 + #define QUOTA_LIMITS_HARDWS_MIN_DISABLE 0x00000002 + #define QUOTA_LIMITS_HARDWS_MAX_ENABLE 0x00000004 + #define QUOTA_LIMITS_HARDWS_MAX_DISABLE 0x00000008 + #define QUOTA_LIMITS_USE_DEFAULT_LIMITS 0x00000010 + + typedef struct _QUOTA_LIMITS { + SIZE_T PagedPoolLimit; + SIZE_T NonPagedPoolLimit; + SIZE_T MinimumWorkingSetSize; + SIZE_T MaximumWorkingSetSize; + SIZE_T PagefileLimit; + LARGE_INTEGER TimeLimit; + } QUOTA_LIMITS, *PQUOTA_LIMITS; + + typedef union _RATE_QUOTA_LIMIT { + ULONG RateData; + _ANONYMOUS_STRUCT struct { + ULONG RatePercent:7; + ULONG Reserved0:25; + } DUMMYSTRUCTNAME; + } RATE_QUOTA_LIMIT, *PRATE_QUOTA_LIMIT; + + typedef struct _QUOTA_LIMITS_EX { + SIZE_T PagedPoolLimit; + SIZE_T NonPagedPoolLimit; + SIZE_T MinimumWorkingSetSize; + SIZE_T MaximumWorkingSetSize; + SIZE_T PagefileLimit; + LARGE_INTEGER TimeLimit; + SIZE_T WorkingSetLimit; + SIZE_T Reserved2; + SIZE_T Reserved3; + SIZE_T Reserved4; + ULONG Flags; + RATE_QUOTA_LIMIT CpuRateLimit; + } QUOTA_LIMITS_EX, *PQUOTA_LIMITS_EX; + + typedef struct _IO_COUNTERS { + ULONGLONG ReadOperationCount; + ULONGLONG WriteOperationCount; + ULONGLONG OtherOperationCount; + ULONGLONG ReadTransferCount; + ULONGLONG WriteTransferCount; + ULONGLONG OtherTransferCount; + } IO_COUNTERS, *PIO_COUNTERS; + + typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + } VM_COUNTERS, *PVM_COUNTERS; + + typedef struct _VM_COUNTERS_EX { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; + } VM_COUNTERS_EX, *PVM_COUNTERS_EX; + + #define MAX_HW_COUNTERS 16 + #define THREAD_PROFILING_FLAG_DISPATCH 0x00000001 + + typedef enum _HARDWARE_COUNTER_TYPE { + PMCCounter, + MaxHardwareCounterType + } HARDWARE_COUNTER_TYPE, *PHARDWARE_COUNTER_TYPE; + + typedef struct _HARDWARE_COUNTER { + HARDWARE_COUNTER_TYPE Type; + ULONG Reserved; + ULONG64 Index; + } HARDWARE_COUNTER, *PHARDWARE_COUNTER; + + typedef struct _POOLED_USAGE_AND_LIMITS { + SIZE_T PeakPagedPoolUsage; + SIZE_T PagedPoolUsage; + SIZE_T PagedPoolLimit; + SIZE_T PeakNonPagedPoolUsage; + SIZE_T NonPagedPoolUsage; + SIZE_T NonPagedPoolLimit; + SIZE_T PeakPagefileUsage; + SIZE_T PagefileUsage; + SIZE_T PagefileLimit; + } POOLED_USAGE_AND_LIMITS, *PPOOLED_USAGE_AND_LIMITS; + + typedef struct _PROCESS_ACCESS_TOKEN { + HANDLE Token; + HANDLE Thread; + } PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN; + + #define PROCESS_EXCEPTION_PORT_ALL_STATE_BITS 0x00000003UL + #define PROCESS_EXCEPTION_PORT_ALL_STATE_FLAGS ((ULONG_PTR)((1UL << PROCESS_EXCEPTION_PORT_ALL_STATE_BITS) - 1)) + + typedef struct _PROCESS_EXCEPTION_PORT { + _In_ HANDLE ExceptionPortHandle; + _Inout_ ULONG StateFlags; + } PROCESS_EXCEPTION_PORT, *PPROCESS_EXCEPTION_PORT; + + typedef VOID + (NTAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)( + _In_ HANDLE ParentId, + _In_ HANDLE ProcessId, + _In_ BOOLEAN Create); + + typedef struct _PS_CREATE_NOTIFY_INFO { + _In_ SIZE_T Size; + _ANONYMOUS_UNION union { + _In_ ULONG Flags; + _ANONYMOUS_STRUCT struct { + _In_ ULONG FileOpenNameAvailable:1; + _In_ ULONG Reserved:31; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + _In_ HANDLE ParentProcessId; + _In_ CLIENT_ID CreatingThreadId; + _Inout_ struct _FILE_OBJECT *FileObject; + _In_ PCUNICODE_STRING ImageFileName; + _In_opt_ PCUNICODE_STRING CommandLine; + _Inout_ NTSTATUS CreationStatus; + } PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO; + + typedef VOID + (NTAPI *PCREATE_PROCESS_NOTIFY_ROUTINE_EX)( + _Inout_ PEPROCESS Process, + _In_ HANDLE ProcessId, + _Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo); + + typedef VOID + (NTAPI *PCREATE_THREAD_NOTIFY_ROUTINE)( + _In_ HANDLE ProcessId, + _In_ HANDLE ThreadId, + _In_ BOOLEAN Create); + + #define IMAGE_ADDRESSING_MODE_32BIT 3 + + typedef struct _IMAGE_INFO { + _ANONYMOUS_UNION union { + ULONG Properties; + _ANONYMOUS_STRUCT struct { + ULONG ImageAddressingMode:8; + ULONG SystemModeImage:1; + ULONG ImageMappedToAllPids:1; + ULONG ExtendedInfoPresent:1; + ULONG Reserved:21; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + PVOID ImageBase; + ULONG ImageSelector; + SIZE_T ImageSize; + ULONG ImageSectionNumber; + } IMAGE_INFO, *PIMAGE_INFO; + + typedef struct _IMAGE_INFO_EX { + SIZE_T Size; + IMAGE_INFO ImageInfo; + struct _FILE_OBJECT *FileObject; + } IMAGE_INFO_EX, *PIMAGE_INFO_EX; + + typedef VOID + (NTAPI *PLOAD_IMAGE_NOTIFY_ROUTINE)( + _In_ PUNICODE_STRING FullImageName, + _In_ HANDLE ProcessId, + _In_ PIMAGE_INFO ImageInfo); + + #define THREAD_CSWITCH_PMU_DISABLE FALSE + #define THREAD_CSWITCH_PMU_ENABLE TRUE + + #define PROCESS_LUID_DOSDEVICES_ONLY 0x00000001 + + #define PROCESS_HANDLE_TRACING_MAX_STACKS 16 + + typedef struct _NT_TIB { + struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; + PVOID StackBase; + PVOID StackLimit; + PVOID SubSystemTib; + _ANONYMOUS_UNION union { + PVOID FiberData; + ULONG Version; + } DUMMYUNIONNAME; + PVOID ArbitraryUserPointer; + struct _NT_TIB *Self; + } NT_TIB, *PNT_TIB; + + typedef struct _NT_TIB32 { + ULONG ExceptionList; + ULONG StackBase; + ULONG StackLimit; + ULONG SubSystemTib; + _ANONYMOUS_UNION union { + ULONG FiberData; + ULONG Version; + } DUMMYUNIONNAME; + ULONG ArbitraryUserPointer; + ULONG Self; + } NT_TIB32,*PNT_TIB32; + + typedef struct _NT_TIB64 { + ULONG64 ExceptionList; + ULONG64 StackBase; + ULONG64 StackLimit; + ULONG64 SubSystemTib; + _ANONYMOUS_UNION union { + ULONG64 FiberData; + ULONG Version; + } DUMMYUNIONNAME; + ULONG64 ArbitraryUserPointer; + ULONG64 Self; + } NT_TIB64,*PNT_TIB64; + + typedef enum _PROCESSINFOCLASS { + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessTlsInformation, + ProcessCookie, + ProcessImageInformation, + ProcessCycleTime, + ProcessPagePriority, + ProcessInstrumentationCallback, + ProcessThreadStackAllocation, + ProcessWorkingSetWatchEx, + ProcessImageFileNameWin32, + ProcessImageFileMapping, + ProcessAffinityUpdateMode, + ProcessMemoryAllocationMode, + ProcessGroupInformation, + ProcessTokenVirtualizationEnabled, + ProcessConsoleHostProcess, + ProcessWindowInformation, + MaxProcessInfoClass + } PROCESSINFOCLASS; + + typedef enum _THREADINFOCLASS { + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + ThreadSwitchLegacyState, + ThreadIsTerminated, + ThreadLastSystemCall, + ThreadIoPriority, + ThreadCycleTime, + ThreadPagePriority, + ThreadActualBasePriority, + ThreadTebInformation, + ThreadCSwitchMon, + ThreadCSwitchPmu, + ThreadWow64Context, + ThreadGroupInformation, + ThreadUmsInformation, + ThreadCounterProfiling, + ThreadIdealProcessorEx, + MaxThreadInfoClass + } THREADINFOCLASS; + + typedef struct _PAGE_PRIORITY_INFORMATION { + ULONG PagePriority; + } PAGE_PRIORITY_INFORMATION, *PPAGE_PRIORITY_INFORMATION; + + typedef struct _PROCESS_WS_WATCH_INFORMATION { + PVOID FaultingPc; + PVOID FaultingVa; + } PROCESS_WS_WATCH_INFORMATION, *PPROCESS_WS_WATCH_INFORMATION; + + typedef struct _PROCESS_BASIC_INFORMATION { + NTSTATUS ExitStatus; + struct _PEB *PebBaseAddress; + ULONG_PTR AffinityMask; + KPRIORITY BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; + } PROCESS_BASIC_INFORMATION,*PPROCESS_BASIC_INFORMATION; + + typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION { + SIZE_T Size; + PROCESS_BASIC_INFORMATION BasicInfo; + _ANONYMOUS_UNION union { + ULONG Flags; + _ANONYMOUS_STRUCT struct { + ULONG IsProtectedProcess:1; + ULONG IsWow64Process:1; + ULONG IsProcessDeleting:1; + ULONG IsCrossSessionCreate:1; + ULONG SpareBits:28; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + } PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION; + + typedef struct _PROCESS_DEVICEMAP_INFORMATION { + _ANONYMOUS_UNION union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[32]; + } Query; + } DUMMYUNIONNAME; + } PROCESS_DEVICEMAP_INFORMATION, *PPROCESS_DEVICEMAP_INFORMATION; + + typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX { + _ANONYMOUS_UNION union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[32]; + } Query; + } DUMMYUNIONNAME; + ULONG Flags; + } PROCESS_DEVICEMAP_INFORMATION_EX, *PPROCESS_DEVICEMAP_INFORMATION_EX; + + typedef struct _PROCESS_SESSION_INFORMATION { + ULONG SessionId; + } PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION; + + typedef struct _PROCESS_HANDLE_TRACING_ENABLE { + ULONG Flags; + } PROCESS_HANDLE_TRACING_ENABLE, *PPROCESS_HANDLE_TRACING_ENABLE; + + typedef struct _PROCESS_HANDLE_TRACING_ENABLE_EX { + ULONG Flags; + ULONG TotalSlots; + } PROCESS_HANDLE_TRACING_ENABLE_EX, *PPROCESS_HANDLE_TRACING_ENABLE_EX; + + typedef struct _PROCESS_HANDLE_TRACING_ENTRY { + HANDLE Handle; + CLIENT_ID ClientId; + ULONG Type; + PVOID Stacks[PROCESS_HANDLE_TRACING_MAX_STACKS]; + } PROCESS_HANDLE_TRACING_ENTRY, *PPROCESS_HANDLE_TRACING_ENTRY; + + typedef struct _PROCESS_HANDLE_TRACING_QUERY { + HANDLE Handle; + ULONG TotalTraces; + PROCESS_HANDLE_TRACING_ENTRY HandleTrace[1]; + } PROCESS_HANDLE_TRACING_QUERY, *PPROCESS_HANDLE_TRACING_QUERY; + + extern NTKERNELAPI PEPROCESS PsInitialSystemProcess; + + + /****************************************************************************** + * Runtime Library Types * + ******************************************************************************/ + + + #ifndef _RTL_RUN_ONCE_DEF + #define _RTL_RUN_ONCE_DEF + + #define RTL_RUN_ONCE_INIT {0} + + #define RTL_RUN_ONCE_CHECK_ONLY 0x00000001UL + #define RTL_RUN_ONCE_ASYNC 0x00000002UL + #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL + + #define RTL_RUN_ONCE_CTX_RESERVED_BITS 2 + + #define RTL_HASH_ALLOCATED_HEADER 0x00000001 + + #define RTL_HASH_RESERVED_SIGNATURE 0 + + /* RtlVerifyVersionInfo() ComparisonType */ + + #define VER_EQUAL 1 + #define VER_GREATER 2 + #define VER_GREATER_EQUAL 3 + #define VER_LESS 4 + #define VER_LESS_EQUAL 5 + #define VER_AND 6 + #define VER_OR 7 + + #define VER_CONDITION_MASK 7 + #define VER_NUM_BITS_PER_CONDITION_MASK 3 + + /* RtlVerifyVersionInfo() TypeMask */ + + #define VER_MINORVERSION 0x0000001 + #define VER_MAJORVERSION 0x0000002 + #define VER_BUILDNUMBER 0x0000004 + #define VER_PLATFORMID 0x0000008 + #define VER_SERVICEPACKMINOR 0x0000010 + #define VER_SERVICEPACKMAJOR 0x0000020 + #define VER_SUITENAME 0x0000040 + #define VER_PRODUCT_TYPE 0x0000080 + + #define VER_NT_WORKSTATION 0x0000001 + #define VER_NT_DOMAIN_CONTROLLER 0x0000002 + #define VER_NT_SERVER 0x0000003 + + #define VER_PLATFORM_WIN32s 0 + #define VER_PLATFORM_WIN32_WINDOWS 1 + #define VER_PLATFORM_WIN32_NT 2 + + typedef union _RTL_RUN_ONCE { + PVOID Ptr; + } RTL_RUN_ONCE, *PRTL_RUN_ONCE; + + _Function_class_(RTL_RUN_ONCE_INIT_FN) + _IRQL_requires_same_ + typedef ULONG /* LOGICAL */ + (NTAPI *PRTL_RUN_ONCE_INIT_FN) ( + _Inout_ PRTL_RUN_ONCE RunOnce, + _Inout_opt_ PVOID Parameter, + _Inout_opt_ PVOID *Context); + + #endif /* _RTL_RUN_ONCE_DEF */ + + typedef enum _TABLE_SEARCH_RESULT { + TableEmptyTree, + TableFoundNode, + TableInsertAsLeft, + TableInsertAsRight + } TABLE_SEARCH_RESULT; + + typedef enum _RTL_GENERIC_COMPARE_RESULTS { + GenericLessThan, + GenericGreaterThan, + GenericEqual + } RTL_GENERIC_COMPARE_RESULTS; + + // Forwarder + struct _RTL_AVL_TABLE; + + _IRQL_requires_same_ + _Function_class_(RTL_AVL_COMPARE_ROUTINE) + typedef RTL_GENERIC_COMPARE_RESULTS + (NTAPI RTL_AVL_COMPARE_ROUTINE) ( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ PVOID FirstStruct, + _In_ PVOID SecondStruct); + typedef RTL_AVL_COMPARE_ROUTINE *PRTL_AVL_COMPARE_ROUTINE; + + _IRQL_requires_same_ + _Function_class_(RTL_AVL_ALLOCATE_ROUTINE) + __drv_allocatesMem(Mem) + typedef PVOID + (NTAPI RTL_AVL_ALLOCATE_ROUTINE) ( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ CLONG ByteSize); + typedef RTL_AVL_ALLOCATE_ROUTINE *PRTL_AVL_ALLOCATE_ROUTINE; + + _IRQL_requires_same_ + _Function_class_(RTL_AVL_FREE_ROUTINE) + typedef VOID + (NTAPI RTL_AVL_FREE_ROUTINE) ( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer); + typedef RTL_AVL_FREE_ROUTINE *PRTL_AVL_FREE_ROUTINE; + + _IRQL_requires_same_ + _Function_class_(RTL_AVL_MATCH_FUNCTION) + typedef NTSTATUS + (NTAPI RTL_AVL_MATCH_FUNCTION) ( + _In_ struct _RTL_AVL_TABLE *Table, + _In_ PVOID UserData, + _In_ PVOID MatchData); + typedef RTL_AVL_MATCH_FUNCTION *PRTL_AVL_MATCH_FUNCTION; + + typedef struct _RTL_BALANCED_LINKS { + struct _RTL_BALANCED_LINKS *Parent; + struct _RTL_BALANCED_LINKS *LeftChild; + struct _RTL_BALANCED_LINKS *RightChild; + CHAR Balance; + UCHAR Reserved[3]; + } RTL_BALANCED_LINKS, *PRTL_BALANCED_LINKS; + + typedef struct _RTL_AVL_TABLE { + RTL_BALANCED_LINKS BalancedRoot; + PVOID OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + ULONG DepthOfTree; + PRTL_BALANCED_LINKS RestartKey; + ULONG DeleteCount; + PRTL_AVL_COMPARE_ROUTINE CompareRoutine; + PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_AVL_FREE_ROUTINE FreeRoutine; + PVOID TableContext; + } RTL_AVL_TABLE, *PRTL_AVL_TABLE; + + typedef struct _RTL_SPLAY_LINKS { + struct _RTL_SPLAY_LINKS *Parent; + struct _RTL_SPLAY_LINKS *LeftChild; + struct _RTL_SPLAY_LINKS *RightChild; + } RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS; + + #ifndef RTL_USE_AVL_TABLES + + struct _RTL_GENERIC_TABLE; + + _IRQL_requires_same_ + _Function_class_(RTL_GENERIC_COMPARE_ROUTINE) + typedef RTL_GENERIC_COMPARE_RESULTS + (NTAPI RTL_GENERIC_COMPARE_ROUTINE) ( + _In_ struct _RTL_GENERIC_TABLE *Table, + _In_ PVOID FirstStruct, + _In_ PVOID SecondStruct); + typedef RTL_GENERIC_COMPARE_ROUTINE *PRTL_GENERIC_COMPARE_ROUTINE; + + _IRQL_requires_same_ + _Function_class_(RTL_GENERIC_ALLOCATE_ROUTINE) + __drv_allocatesMem(Mem) + typedef PVOID + (NTAPI RTL_GENERIC_ALLOCATE_ROUTINE) ( + _In_ struct _RTL_GENERIC_TABLE *Table, + _In_ CLONG ByteSize); + typedef RTL_GENERIC_ALLOCATE_ROUTINE *PRTL_GENERIC_ALLOCATE_ROUTINE; + + _IRQL_requires_same_ + _Function_class_(RTL_GENERIC_FREE_ROUTINE) + typedef VOID + (NTAPI RTL_GENERIC_FREE_ROUTINE) ( + _In_ struct _RTL_GENERIC_TABLE *Table, + _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer); + typedef RTL_GENERIC_FREE_ROUTINE *PRTL_GENERIC_FREE_ROUTINE; + + typedef struct _RTL_GENERIC_TABLE { + PRTL_SPLAY_LINKS TableRoot; + LIST_ENTRY InsertOrderList; + PLIST_ENTRY OrderedPointer; + ULONG WhichOrderedElement; + ULONG NumberGenericTableElements; + PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine; + PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine; + PRTL_GENERIC_FREE_ROUTINE FreeRoutine; + PVOID TableContext; + } RTL_GENERIC_TABLE, *PRTL_GENERIC_TABLE; + + #endif /* !RTL_USE_AVL_TABLES */ + + #ifdef RTL_USE_AVL_TABLES + + #undef RTL_GENERIC_COMPARE_ROUTINE + #undef PRTL_GENERIC_COMPARE_ROUTINE + #undef RTL_GENERIC_ALLOCATE_ROUTINE + #undef PRTL_GENERIC_ALLOCATE_ROUTINE + #undef RTL_GENERIC_FREE_ROUTINE + #undef PRTL_GENERIC_FREE_ROUTINE + #undef RTL_GENERIC_TABLE + #undef PRTL_GENERIC_TABLE + + #define RTL_GENERIC_COMPARE_ROUTINE RTL_AVL_COMPARE_ROUTINE + #define PRTL_GENERIC_COMPARE_ROUTINE PRTL_AVL_COMPARE_ROUTINE + #define RTL_GENERIC_ALLOCATE_ROUTINE RTL_AVL_ALLOCATE_ROUTINE + #define PRTL_GENERIC_ALLOCATE_ROUTINE PRTL_AVL_ALLOCATE_ROUTINE + #define RTL_GENERIC_FREE_ROUTINE RTL_AVL_FREE_ROUTINE + #define PRTL_GENERIC_FREE_ROUTINE PRTL_AVL_FREE_ROUTINE + #define RTL_GENERIC_TABLE RTL_AVL_TABLE + #define PRTL_GENERIC_TABLE PRTL_AVL_TABLE + + #endif /* RTL_USE_AVL_TABLES */ + + #define RTL_HASH_ALLOCATED_HEADER 0x00000001 + + typedef struct _RTL_DYNAMIC_HASH_TABLE_ENTRY { + LIST_ENTRY Linkage; + ULONG_PTR Signature; + } RTL_DYNAMIC_HASH_TABLE_ENTRY, *PRTL_DYNAMIC_HASH_TABLE_ENTRY; + + typedef struct _RTL_DYNAMIC_HASH_TABLE_CONTEXT { + PLIST_ENTRY ChainHead; + PLIST_ENTRY PrevLinkage; + ULONG_PTR Signature; + } RTL_DYNAMIC_HASH_TABLE_CONTEXT, *PRTL_DYNAMIC_HASH_TABLE_CONTEXT; + + typedef struct _RTL_DYNAMIC_HASH_TABLE_ENUMERATOR { + RTL_DYNAMIC_HASH_TABLE_ENTRY HashEntry; + PLIST_ENTRY ChainHead; + ULONG BucketIndex; + } RTL_DYNAMIC_HASH_TABLE_ENUMERATOR, *PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR; + + typedef struct _RTL_DYNAMIC_HASH_TABLE { + ULONG Flags; + ULONG Shift; + ULONG TableSize; + ULONG Pivot; + ULONG DivisorMask; + ULONG NumEntries; + ULONG NonEmptyBuckets; + ULONG NumEnumerators; + PVOID Directory; + } RTL_DYNAMIC_HASH_TABLE, *PRTL_DYNAMIC_HASH_TABLE; + + typedef struct _OSVERSIONINFOA { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + CHAR szCSDVersion[128]; + } OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA; + + typedef struct _OSVERSIONINFOW { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; + } OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW; + + typedef struct _OSVERSIONINFOEXA { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + CHAR szCSDVersion[128]; + USHORT wServicePackMajor; + USHORT wServicePackMinor; + USHORT wSuiteMask; + UCHAR wProductType; + UCHAR wReserved; + } OSVERSIONINFOEXA, *POSVERSIONINFOEXA, *LPOSVERSIONINFOEXA; + + typedef struct _OSVERSIONINFOEXW { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; + USHORT wServicePackMajor; + USHORT wServicePackMinor; + USHORT wSuiteMask; + UCHAR wProductType; + UCHAR wReserved; + } OSVERSIONINFOEXW, *POSVERSIONINFOEXW, *LPOSVERSIONINFOEXW, RTL_OSVERSIONINFOEXW, *PRTL_OSVERSIONINFOEXW; + + #ifdef UNICODE + typedef OSVERSIONINFOEXW OSVERSIONINFOEX; + typedef POSVERSIONINFOEXW POSVERSIONINFOEX; + typedef LPOSVERSIONINFOEXW LPOSVERSIONINFOEX; + typedef OSVERSIONINFOW OSVERSIONINFO; + typedef POSVERSIONINFOW POSVERSIONINFO; + typedef LPOSVERSIONINFOW LPOSVERSIONINFO; + #else + typedef OSVERSIONINFOEXA OSVERSIONINFOEX; + typedef POSVERSIONINFOEXA POSVERSIONINFOEX; + typedef LPOSVERSIONINFOEXA LPOSVERSIONINFOEX; + typedef OSVERSIONINFOA OSVERSIONINFO; + typedef POSVERSIONINFOA POSVERSIONINFO; + typedef LPOSVERSIONINFOA LPOSVERSIONINFO; + #endif /* UNICODE */ + + #define HASH_ENTRY_KEY(x) ((x)->Signature) + + /****************************************************************************** + * Security Manager Types * + ******************************************************************************/ + #define SE_UNSOLICITED_INPUT_PRIVILEGE 6 + + typedef enum _WELL_KNOWN_SID_TYPE { + WinNullSid = 0, + WinWorldSid = 1, + WinLocalSid = 2, + WinCreatorOwnerSid = 3, + WinCreatorGroupSid = 4, + WinCreatorOwnerServerSid = 5, + WinCreatorGroupServerSid = 6, + WinNtAuthoritySid = 7, + WinDialupSid = 8, + WinNetworkSid = 9, + WinBatchSid = 10, + WinInteractiveSid = 11, + WinServiceSid = 12, + WinAnonymousSid = 13, + WinProxySid = 14, + WinEnterpriseControllersSid = 15, + WinSelfSid = 16, + WinAuthenticatedUserSid = 17, + WinRestrictedCodeSid = 18, + WinTerminalServerSid = 19, + WinRemoteLogonIdSid = 20, + WinLogonIdsSid = 21, + WinLocalSystemSid = 22, + WinLocalServiceSid = 23, + WinNetworkServiceSid = 24, + WinBuiltinDomainSid = 25, + WinBuiltinAdministratorsSid = 26, + WinBuiltinUsersSid = 27, + WinBuiltinGuestsSid = 28, + WinBuiltinPowerUsersSid = 29, + WinBuiltinAccountOperatorsSid = 30, + WinBuiltinSystemOperatorsSid = 31, + WinBuiltinPrintOperatorsSid = 32, + WinBuiltinBackupOperatorsSid = 33, + WinBuiltinReplicatorSid = 34, + WinBuiltinPreWindows2000CompatibleAccessSid = 35, + WinBuiltinRemoteDesktopUsersSid = 36, + WinBuiltinNetworkConfigurationOperatorsSid = 37, + WinAccountAdministratorSid = 38, + WinAccountGuestSid = 39, + WinAccountKrbtgtSid = 40, + WinAccountDomainAdminsSid = 41, + WinAccountDomainUsersSid = 42, + WinAccountDomainGuestsSid = 43, + WinAccountComputersSid = 44, + WinAccountControllersSid = 45, + WinAccountCertAdminsSid = 46, + WinAccountSchemaAdminsSid = 47, + WinAccountEnterpriseAdminsSid = 48, + WinAccountPolicyAdminsSid = 49, + WinAccountRasAndIasServersSid = 50, + WinNTLMAuthenticationSid = 51, + WinDigestAuthenticationSid = 52, + WinSChannelAuthenticationSid = 53, + WinThisOrganizationSid = 54, + WinOtherOrganizationSid = 55, + WinBuiltinIncomingForestTrustBuildersSid = 56, + WinBuiltinPerfMonitoringUsersSid = 57, + WinBuiltinPerfLoggingUsersSid = 58, + WinBuiltinAuthorizationAccessSid = 59, + WinBuiltinTerminalServerLicenseServersSid = 60, + WinBuiltinDCOMUsersSid = 61, + WinBuiltinIUsersSid = 62, + WinIUserSid = 63, + WinBuiltinCryptoOperatorsSid = 64, + WinUntrustedLabelSid = 65, + WinLowLabelSid = 66, + WinMediumLabelSid = 67, + WinHighLabelSid = 68, + WinSystemLabelSid = 69, + WinWriteRestrictedCodeSid = 70, + WinCreatorOwnerRightsSid = 71, + WinCacheablePrincipalsGroupSid = 72, + WinNonCacheablePrincipalsGroupSid = 73, + WinEnterpriseReadonlyControllersSid = 74, + WinAccountReadonlyControllersSid = 75, + WinBuiltinEventLogReadersGroup = 76, + WinNewEnterpriseReadonlyControllersSid = 77, + WinBuiltinCertSvcDComAccessGroup = 78, + WinMediumPlusLabelSid = 79, + WinLocalLogonSid = 80, + WinConsoleLogonSid = 81, + WinThisOrganizationCertificateSid = 82, + } WELL_KNOWN_SID_TYPE; + + #if defined(_M_IX86) + + #define PAUSE_PROCESSOR YieldProcessor(); + + #define KERNEL_STACK_SIZE 12288 + #define KERNEL_LARGE_STACK_SIZE 61440 + #define KERNEL_LARGE_STACK_COMMIT 12288 + + #define SIZE_OF_80387_REGISTERS 80 + + #if !defined(RC_INVOKED) + + #define CONTEXT_i386 0x10000 + #define CONTEXT_i486 0x10000 + #define CONTEXT_CONTROL (CONTEXT_i386|0x00000001L) + #define CONTEXT_INTEGER (CONTEXT_i386|0x00000002L) + #define CONTEXT_SEGMENTS (CONTEXT_i386|0x00000004L) + #define CONTEXT_FLOATING_POINT (CONTEXT_i386|0x00000008L) + #define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386|0x00000010L) + #define CONTEXT_EXTENDED_REGISTERS (CONTEXT_i386|0x00000020L) + + #define CONTEXT_FULL (CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS) + #define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \ + CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \ + CONTEXT_EXTENDED_REGISTERS) + + #define CONTEXT_XSTATE (CONTEXT_i386 | 0x00000040L) + + #endif /* !defined(RC_INVOKED) */ + + typedef struct _FLOATING_SAVE_AREA { + ULONG ControlWord; + ULONG StatusWord; + ULONG TagWord; + ULONG ErrorOffset; + ULONG ErrorSelector; + ULONG DataOffset; + ULONG DataSelector; + UCHAR RegisterArea[SIZE_OF_80387_REGISTERS]; + ULONG Cr0NpxState; + } FLOATING_SAVE_AREA, *PFLOATING_SAVE_AREA; + + #include "pshpack4.h" + typedef struct _CONTEXT { + ULONG ContextFlags; + ULONG Dr0; + ULONG Dr1; + ULONG Dr2; + ULONG Dr3; + ULONG Dr6; + ULONG Dr7; + FLOATING_SAVE_AREA FloatSave; + ULONG SegGs; + ULONG SegFs; + ULONG SegEs; + ULONG SegDs; + ULONG Edi; + ULONG Esi; + ULONG Ebx; + ULONG Edx; + ULONG Ecx; + ULONG Eax; + ULONG Ebp; + ULONG Eip; + ULONG SegCs; + ULONG EFlags; + ULONG Esp; + ULONG SegSs; + UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; + } CONTEXT; + #include "poppack.h" + + #define KeGetPcr() PCR + + #define PCR_MINOR_VERSION 1 + #define PCR_MAJOR_VERSION 1 + + typedef struct _KPCR { + union { + NT_TIB NtTib; + struct { + struct _EXCEPTION_REGISTRATION_RECORD *Used_ExceptionList; + PVOID Used_StackBase; + PVOID Spare2; + PVOID TssCopy; + ULONG ContextSwitches; + KAFFINITY SetMemberCopy; + PVOID Used_Self; + }; + }; + struct _KPCR *SelfPcr; + struct _KPRCB *Prcb; + KIRQL Irql; + ULONG IRR; + ULONG IrrActive; + ULONG IDR; + PVOID KdVersionBlock; + struct _KIDTENTRY *IDT; + struct _KGDTENTRY *GDT; + struct _KTSS *TSS; + USHORT MajorVersion; + USHORT MinorVersion; + KAFFINITY SetMember; + ULONG StallScaleFactor; + UCHAR SpareUnused; + UCHAR Number; + UCHAR Spare0; + UCHAR SecondLevelCacheAssociativity; + ULONG VdmAlert; + ULONG KernelReserved[14]; + ULONG SecondLevelCacheSize; + ULONG HalReserved[16]; + } KPCR, *PKPCR; + + FORCEINLINE + ULONG + KeGetCurrentProcessorNumber(VOID) + { + return (ULONG)__readfsbyte(FIELD_OFFSET(KPCR, Number)); + } + + + + + + + extern NTKERNELAPI PVOID MmHighestUserAddress; + extern NTKERNELAPI PVOID MmSystemRangeStart; + extern NTKERNELAPI ULONG MmUserProbeAddress; + + #define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress + #define MM_SYSTEM_RANGE_START MmSystemRangeStart + #if defined(_LOCAL_COPY_USER_PROBE_ADDRESS_) + #define MM_USER_PROBE_ADDRESS _LOCAL_COPY_USER_PROBE_ADDRESS_ + extern ULONG _LOCAL_COPY_USER_PROBE_ADDRESS_; + #else + #define MM_USER_PROBE_ADDRESS MmUserProbeAddress + #endif + #define MM_LOWEST_USER_ADDRESS (PVOID)0x10000 + #define MM_KSEG0_BASE MM_SYSTEM_RANGE_START + #define MM_SYSTEM_SPACE_END 0xFFFFFFFF + #if !defined (_X86PAE_) + #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0800000 + #else + #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0C00000 + #endif + + #elif defined(_M_AMD64) + + #define PAUSE_PROCESSOR YieldProcessor(); + + #define KERNEL_STACK_SIZE 0x6000 + #define KERNEL_LARGE_STACK_SIZE 0x12000 + #define KERNEL_LARGE_STACK_COMMIT KERNEL_STACK_SIZE + + #define KERNEL_MCA_EXCEPTION_STACK_SIZE 0x2000 + + #define EXCEPTION_READ_FAULT 0 + #define EXCEPTION_WRITE_FAULT 1 + #define EXCEPTION_EXECUTE_FAULT 8 + + #if !defined(RC_INVOKED) + + #define CONTEXT_AMD64 0x100000 + + #define CONTEXT_CONTROL (CONTEXT_AMD64 | 0x1L) + #define CONTEXT_INTEGER (CONTEXT_AMD64 | 0x2L) + #define CONTEXT_SEGMENTS (CONTEXT_AMD64 | 0x4L) + #define CONTEXT_FLOATING_POINT (CONTEXT_AMD64 | 0x8L) + #define CONTEXT_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L) + + #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + #define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + + #define CONTEXT_XSTATE (CONTEXT_AMD64 | 0x20L) + + #define CONTEXT_EXCEPTION_ACTIVE 0x8000000 + #define CONTEXT_SERVICE_ACTIVE 0x10000000 + #define CONTEXT_EXCEPTION_REQUEST 0x40000000 + #define CONTEXT_EXCEPTION_REPORTING 0x80000000 + + #endif /* !defined(RC_INVOKED) */ + + #define INITIAL_MXCSR 0x1f80 + #define INITIAL_FPCSR 0x027f + + typedef struct DECLSPEC_ALIGN(16) _CONTEXT { + ULONG64 P1Home; + ULONG64 P2Home; + ULONG64 P3Home; + ULONG64 P4Home; + ULONG64 P5Home; + ULONG64 P6Home; + ULONG ContextFlags; + ULONG MxCsr; + USHORT SegCs; + USHORT SegDs; + USHORT SegEs; + USHORT SegFs; + USHORT SegGs; + USHORT SegSs; + ULONG EFlags; + ULONG64 Dr0; + ULONG64 Dr1; + ULONG64 Dr2; + ULONG64 Dr3; + ULONG64 Dr6; + ULONG64 Dr7; + ULONG64 Rax; + ULONG64 Rcx; + ULONG64 Rdx; + ULONG64 Rbx; + ULONG64 Rsp; + ULONG64 Rbp; + ULONG64 Rsi; + ULONG64 Rdi; + ULONG64 R8; + ULONG64 R9; + ULONG64 R10; + ULONG64 R11; + ULONG64 R12; + ULONG64 R13; + ULONG64 R14; + ULONG64 R15; + ULONG64 Rip; + union { + XMM_SAVE_AREA32 FltSave; + struct { + M128A Header[2]; + M128A Legacy[8]; + M128A Xmm0; + M128A Xmm1; + M128A Xmm2; + M128A Xmm3; + M128A Xmm4; + M128A Xmm5; + M128A Xmm6; + M128A Xmm7; + M128A Xmm8; + M128A Xmm9; + M128A Xmm10; + M128A Xmm11; + M128A Xmm12; + M128A Xmm13; + M128A Xmm14; + M128A Xmm15; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + M128A VectorRegister[26]; + ULONG64 VectorControl; + ULONG64 DebugControl; + ULONG64 LastBranchToRip; + ULONG64 LastBranchFromRip; + ULONG64 LastExceptionToRip; + ULONG64 LastExceptionFromRip; + } CONTEXT; + + #define PCR_MINOR_VERSION 1 + #define PCR_MAJOR_VERSION 1 + + typedef struct _KPCR + { + _ANONYMOUS_UNION union + { + NT_TIB NtTib; + _ANONYMOUS_STRUCT struct + { + union _KGDTENTRY64 *GdtBase; + struct _KTSS64 *TssBase; + ULONG64 UserRsp; + struct _KPCR *Self; + struct _KPRCB *CurrentPrcb; + PKSPIN_LOCK_QUEUE LockArray; + PVOID Used_Self; + }; + }; + union _KIDTENTRY64 *IdtBase; + ULONG64 Unused[2]; + KIRQL Irql; + UCHAR SecondLevelCacheAssociativity; + UCHAR ObsoleteNumber; + UCHAR Fill0; + ULONG Unused0[3]; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG StallScaleFactor; + PVOID Unused1[3]; + ULONG KernelReserved[15]; + ULONG SecondLevelCacheSize; + ULONG HalReserved[16]; + ULONG Unused2; + PVOID KdVersionBlock; + PVOID Unused3; + ULONG PcrAlign1[24]; + } KPCR, *PKPCR; + + FORCEINLINE + PKPCR + KeGetPcr(VOID) + { + return (PKPCR)__readgsqword(FIELD_OFFSET(KPCR, Self)); + } + + FORCEINLINE + ULONG + KeGetCurrentProcessorNumber(VOID) + { + return (ULONG)__readgsword(0x184); + } + + + #define PTI_SHIFT 12L + #define PDI_SHIFT 21L + #define PPI_SHIFT 30L + #define PXI_SHIFT 39L + #define PTE_PER_PAGE 512 + #define PDE_PER_PAGE 512 + #define PPE_PER_PAGE 512 + #define PXE_PER_PAGE 512 + #define PTI_MASK_AMD64 (PTE_PER_PAGE - 1) + #define PDI_MASK_AMD64 (PDE_PER_PAGE - 1) + #define PPI_MASK (PPE_PER_PAGE - 1) + #define PXI_MASK (PXE_PER_PAGE - 1) + + #define PXE_BASE 0xFFFFF6FB7DBED000ULL + #define PXE_SELFMAP 0xFFFFF6FB7DBEDF68ULL + #define PPE_BASE 0xFFFFF6FB7DA00000ULL + #define PDE_BASE 0xFFFFF6FB40000000ULL + #define PTE_BASE 0xFFFFF68000000000ULL + #define PXE_TOP 0xFFFFF6FB7DBEDFFFULL + #define PPE_TOP 0xFFFFF6FB7DBFFFFFULL + #define PDE_TOP 0xFFFFF6FB7FFFFFFFULL + #define PTE_TOP 0xFFFFF6FFFFFFFFFFULL + + extern NTKERNELAPI PVOID MmHighestUserAddress; + extern NTKERNELAPI PVOID MmSystemRangeStart; + extern NTKERNELAPI ULONG64 MmUserProbeAddress; + + #define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress + #define MM_SYSTEM_RANGE_START MmSystemRangeStart + #define MM_USER_PROBE_ADDRESS MmUserProbeAddress + #define MM_LOWEST_USER_ADDRESS (PVOID)0x10000 + #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xFFFF080000000000ULL + + + #elif defined(_M_IA64) + + #elif defined(_M_PPC) + + + #elif defined(_M_MIPS) + + #elif defined(_M_ARM) + #else + #error Unknown Architecture + #endif + + /****************************************************************************** + * Executive Functions * + ******************************************************************************/ + + static __inline PVOID + ExAllocateFromZone( + IN PZONE_HEADER Zone) + { + if (Zone->FreeList.Next) + Zone->FreeList.Next = Zone->FreeList.Next->Next; + return (PVOID) Zone->FreeList.Next; + } + + static __inline PVOID + ExFreeToZone( + IN PZONE_HEADER Zone, + IN PVOID Block) + { + ((PSINGLE_LIST_ENTRY) Block)->Next = Zone->FreeList.Next; + Zone->FreeList.Next = ((PSINGLE_LIST_ENTRY) Block); + return ((PSINGLE_LIST_ENTRY) Block)->Next; + } + + /* + * PVOID + * ExInterlockedAllocateFromZone( + * IN PZONE_HEADER Zone, + * IN PKSPIN_LOCK Lock) + */ + #define ExInterlockedAllocateFromZone(Zone, Lock) \ + ((PVOID) ExInterlockedPopEntryList(&Zone->FreeList, Lock)) + + /* PVOID + * ExInterlockedFreeToZone( + * IN PZONE_HEADER Zone, + * IN PVOID Block, + * IN PKSPIN_LOCK Lock); + */ + #define ExInterlockedFreeToZone(Zone, Block, Lock) \ + ExInterlockedPushEntryList(&(Zone)->FreeList, (PSINGLE_LIST_ENTRY)(Block), Lock) + + /* + * BOOLEAN + * ExIsFullZone( + * IN PZONE_HEADER Zone) + */ + #define ExIsFullZone(Zone) \ + ((Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY) NULL) + + /* BOOLEAN + * ExIsObjectInFirstZoneSegment( + * IN PZONE_HEADER Zone, + * IN PVOID Object); + */ + #define ExIsObjectInFirstZoneSegment(Zone,Object) \ + ((BOOLEAN)( ((PUCHAR)(Object) >= (PUCHAR)(Zone)->SegmentList.Next) && \ + ((PUCHAR)(Object) < (PUCHAR)(Zone)->SegmentList.Next + \ + (Zone)->TotalSegmentSize)) ) + + #define ExAcquireResourceExclusive ExAcquireResourceExclusiveLite + #define ExAcquireResourceShared ExAcquireResourceSharedLite + #define ExConvertExclusiveToShared ExConvertExclusiveToSharedLite + #define ExDeleteResource ExDeleteResourceLite + #define ExInitializeResource ExInitializeResourceLite + #define ExIsResourceAcquiredExclusive ExIsResourceAcquiredExclusiveLite + #define ExIsResourceAcquiredShared ExIsResourceAcquiredSharedLite + #define ExIsResourceAcquired ExIsResourceAcquiredSharedLite + #define ExReleaseResourceForThread ExReleaseResourceForThreadLite + + #ifndef _M_IX86 + #define RESULT_ZERO 0 + #define RESULT_NEGATIVE 1 + #define RESULT_POSITIVE 2 + #endif + + typedef enum _INTERLOCKED_RESULT { + ResultNegative = RESULT_NEGATIVE, + ResultZero = RESULT_ZERO, + ResultPositive = RESULT_POSITIVE + } INTERLOCKED_RESULT; + + #ifdef _X86_ + + NTKERNELAPI + INTERLOCKED_RESULT + FASTCALL + Exfi386InterlockedIncrementLong( + _Inout_ _Interlocked_operand_ LONG volatile *Addend); + + NTKERNELAPI + INTERLOCKED_RESULT + FASTCALL + Exfi386InterlockedDecrementLong( + _Inout_ _Interlocked_operand_ PLONG Addend); + + NTKERNELAPI + ULONG + FASTCALL + Exfi386InterlockedExchangeUlong( + _Inout_ _Interlocked_operand_ PULONG Target, + _In_ ULONG Value); + + #endif + + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + NTKERNELAPI + NTSTATUS + NTAPI + ExExtendZone( + _Inout_ PZONE_HEADER Zone, + _Inout_ PVOID Segment, + _In_ ULONG SegmentSize); + + NTKERNELAPI + NTSTATUS + NTAPI + ExInitializeZone( + _Out_ PZONE_HEADER Zone, + _In_ ULONG BlockSize, + _Inout_ PVOID InitialSegment, + _In_ ULONG InitialSegmentSize); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + ExInterlockedExtendZone( + _Inout_ PZONE_HEADER Zone, + _Inout_ PVOID Segment, + _In_ ULONG SegmentSize, + _Inout_ _Requires_lock_not_held_(*_Curr_) PKSPIN_LOCK Lock); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + ExUuidCreate( + _Out_ UUID *Uuid); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + DECLSPEC_NORETURN + VOID + NTAPI + ExRaiseAccessViolation(VOID); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + DECLSPEC_NORETURN + VOID + NTAPI + ExRaiseDatatypeMisalignment(VOID); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + + /* Hardware Abstraction Layer Functions */ + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + #if defined(USE_DMA_MACROS) && !defined(_NTHAL_) && (defined(_NTDDK_) || defined(_NTDRIVER_)) || defined(_WDM_INCLUDED_) + + /* Nothing here */ + + #else /* USE_DMA_MACROS ... */ + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + VOID + NTAPI + IoFreeAdapterChannel( + _In_ PADAPTER_OBJECT AdapterObject); + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + BOOLEAN + NTAPI + IoFlushAdapterBuffers( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ PMDL Mdl, + _In_ PVOID MapRegisterBase, + _In_ PVOID CurrentVa, + _In_ ULONG Length, + _In_ BOOLEAN WriteToDevice); + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + VOID + NTAPI + IoFreeMapRegisters( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ PVOID MapRegisterBase, + _In_ ULONG NumberOfMapRegisters); + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + PVOID + NTAPI + HalAllocateCommonBuffer( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ ULONG Length, + _Out_ PPHYSICAL_ADDRESS LogicalAddress, + _In_ BOOLEAN CacheEnabled); + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + VOID + NTAPI + HalFreeCommonBuffer( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ ULONG Length, + _In_ PHYSICAL_ADDRESS LogicalAddress, + _In_ PVOID VirtualAddress, + _In_ BOOLEAN CacheEnabled); + + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + ULONG + NTAPI + HalReadDmaCounter( + _In_ PADAPTER_OBJECT AdapterObject); + + NTHALAPI + NTSTATUS + NTAPI + HalAllocateAdapterChannel( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ PWAIT_CONTEXT_BLOCK Wcb, + _In_ ULONG NumberOfMapRegisters, + _In_ PDRIVER_CONTROL ExecutionRoutine); + + #endif /* USE_DMA_MACROS ... */ + + #if !defined(NO_LEGACY_DRIVERS) + NTHALAPI + NTSTATUS + NTAPI + HalAssignSlotResources( + _In_ PUNICODE_STRING RegistryPath, + _In_opt_ PUNICODE_STRING DriverClassName, + _In_ PDRIVER_OBJECT DriverObject, + _In_ PDEVICE_OBJECT DeviceObject, + _In_ INTERFACE_TYPE BusType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _Inout_ PCM_RESOURCE_LIST *AllocatedResources); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTHALAPI + ULONG + NTAPI + HalGetInterruptVector( + _In_ INTERFACE_TYPE InterfaceType, + _In_ ULONG BusNumber, + _In_ ULONG BusInterruptLevel, + _In_ ULONG BusInterruptVector, + _Out_ PKIRQL Irql, + _Out_ PKAFFINITY Affinity); + + NTHALAPI + ULONG + NTAPI + HalSetBusData( + _In_ BUS_DATA_TYPE BusDataType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _In_reads_bytes_(Length) PVOID Buffer, + _In_ ULONG Length); + + NTHALAPI + ULONG + NTAPI + HalGetBusData( + _In_ BUS_DATA_TYPE BusDataType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _Out_writes_bytes_(Length) PVOID Buffer, + _In_ ULONG Length); + + NTHALAPI + BOOLEAN + NTAPI + HalMakeBeep( + _In_ ULONG Frequency); + #endif /* !defined(NO_LEGACY_DRIVERS) */ + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTHALAPI + PADAPTER_OBJECT + NTAPI + HalGetAdapter( + _In_ PDEVICE_DESCRIPTION DeviceDescription, + _Out_ PULONG NumberOfMapRegisters); + + VOID + NTAPI + HalPutDmaAdapter( + _In_ PADAPTER_OBJECT DmaAdapter); + + NTHALAPI + VOID + NTAPI + HalAcquireDisplayOwnership( + _In_ PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters); + + NTHALAPI + ULONG + NTAPI + HalGetBusDataByOffset( + _In_ BUS_DATA_TYPE BusDataType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _Out_writes_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + + NTHALAPI + ULONG + NTAPI + HalSetBusDataByOffset( + _In_ BUS_DATA_TYPE BusDataType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _In_reads_bytes_(Length) PVOID Buffer, + _In_ ULONG Offset, + _In_ ULONG Length); + + NTHALAPI + BOOLEAN + NTAPI + HalTranslateBusAddress( + _In_ INTERFACE_TYPE InterfaceType, + _In_ ULONG BusNumber, + _In_ PHYSICAL_ADDRESS BusAddress, + _Inout_ PULONG AddressSpace, + _Out_ PPHYSICAL_ADDRESS TranslatedAddress); + + NTHALAPI + PVOID + NTAPI + HalAllocateCrashDumpRegisters( + _In_ PADAPTER_OBJECT AdapterObject, + _Inout_ PULONG NumberOfMapRegisters); + + NTSTATUS + NTAPI + HalGetScatterGatherList( + _In_ PADAPTER_OBJECT DmaAdapter, + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PMDL Mdl, + _In_ PVOID CurrentVa, + _In_ ULONG Length, + _In_ PDRIVER_LIST_CONTROL ExecutionRoutine, + _In_ PVOID Context, + _In_ BOOLEAN WriteToDevice); + + VOID + NTAPI + HalPutScatterGatherList( + _In_ PADAPTER_OBJECT DmaAdapter, + _In_ PSCATTER_GATHER_LIST ScatterGather, + _In_ BOOLEAN WriteToDevice); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + #if (NTDDI_VERSION >= NTDDI_WINXP) + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + VOID + FASTCALL + HalExamineMBR( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG MBRTypeIdentifier, + _Out_ PVOID *Buffer); + #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + NTSTATUS + NTAPI + HalAllocateHardwareCounters( + _In_reads_(GroupCount) PGROUP_AFFINITY GroupAffinty, + _In_ ULONG GroupCount, + _In_ PPHYSICAL_COUNTER_RESOURCE_LIST ResourceList, + _Out_ PHANDLE CounterSetHandle); + + NTSTATUS + NTAPI + HalFreeHardwareCounters( + _In_ HANDLE CounterSetHandle); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + #if defined(_IA64_) + #if (NTDDI_VERSION >= NTDDI_WIN2K) + NTHALAPI + ULONG + NTAPI + HalGetDmaAlignmentRequirement(VOID); + #endif + #endif /* defined(_IA64_) */ + + #if defined(_M_IX86) || defined(_M_AMD64) + #define HalGetDmaAlignmentRequirement() 1L + #endif + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + typedef struct _WHEA_ERROR_SOURCE_DESCRIPTOR *PWHEA_ERROR_SOURCE_DESCRIPTOR; + typedef struct _WHEA_ERROR_RECORD *PWHEA_ERROR_RECORD; + + NTHALAPI + VOID + NTAPI + HalBugCheckSystem( + _In_ PWHEA_ERROR_SOURCE_DESCRIPTOR ErrorSource, + _In_ PWHEA_ERROR_RECORD ErrorRecord); + + #else + + typedef struct _WHEA_ERROR_RECORD *PWHEA_ERROR_RECORD; + + NTHALAPI + VOID + NTAPI + HalBugCheckSystem( + _In_ PWHEA_ERROR_RECORD ErrorRecord); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + /****************************************************************************** + * I/O Manager Functions * + ******************************************************************************/ + + /* + * VOID IoAssignArcName( + * IN PUNICODE_STRING ArcName, + * IN PUNICODE_STRING DeviceName); + */ + #define IoAssignArcName(_ArcName, _DeviceName) ( \ + IoCreateSymbolicLink((_ArcName), (_DeviceName))) + + /* + * VOID + * IoDeassignArcName( + * IN PUNICODE_STRING ArcName) + */ + #define IoDeassignArcName IoDeleteSymbolicLink + + FORCEINLINE + VOID + NTAPI + IoInitializeDriverCreateContext( + PIO_DRIVER_CREATE_CONTEXT DriverContext) + { + RtlZeroMemory(DriverContext, sizeof(IO_DRIVER_CREATE_CONTEXT)); + DriverContext->Size = sizeof(IO_DRIVER_CREATE_CONTEXT); + } + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + #if !(defined(USE_DMA_MACROS) && (defined(_NTDDK_) || defined(_NTDRIVER_)) || defined(_WDM_INCLUDED_)) + _IRQL_requires_max_(DISPATCH_LEVEL) + _IRQL_requires_min_(DISPATCH_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + IoAllocateAdapterChannel( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG NumberOfMapRegisters, + _In_ PDRIVER_CONTROL ExecutionRoutine, + _In_ PVOID Context); + #endif + + #if !defined(DMA_MACROS_DEFINED) + //DECLSPEC_DEPRECATED_DDK + NTHALAPI + PHYSICAL_ADDRESS + NTAPI + IoMapTransfer( + _In_ PADAPTER_OBJECT AdapterObject, + _In_ PMDL Mdl, + _In_ PVOID MapRegisterBase, + _In_ PVOID CurrentVa, + _Inout_ PULONG Length, + _In_ BOOLEAN WriteToDevice); + #endif + + _IRQL_requires_max_(DISPATCH_LEVEL) + _IRQL_requires_min_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoAllocateController( + _In_ PCONTROLLER_OBJECT ControllerObject, + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PDRIVER_CONTROL ExecutionRoutine, + _In_opt_ PVOID Context); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + PCONTROLLER_OBJECT + NTAPI + IoCreateController( + _In_ ULONG Size); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoDeleteController( + _In_ PCONTROLLER_OBJECT ControllerObject); + + _IRQL_requires_max_(DISPATCH_LEVEL) + _IRQL_requires_min_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoFreeController( + _In_ PCONTROLLER_OBJECT ControllerObject); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + PCONFIGURATION_INFORMATION + NTAPI + IoGetConfigurationInformation(VOID); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + PDEVICE_OBJECT + NTAPI + IoGetDeviceToVerify( + _In_ PETHREAD Thread); + + NTKERNELAPI + VOID + NTAPI + IoCancelFileOpen( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PFILE_OBJECT FileObject); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + PGENERIC_MAPPING + NTAPI + IoGetFileObjectGenericMapping(VOID); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + PIRP + NTAPI + IoMakeAssociatedIrp( + _In_ PIRP Irp, + _In_ CCHAR StackSize); + + NTKERNELAPI + NTSTATUS + NTAPI + IoQueryDeviceDescription( + _In_opt_ PINTERFACE_TYPE BusType, + _In_opt_ PULONG BusNumber, + _In_opt_ PCONFIGURATION_TYPE ControllerType, + _In_opt_ PULONG ControllerNumber, + _In_opt_ PCONFIGURATION_TYPE PeripheralType, + _In_opt_ PULONG PeripheralNumber, + _In_ PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, + _Inout_opt_ PVOID Context); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoRaiseHardError( + _In_ PIRP Irp, + _In_opt_ PVPB Vpb, + _In_ PDEVICE_OBJECT RealDeviceObject); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + BOOLEAN + NTAPI + IoRaiseInformationalHardError( + _In_ NTSTATUS ErrorStatus, + _In_opt_ PUNICODE_STRING String, + _In_opt_ PKTHREAD Thread); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoRegisterBootDriverReinitialization( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PDRIVER_REINITIALIZE DriverReinitializationRoutine, + _In_opt_ PVOID Context); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoRegisterDriverReinitialization( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PDRIVER_REINITIALIZE DriverReinitializationRoutine, + _In_opt_ PVOID Context); + + NTKERNELAPI + NTSTATUS + NTAPI + IoAttachDeviceByPointer( + _In_ PDEVICE_OBJECT SourceDevice, + _In_ PDEVICE_OBJECT TargetDevice); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _Must_inspect_result_ + NTKERNELAPI + NTSTATUS + NTAPI + IoReportDetectedDevice( + _In_ PDRIVER_OBJECT DriverObject, + _In_ INTERFACE_TYPE LegacyBusType, + _In_ ULONG BusNumber, + _In_ ULONG SlotNumber, + _In_opt_ PCM_RESOURCE_LIST ResourceList, + _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements, + _In_ BOOLEAN ResourceAssigned, + _Inout_ PDEVICE_OBJECT *DeviceObject); + + NTKERNELAPI + NTSTATUS + NTAPI + IoReportResourceForDetection( + _In_ PDRIVER_OBJECT DriverObject, + _In_reads_bytes_opt_(DriverListSize) PCM_RESOURCE_LIST DriverList, + _In_opt_ ULONG DriverListSize, + _In_opt_ PDEVICE_OBJECT DeviceObject, + _In_reads_bytes_opt_(DeviceListSize) PCM_RESOURCE_LIST DeviceList, + _In_opt_ ULONG DeviceListSize, + _Out_ PBOOLEAN ConflictDetected); + + NTKERNELAPI + NTSTATUS + NTAPI + IoReportResourceUsage( + _In_opt_ PUNICODE_STRING DriverClassName, + _In_ PDRIVER_OBJECT DriverObject, + _In_reads_bytes_opt_(DriverListSize) PCM_RESOURCE_LIST DriverList, + _In_opt_ ULONG DriverListSize, + _In_opt_ PDEVICE_OBJECT DeviceObject, + _In_reads_bytes_opt_(DeviceListSize) PCM_RESOURCE_LIST DeviceList, + _In_opt_ ULONG DeviceListSize, + _In_ BOOLEAN OverrideConflict, + _Out_ PBOOLEAN ConflictDetected); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + NTAPI + IoSetHardErrorOrVerifyDevice( + _In_ PIRP Irp, + _In_ PDEVICE_OBJECT DeviceObject); + + NTKERNELAPI + NTSTATUS + NTAPI + IoAssignResources( + _In_ PUNICODE_STRING RegistryPath, + _In_opt_ PUNICODE_STRING DriverClassName, + _In_ PDRIVER_OBJECT DriverObject, + _In_opt_ PDEVICE_OBJECT DeviceObject, + _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, + _Inout_ PCM_RESOURCE_LIST *AllocatedResources); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + BOOLEAN + NTAPI + IoSetThreadHardErrorMode( + _In_ BOOLEAN EnableHardErrors); + + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + #if (NTDDI_VERSION >= NTDDI_WIN2KSP3) + + NTKERNELAPI + BOOLEAN + NTAPI + IoIsFileOriginRemote( + _In_ PFILE_OBJECT FileObject); + + NTKERNELAPI + NTSTATUS + NTAPI + IoSetFileOrigin( + _In_ PFILE_OBJECT FileObject, + _In_ BOOLEAN Remote); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2KSP3) */ + + #if (NTDDI_VERSION >= NTDDI_WINXP) + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + FASTCALL + IoReadPartitionTable( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ BOOLEAN ReturnRecognizedPartitions, + _Out_ struct _DRIVE_LAYOUT_INFORMATION **PartitionBuffer); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + FASTCALL + IoSetPartitionInformation( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG PartitionNumber, + _In_ ULONG PartitionType); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + FASTCALL + IoWritePartitionTable( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG SectorSize, + _In_ ULONG SectorsPerTrack, + _In_ ULONG NumberOfHeads, + _In_ struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer); + + NTKERNELAPI + NTSTATUS + NTAPI + IoCreateDisk( + _In_ PDEVICE_OBJECT DeviceObject, + _In_opt_ struct _CREATE_DISK* Disk); + + NTKERNELAPI + NTSTATUS + NTAPI + IoReadDiskSignature( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG BytesPerSector, + _Out_ PDISK_SIGNATURE Signature); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + IoReadPartitionTableEx( + _In_ PDEVICE_OBJECT DeviceObject, + _Out_ struct _DRIVE_LAYOUT_INFORMATION_EX **PartitionBuffer); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + IoSetPartitionInformationEx( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ ULONG PartitionNumber, + _In_ struct _SET_PARTITION_INFORMATION_EX *PartitionInfo); + + NTKERNELAPI + NTSTATUS + NTAPI + IoSetSystemPartition( + _In_ PUNICODE_STRING VolumeNameString); + + NTKERNELAPI + NTSTATUS + NTAPI + IoVerifyPartitionTable( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ BOOLEAN FixErrors); + + NTKERNELAPI + NTSTATUS + NTAPI + IoVolumeDeviceToDosName( + _In_ PVOID VolumeDeviceObject, + _Out_ _When_(return==0, + _At_(DosName->Buffer, __drv_allocatesMem(Mem))) + PUNICODE_STRING DosName); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + IoWritePartitionTableEx( + _In_ PDEVICE_OBJECT DeviceObject, + _In_reads_(_Inexpressible_(FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]))) + struct _DRIVE_LAYOUT_INFORMATION_EX *DriveLayout); + + NTKERNELAPI + NTSTATUS + NTAPI + IoCreateFileSpecifyDeviceObjectHint( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_opt_ PLARGE_INTEGER AllocationSize, + _In_ ULONG FileAttributes, + _In_ ULONG ShareAccess, + _In_ ULONG Disposition, + _In_ ULONG CreateOptions, + _In_opt_ PVOID EaBuffer, + _In_ ULONG EaLength, + _In_ CREATE_FILE_TYPE CreateFileType, + _In_opt_ PVOID InternalParameters, + _In_ ULONG Options, + _In_opt_ PVOID DeviceObject); + + NTKERNELAPI + NTSTATUS + NTAPI + IoAttachDeviceToDeviceStackSafe( + _In_ PDEVICE_OBJECT SourceDevice, + _In_ PDEVICE_OBJECT TargetDevice, + _Outptr_ PDEVICE_OBJECT *AttachedToDeviceObject); + + + #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ + + #if (NTDDI_VERSION >= NTDDI_WS03) + NTKERNELAPI + IO_PAGING_PRIORITY + FASTCALL + IoGetPagingIoPriority( + _In_ PIRP Irp); + + #endif /* (NTDDI_VERSION >= NTDDI_WS03) */ + #if (NTDDI_VERSION >= NTDDI_WS03SP1) + + BOOLEAN + NTAPI + IoTranslateBusAddress( + _In_ INTERFACE_TYPE InterfaceType, + _In_ ULONG BusNumber, + _In_ PHYSICAL_ADDRESS BusAddress, + _Inout_ PULONG AddressSpace, + _Out_ PPHYSICAL_ADDRESS TranslatedAddress); + #endif /* (NTDDI_VERSION >= NTDDI_WS03SP1) */ + + #if (NTDDI_VERSION >= NTDDI_VISTA) ++ ++ struct _DISK_GEOMETRY_EX; ++ + NTKERNELAPI + NTSTATUS + NTAPI + IoUpdateDiskGeometry( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ struct _DISK_GEOMETRY_EX* OldDiskGeometry, + _In_ struct _DISK_GEOMETRY_EX* NewDiskGeometry); + + PTXN_PARAMETER_BLOCK + NTAPI + IoGetTransactionParameterBlock( + _In_ PFILE_OBJECT FileObject); + + NTKERNELAPI + NTSTATUS + NTAPI + IoCreateFileEx( + _Out_ PHANDLE FileHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_opt_ PLARGE_INTEGER AllocationSize, + _In_ ULONG FileAttributes, + _In_ ULONG ShareAccess, + _In_ ULONG Disposition, + _In_ ULONG CreateOptions, + _In_opt_ PVOID EaBuffer, + _In_ ULONG EaLength, + _In_ CREATE_FILE_TYPE CreateFileType, + _In_opt_ PVOID InternalParameters, + _In_ ULONG Options, + _In_opt_ PIO_DRIVER_CREATE_CONTEXT DriverContext); + + NTSTATUS + NTAPI + IoSetIrpExtraCreateParameter( + _Inout_ PIRP Irp, + _In_ struct _ECP_LIST *ExtraCreateParameter); + + VOID + NTAPI + IoClearIrpExtraCreateParameter( + _Inout_ PIRP Irp); + + NTSTATUS + NTAPI + IoGetIrpExtraCreateParameter( + _In_ PIRP Irp, + _Outptr_result_maybenull_ struct _ECP_LIST **ExtraCreateParameter); + + BOOLEAN + NTAPI + IoIsFileObjectIgnoringSharing( + _In_ PFILE_OBJECT FileObject); + + #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + NTSTATUS + NTAPI + IoSetFileObjectIgnoreSharing( + _In_ PFILE_OBJECT FileObject); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + /****************************************************************************** + * Kernel Debugger Functions * + ******************************************************************************/ + NTSYSAPI + ULONG + NTAPI + DbgPrompt( + _In_z_ PCCH Prompt, + _Out_writes_bytes_(MaximumResponseLength) PCH Response, + _In_ ULONG MaximumResponseLength); + + /****************************************************************************** + * Kernel Functions * + ******************************************************************************/ + + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + FASTCALL + KeInvalidateRangeAllCaches( + _In_ PVOID BaseAddress, + _In_ ULONG Length); + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + NTKERNELAPI + VOID + NTAPI + KeSetImportanceDpc( + _Inout_ PRKDPC Dpc, + _In_ KDPC_IMPORTANCE Importance); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + LONG + NTAPI + KePulseEvent( + _Inout_ PRKEVENT Event, + _In_ KPRIORITY Increment, + _In_ BOOLEAN Wait); + + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + LONG + NTAPI + KeSetBasePriorityThread( + _Inout_ PRKTHREAD Thread, + _In_ LONG Increment); + + _Acquires_lock_(_Global_critical_region_) + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + KeEnterCriticalRegion(VOID); + + _Releases_lock_(_Global_critical_region_) + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + KeLeaveCriticalRegion(VOID); + + NTKERNELAPI + DECLSPEC_NORETURN + VOID + NTAPI + KeBugCheck( + _In_ ULONG BugCheckCode); + #if defined(SINGLE_GROUP_LEGACY_API) + + + NTKERNELAPI + VOID + NTAPI + KeSetTargetProcessorDpc( + _Inout_ PRKDPC Dpc, + _In_ CCHAR Number); + + NTKERNELAPI + KAFFINITY + NTAPI + KeQueryActiveProcessors(VOID); + #endif /* defined(SINGLE_GROUP_LEGACY_API) */ + + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + #if (NTDDI_VERSION >= NTDDI_WINXP) + + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + BOOLEAN + NTAPI + KeAreApcsDisabled(VOID); + + #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ + + #if (NTDDI_VERSION >= NTDDI_WS03) + + + NTKERNELAPI + BOOLEAN + NTAPI + KeInvalidateAllCaches(VOID); + #endif /* (NTDDI_VERSION >= NTDDI_WS03) */ + #if (NTDDI_VERSION >= NTDDI_WS03SP1) + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + KeExpandKernelStackAndCallout( + _In_ PEXPAND_STACK_CALLOUT Callout, + _In_opt_ PVOID Parameter, + _In_ SIZE_T Size); + + _Acquires_lock_(_Global_critical_region_) + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + KeEnterGuardedRegion(VOID); + + _Releases_lock_(_Global_critical_region_) + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + KeLeaveGuardedRegion(VOID); + #endif /* (NTDDI_VERSION >= NTDDI_WS03SP1) */ + + #if (NTDDI_VERSION >= NTDDI_VISTA) + #if defined(SINGLE_GROUP_LEGACY_API) + + NTKERNELAPI + ULONG + NTAPI + KeQueryActiveProcessorCount( + _Out_opt_ PKAFFINITY ActiveProcessors); + + NTKERNELAPI + ULONG + NTAPI + KeQueryMaximumProcessorCount(VOID); + #endif /* SINGLE_GROUP_LEGACY_API */ + + #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + NTKERNELAPI + ULONG + NTAPI + KeQueryActiveProcessorCountEx( + _In_ USHORT GroupNumber); + + NTKERNELAPI + ULONG + NTAPI + KeQueryMaximumProcessorCountEx( + _In_ USHORT GroupNumber); + + NTKERNELAPI + USHORT + NTAPI + KeQueryActiveGroupCount(VOID); + + NTKERNELAPI + USHORT + NTAPI + KeQueryMaximumGroupCount(VOID); + + NTKERNELAPI + KAFFINITY + NTAPI + KeQueryGroupAffinity( + _In_ USHORT GroupNumber); + + NTKERNELAPI + ULONG + NTAPI + KeGetCurrentProcessorNumberEx( + _Out_opt_ PPROCESSOR_NUMBER ProcNumber); + + NTKERNELAPI + VOID + NTAPI + KeQueryNodeActiveAffinity( + _In_ USHORT NodeNumber, + _Out_opt_ PGROUP_AFFINITY Affinity, + _Out_opt_ PUSHORT Count); + + NTKERNELAPI + USHORT + NTAPI + KeQueryNodeMaximumProcessorCount( + _In_ USHORT NodeNumber); + + NTKERNELAPI + USHORT + NTAPI + KeQueryHighestNodeNumber(VOID); + + NTKERNELAPI + USHORT + NTAPI + KeGetCurrentNodeNumber(VOID); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + KeQueryLogicalProcessorRelationship( + _In_opt_ PPROCESSOR_NUMBER ProcessorNumber, + _In_ LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, + _Out_writes_bytes_opt_(*Length) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Information, + _Inout_ PULONG Length); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + KeSetHardwareCounterConfiguration( + _In_reads_(Count) PHARDWARE_COUNTER CounterArray, + _In_ ULONG Count); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + KeQueryHardwareCounterConfiguration( + _Out_writes_to_(MaximumCount, *Count) PHARDWARE_COUNTER CounterArray, + _In_ ULONG MaximumCount, + _Out_ PULONG Count); + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + /****************************************************************************** + * Memory manager Functions * + ******************************************************************************/ + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + _IRQL_requires_max_ (PASSIVE_LEVEL) + NTKERNELAPI + PPHYSICAL_MEMORY_RANGE + NTAPI + MmGetPhysicalMemoryRanges(VOID); + + NTKERNELAPI + PHYSICAL_ADDRESS + NTAPI + MmGetPhysicalAddress( + _In_ PVOID BaseAddress); + + NTKERNELAPI + BOOLEAN + NTAPI + MmIsNonPagedSystemAddressValid( + _In_ PVOID VirtualAddress); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + _Out_writes_bytes_opt_(NumberOfBytes) + NTKERNELAPI + PVOID + NTAPI + MmAllocateNonCachedMemory( + _In_ SIZE_T NumberOfBytes); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmFreeNonCachedMemory( + _In_reads_bytes_(NumberOfBytes) PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes); + + NTKERNELAPI + PVOID + NTAPI + MmGetVirtualForPhysical( + _In_ PHYSICAL_ADDRESS PhysicalAddress); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmMapUserAddressesToPage( + _In_reads_bytes_(NumberOfBytes) PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes, + _In_ PVOID PageAddress); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + _Out_writes_bytes_opt_(NumberOfBytes) + NTKERNELAPI + PVOID + NTAPI + MmMapVideoDisplay( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ SIZE_T NumberOfBytes, + _In_ MEMORY_CACHING_TYPE CacheType); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmMapViewInSessionSpace( + _In_ PVOID Section, + _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, + _Inout_ PSIZE_T ViewSize); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmMapViewInSystemSpace( + _In_ PVOID Section, + _Outptr_result_bytebuffer_(*ViewSize) PVOID *MappedBase, + _Inout_ PSIZE_T ViewSize); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + BOOLEAN + NTAPI + MmIsAddressValid( + _In_ PVOID VirtualAddress); + + NTKERNELAPI + BOOLEAN + NTAPI + MmIsThisAnNtAsSystem(VOID); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmLockPagableSectionByHandle( + _In_ PVOID ImageSectionHandle); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmUnmapViewInSessionSpace( + _In_ PVOID MappedBase); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmUnmapViewInSystemSpace( + _In_ PVOID MappedBase); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmUnsecureVirtualMemory( + _In_ HANDLE SecureHandle); + + _IRQL_requires_max_ (PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmRemovePhysicalMemory( + _In_ PPHYSICAL_ADDRESS StartAddress, + _Inout_ PLARGE_INTEGER NumberOfBytes); + + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + HANDLE + NTAPI + MmSecureVirtualMemory( + __in_data_source(USER_MODE) _In_reads_bytes_ (Size) PVOID Address, + _In_ __in_data_source(USER_MODE) SIZE_T Size, + _In_ ULONG ProbeMode); + + _IRQL_requires_max_(APC_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmUnmapVideoDisplay( + _In_reads_bytes_(NumberOfBytes) PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes); + + _IRQL_requires_max_ (PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmAddPhysicalMemory( + _In_ PPHYSICAL_ADDRESS StartAddress, + _Inout_ PLARGE_INTEGER NumberOfBytes); + + _Must_inspect_result_ + _IRQL_requires_max_(DISPATCH_LEVEL) + _When_(return != NULL, _Post_writable_byte_size_(NumberOfBytes)) + NTKERNELAPI + PVOID + NTAPI + MmAllocateContiguousMemory( + _In_ SIZE_T NumberOfBytes, + _In_ PHYSICAL_ADDRESS HighestAcceptableAddress); + + _Must_inspect_result_ + _IRQL_requires_max_(DISPATCH_LEVEL) + _When_(return != NULL, _Post_writable_byte_size_(NumberOfBytes)) + NTKERNELAPI + PVOID + NTAPI + MmAllocateContiguousMemorySpecifyCache( + _In_ SIZE_T NumberOfBytes, + _In_ PHYSICAL_ADDRESS LowestAcceptableAddress, + _In_ PHYSICAL_ADDRESS HighestAcceptableAddress, + _In_opt_ PHYSICAL_ADDRESS BoundaryAddressMultiple, + _In_ MEMORY_CACHING_TYPE CacheType); + + _Must_inspect_result_ + _IRQL_requires_max_(DISPATCH_LEVEL) + _When_(return != NULL, _Post_writable_byte_size_(NumberOfBytes)) + NTKERNELAPI + PVOID + NTAPI + MmAllocateContiguousMemorySpecifyCacheNode( + _In_ SIZE_T NumberOfBytes, + _In_ PHYSICAL_ADDRESS LowestAcceptableAddress, + _In_ PHYSICAL_ADDRESS HighestAcceptableAddress, + _In_opt_ PHYSICAL_ADDRESS BoundaryAddressMultiple, + _In_ MEMORY_CACHING_TYPE CacheType, + _In_ NODE_REQUIREMENT PreferredNode); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmFreeContiguousMemory( + _In_ PVOID BaseAddress); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + VOID + NTAPI + MmFreeContiguousMemorySpecifyCache( + _In_reads_bytes_(NumberOfBytes) PVOID BaseAddress, + _In_ SIZE_T NumberOfBytes, + _In_ MEMORY_CACHING_TYPE CacheType); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + + + #if (NTDDI_VERSION >= NTDDI_WS03) + + _Must_inspect_result_ + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + MmCreateMirror(VOID); + #endif /* (NTDDI_VERSION >= NTDDI_WS03) */ + + #if (NTDDI_VERSION >= NTDDI_VISTA) + _Must_inspect_result_ + _IRQL_requires_max_(APC_LEVEL) + NTSTATUS + NTAPI + MmRotatePhysicalView( + _In_ PVOID VirtualAddress, + _Inout_ PSIZE_T NumberOfBytes, + _In_opt_ PMDLX NewMdl, + _In_ MM_ROTATE_DIRECTION Direction, + _In_ PMM_ROTATE_COPY_CALLBACK_FUNCTION CopyFunction, + _In_opt_ PVOID Context); + #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ + + /****************************************************************************** + * Process Manager Functions * + ******************************************************************************/ + + __kernel_entry + NTSYSCALLAPI + NTSTATUS + NTAPI + NtOpenProcess( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PCLIENT_ID ClientId); + + NTSYSCALLAPI + NTSTATUS + NTAPI + NtQueryInformationProcess( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation OPTIONAL, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL); + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + PsSetCreateProcessNotifyRoutine( + _In_ PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, + _In_ BOOLEAN Remove); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + PsSetCreateThreadNotifyRoutine( + _In_ PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + PsSetLoadImageNotifyRoutine( + _In_ PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine); + + NTKERNELAPI + HANDLE + NTAPI + PsGetCurrentProcessId(VOID); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + HANDLE + NTAPI + PsGetCurrentThreadId(VOID); + + NTKERNELAPI + BOOLEAN + NTAPI + PsGetVersion( + OUT PULONG MajorVersion OPTIONAL, + OUT PULONG MinorVersion OPTIONAL, + OUT PULONG BuildNumber OPTIONAL, + OUT PUNICODE_STRING CSDVersion OPTIONAL); + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + #if (NTDDI_VERSION >= NTDDI_WINXP) + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + HANDLE + NTAPI + PsGetProcessId( + _In_ PEPROCESS Process); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + HANDLE + NTAPI + PsGetThreadId( + _In_ PETHREAD Thread); + + NTKERNELAPI + NTSTATUS + NTAPI + PsRemoveCreateThreadNotifyRoutine( + _In_ PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + NTSTATUS + NTAPI + PsRemoveLoadImageNotifyRoutine( + _In_ PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine); + + _IRQL_requires_max_(DISPATCH_LEVEL) + NTKERNELAPI + LONGLONG + NTAPI + PsGetProcessCreateTimeQuadPart( + _In_ PEPROCESS Process); + #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ + + #if (NTDDI_VERSION >= NTDDI_WS03) + NTKERNELAPI + HANDLE + NTAPI + PsGetThreadProcessId( + IN PETHREAD Thread); + #endif /* (NTDDI_VERSION >= NTDDI_WS03) */ + + #if (NTDDI_VERSION >= NTDDI_VISTA) + + NTKERNELAPI + BOOLEAN + NTAPI + PsSetCurrentThreadPrefetching( + IN BOOLEAN Prefetching); + + NTKERNELAPI + BOOLEAN + NTAPI + PsIsCurrentThreadPrefetching(VOID); + + #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ + + #if (NTDDI_VERSION >= NTDDI_VISTASP1) + NTKERNELAPI + NTSTATUS + NTAPI + PsSetCreateProcessNotifyRoutineEx( + IN PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine, + IN BOOLEAN Remove); + #endif /* (NTDDI_VERSION >= NTDDI_VISTASP1) */ + /****************************************************************************** + * Runtime Library Functions * + ******************************************************************************/ + + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + + #ifndef RTL_USE_AVL_TABLES + + NTSYSAPI + VOID + NTAPI + RtlInitializeGenericTable( + _Out_ PRTL_GENERIC_TABLE Table, + _In_ PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, + _In_ PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, + _In_ PRTL_GENERIC_FREE_ROUTINE FreeRoutine, + _In_opt_ PVOID TableContext); + + NTSYSAPI + PVOID + NTAPI + RtlInsertElementGenericTable( + _In_ PRTL_GENERIC_TABLE Table, + _In_reads_bytes_(BufferSize) PVOID Buffer, + _In_ CLONG BufferSize, + _Out_opt_ PBOOLEAN NewElement); + + NTSYSAPI + PVOID + NTAPI + RtlInsertElementGenericTableFull( + _In_ PRTL_GENERIC_TABLE Table, + _In_reads_bytes_(BufferSize) PVOID Buffer, + _In_ CLONG BufferSize, + _Out_opt_ PBOOLEAN NewElement, + _In_ PVOID NodeOrParent, + _In_ TABLE_SEARCH_RESULT SearchResult); + + NTSYSAPI + BOOLEAN + NTAPI + RtlDeleteElementGenericTable( + _In_ PRTL_GENERIC_TABLE Table, + _In_ PVOID Buffer); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlLookupElementGenericTable( + _In_ PRTL_GENERIC_TABLE Table, + _In_ PVOID Buffer); + + NTSYSAPI + PVOID + NTAPI + RtlLookupElementGenericTableFull( + _In_ PRTL_GENERIC_TABLE Table, + _In_ PVOID Buffer, + _Out_ PVOID *NodeOrParent, + _Out_ TABLE_SEARCH_RESULT *SearchResult); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlEnumerateGenericTable( + _In_ PRTL_GENERIC_TABLE Table, + _In_ BOOLEAN Restart); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlEnumerateGenericTableWithoutSplaying( + _In_ PRTL_GENERIC_TABLE Table, + _Inout_ PVOID *RestartKey); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlGetElementGenericTable( + _In_ PRTL_GENERIC_TABLE Table, + _In_ ULONG I); + + NTSYSAPI + ULONG + NTAPI + RtlNumberGenericTableElements( + _In_ PRTL_GENERIC_TABLE Table); + + _Must_inspect_result_ + NTSYSAPI + BOOLEAN + NTAPI + RtlIsGenericTableEmpty( + _In_ PRTL_GENERIC_TABLE Table); + + #endif /* !RTL_USE_AVL_TABLES */ + + #define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8 + + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlSplay( + _Inout_ PRTL_SPLAY_LINKS Links); + + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlDelete( + _In_ PRTL_SPLAY_LINKS Links); + + NTSYSAPI + VOID + NTAPI + RtlDeleteNoSplay( + _In_ PRTL_SPLAY_LINKS Links, + _Inout_ PRTL_SPLAY_LINKS *Root); + + _Must_inspect_result_ + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlSubtreeSuccessor( + _In_ PRTL_SPLAY_LINKS Links); + + _Must_inspect_result_ + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlSubtreePredecessor( + _In_ PRTL_SPLAY_LINKS Links); + + _Must_inspect_result_ + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlRealSuccessor( + _In_ PRTL_SPLAY_LINKS Links); + + _Must_inspect_result_ + NTSYSAPI + PRTL_SPLAY_LINKS + NTAPI + RtlRealPredecessor( + _In_ PRTL_SPLAY_LINKS Links); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _Must_inspect_result_ + NTSYSAPI + BOOLEAN + NTAPI + RtlPrefixUnicodeString( + _In_ PCUNICODE_STRING String1, + _In_ PCUNICODE_STRING String2, + _In_ BOOLEAN CaseInSensitive); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + VOID + NTAPI + RtlUpperString( + _Inout_ PSTRING DestinationString, + _In_ const PSTRING SourceString); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _When_(AllocateDestinationString, _Must_inspect_result_) + NTSYSAPI + NTSTATUS + NTAPI + RtlUpcaseUnicodeString( + _When_(AllocateDestinationString, _Out_ _At_(DestinationString->Buffer, __drv_allocatesMem(Mem))) + _When_(!AllocateDestinationString, _Inout_) + PUNICODE_STRING DestinationString, + _In_ PCUNICODE_STRING SourceString, + _In_ BOOLEAN AllocateDestinationString); + + _IRQL_requires_max_(APC_LEVEL) + NTSYSAPI + VOID + NTAPI + RtlMapGenericMask( + _Inout_ PACCESS_MASK AccessMask, + _In_ PGENERIC_MAPPING GenericMapping); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + RtlVolumeDeviceToDosName( + _In_ PVOID VolumeDeviceObject, + _Out_ PUNICODE_STRING DosName); + + NTSYSAPI + NTSTATUS + NTAPI + RtlGetVersion( + IN OUT PRTL_OSVERSIONINFOW lpVersionInformation); + + NTSYSAPI + NTSTATUS + NTAPI + RtlVerifyVersionInfo( + IN PRTL_OSVERSIONINFOEXW VersionInfo, + IN ULONG TypeMask, + IN ULONGLONG ConditionMask); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _Must_inspect_result_ + NTSYSAPI + LONG + NTAPI + RtlCompareString( + _In_ const PSTRING String1, + _In_ const PSTRING String2, + _In_ BOOLEAN CaseInSensitive); + + NTSYSAPI + VOID + NTAPI + RtlCopyString( + _Out_ PSTRING DestinationString, + _In_opt_ const PSTRING SourceString); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _Must_inspect_result_ + NTSYSAPI + BOOLEAN + NTAPI + RtlEqualString( + _In_ const PSTRING String1, + _In_ const PSTRING String2, + _In_ BOOLEAN CaseInSensitive); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + RtlCharToInteger( + _In_z_ PCSZ String, + _In_opt_ ULONG Base, + _Out_ PULONG Value); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + CHAR + NTAPI + RtlUpperChar( + _In_ CHAR Character); + + NTSYSAPI + ULONG + NTAPI + RtlWalkFrameChain( + _Out_writes_(Count - (Flags >> RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT)) + PVOID *Callers, + _In_ ULONG Count, + _In_ ULONG Flags); + + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + + #if (NTDDI_VERSION >= NTDDI_WINXP) + + + + NTSYSAPI + VOID + NTAPI + RtlInitializeGenericTableAvl( + _Out_ PRTL_AVL_TABLE Table, + _In_ PRTL_AVL_COMPARE_ROUTINE CompareRoutine, + _In_opt_ PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, + _In_opt_ PRTL_AVL_FREE_ROUTINE FreeRoutine, + _In_opt_ PVOID TableContext); + + NTSYSAPI + PVOID + NTAPI + RtlInsertElementGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_reads_bytes_(BufferSize) PVOID Buffer, + _In_ CLONG BufferSize, + _Out_opt_ PBOOLEAN NewElement); + + NTSYSAPI + PVOID + NTAPI + RtlInsertElementGenericTableFullAvl( + _In_ PRTL_AVL_TABLE Table, + _In_reads_bytes_(BufferSize) PVOID Buffer, + _In_ CLONG BufferSize, + _Out_opt_ PBOOLEAN NewElement, + _In_ PVOID NodeOrParent, + _In_ TABLE_SEARCH_RESULT SearchResult); + + NTSYSAPI + BOOLEAN + NTAPI + RtlDeleteElementGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ PVOID Buffer); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlLookupElementGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ PVOID Buffer); + + NTSYSAPI + PVOID + NTAPI + RtlLookupElementGenericTableFullAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ PVOID Buffer, + _Out_ PVOID *NodeOrParent, + _Out_ TABLE_SEARCH_RESULT *SearchResult); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlEnumerateGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ BOOLEAN Restart); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlEnumerateGenericTableWithoutSplayingAvl( + _In_ PRTL_AVL_TABLE Table, + _Inout_ PVOID *RestartKey); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlLookupFirstMatchingElementGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ PVOID Buffer, + _Out_ PVOID *RestartKey); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlEnumerateGenericTableLikeADirectory( + _In_ PRTL_AVL_TABLE Table, + _In_opt_ PRTL_AVL_MATCH_FUNCTION MatchFunction, + _In_opt_ PVOID MatchData, + _In_ ULONG NextFlag, + _Inout_ PVOID *RestartKey, + _Inout_ PULONG DeleteCount, + _In_ PVOID Buffer); + + _Must_inspect_result_ + NTSYSAPI + PVOID + NTAPI + RtlGetElementGenericTableAvl( + _In_ PRTL_AVL_TABLE Table, + _In_ ULONG I); + + NTSYSAPI + ULONG + NTAPI + RtlNumberGenericTableElementsAvl( + _In_ PRTL_AVL_TABLE Table); + + _Must_inspect_result_ + NTSYSAPI + BOOLEAN + NTAPI + RtlIsGenericTableEmptyAvl( + _In_ PRTL_AVL_TABLE Table); + + + #endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ + + + #if (NTDDI_VERSION >= NTDDI_VISTA) + + + _IRQL_requires_max_(APC_LEVEL) + NTSYSAPI + VOID + NTAPI + RtlRunOnceInitialize( + _Out_ PRTL_RUN_ONCE RunOnce); + + _IRQL_requires_max_(APC_LEVEL) + _Maybe_raises_SEH_exception_ + NTSYSAPI + NTSTATUS + NTAPI + RtlRunOnceExecuteOnce( + _Inout_ PRTL_RUN_ONCE RunOnce, + _In_ __inner_callback PRTL_RUN_ONCE_INIT_FN InitFn, + _Inout_opt_ PVOID Parameter, + _Outptr_opt_result_maybenull_ PVOID *Context); + + _IRQL_requires_max_(APC_LEVEL) + _Must_inspect_result_ + NTSYSAPI + NTSTATUS + NTAPI + RtlRunOnceBeginInitialize( + _Inout_ PRTL_RUN_ONCE RunOnce, + _In_ ULONG Flags, + _Outptr_opt_result_maybenull_ PVOID *Context); + + _IRQL_requires_max_(APC_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + RtlRunOnceComplete( + _Inout_ PRTL_RUN_ONCE RunOnce, + _In_ ULONG Flags, + _In_opt_ PVOID Context); + + NTSYSAPI + BOOLEAN + NTAPI + RtlGetProductInfo( + _In_ ULONG OSMajorVersion, + _In_ ULONG OSMinorVersion, + _In_ ULONG SpMajorVersion, + _In_ ULONG SpMinorVersion, + _Out_ PULONG ReturnedProductType); + + + #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + + _Must_inspect_result_ + NTSYSAPI + BOOLEAN + NTAPI + RtlCreateHashTable( + _Inout_ _When_(NULL == *HashTable, __drv_allocatesMem(Mem)) + PRTL_DYNAMIC_HASH_TABLE *HashTable, + _In_ ULONG Shift, + _In_ _Reserved_ ULONG Flags); + + NTSYSAPI + VOID + NTAPI + RtlDeleteHashTable( + _In_ _When_((HashTable->Flags & RTL_HASH_ALLOCATED_HEADER), __drv_freesMem(Mem) _Post_invalid_) + PRTL_DYNAMIC_HASH_TABLE HashTable); + + NTSYSAPI + BOOLEAN + NTAPI + RtlInsertEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _In_ __drv_aliasesMem PRTL_DYNAMIC_HASH_TABLE_ENTRY Entry, + _In_ ULONG_PTR Signature, + _Inout_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context); + + NTSYSAPI + BOOLEAN + NTAPI + RtlRemoveEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _In_ PRTL_DYNAMIC_HASH_TABLE_ENTRY Entry, + _Inout_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context); + + _Must_inspect_result_ + NTSYSAPI + PRTL_DYNAMIC_HASH_TABLE_ENTRY + NTAPI + RtlLookupEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _In_ ULONG_PTR Signature, + _Out_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context); + + _Must_inspect_result_ + NTSYSAPI + PRTL_DYNAMIC_HASH_TABLE_ENTRY + NTAPI + RtlGetNextEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _In_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context); + + NTSYSAPI + BOOLEAN + NTAPI + RtlInitEnumerationHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Out_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + _Must_inspect_result_ + NTSYSAPI + PRTL_DYNAMIC_HASH_TABLE_ENTRY + NTAPI + RtlEnumerateEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + NTSYSAPI + VOID + NTAPI + RtlEndEnumerationHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + NTSYSAPI + BOOLEAN + NTAPI + RtlInitWeakEnumerationHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Out_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + _Must_inspect_result_ + NTSYSAPI + PRTL_DYNAMIC_HASH_TABLE_ENTRY + NTAPI + RtlWeaklyEnumerateEntryHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + NTSYSAPI + VOID + NTAPI + RtlEndWeakEnumerationHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable, + _Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator); + + NTSYSAPI + BOOLEAN + NTAPI + RtlExpandHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable); + + NTSYSAPI + BOOLEAN + NTAPI + RtlContractHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable); + + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + + #if defined(_AMD64_) || defined(_IA64_) + + + + //DECLSPEC_DEPRECATED_DDK_WINXP + FORCEINLINE + LARGE_INTEGER + NTAPI_INLINE + RtlLargeIntegerDivide( + _In_ LARGE_INTEGER Dividend, + _In_ LARGE_INTEGER Divisor, + _Out_opt_ PLARGE_INTEGER Remainder) + { + LARGE_INTEGER ret; + ret.QuadPart = Dividend.QuadPart / Divisor.QuadPart; + if (Remainder) + Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart; + return ret; + } + + #else + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + NTSYSAPI + LARGE_INTEGER + NTAPI + RtlLargeIntegerDivide( + _In_ LARGE_INTEGER Dividend, + _In_ LARGE_INTEGER Divisor, + _Out_opt_ PLARGE_INTEGER Remainder); + #endif + + + #endif /* defined(_AMD64_) || defined(_IA64_) */ + + + + #ifdef RTL_USE_AVL_TABLES + + #define RtlInitializeGenericTable RtlInitializeGenericTableAvl + #define RtlInsertElementGenericTable RtlInsertElementGenericTableAvl + #define RtlInsertElementGenericTableFull RtlInsertElementGenericTableFullAvl + #define RtlDeleteElementGenericTable RtlDeleteElementGenericTableAvl + #define RtlLookupElementGenericTable RtlLookupElementGenericTableAvl + #define RtlLookupElementGenericTableFull RtlLookupElementGenericTableFullAvl + #define RtlEnumerateGenericTable RtlEnumerateGenericTableAvl + #define RtlEnumerateGenericTableWithoutSplaying RtlEnumerateGenericTableWithoutSplayingAvl + #define RtlGetElementGenericTable RtlGetElementGenericTableAvl + #define RtlNumberGenericTableElements RtlNumberGenericTableElementsAvl + #define RtlIsGenericTableEmpty RtlIsGenericTableEmptyAvl + + #endif /* RTL_USE_AVL_TABLES */ + + #define RtlInitializeSplayLinks(Links) { \ + PRTL_SPLAY_LINKS _SplayLinks; \ + _SplayLinks = (PRTL_SPLAY_LINKS)(Links); \ + _SplayLinks->Parent = _SplayLinks; \ + _SplayLinks->LeftChild = NULL; \ + _SplayLinks->RightChild = NULL; \ + } + + #define RtlIsLeftChild(Links) \ + (RtlLeftChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) + + #define RtlIsRightChild(Links) \ + (RtlRightChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) + + #define RtlRightChild(Links) \ + ((PRTL_SPLAY_LINKS)(Links))->RightChild + + #define RtlIsRoot(Links) \ + (RtlParent(Links) == (PRTL_SPLAY_LINKS)(Links)) + + #define RtlLeftChild(Links) \ + ((PRTL_SPLAY_LINKS)(Links))->LeftChild + + #define RtlParent(Links) \ + ((PRTL_SPLAY_LINKS)(Links))->Parent + + #define RtlInsertAsLeftChild(ParentLinks,ChildLinks) \ + { \ + PRTL_SPLAY_LINKS _SplayParent; \ + PRTL_SPLAY_LINKS _SplayChild; \ + _SplayParent = (PRTL_SPLAY_LINKS)(ParentLinks); \ + _SplayChild = (PRTL_SPLAY_LINKS)(ChildLinks); \ + _SplayParent->LeftChild = _SplayChild; \ + _SplayChild->Parent = _SplayParent; \ + } + + #define RtlInsertAsRightChild(ParentLinks,ChildLinks) \ + { \ + PRTL_SPLAY_LINKS _SplayParent; \ + PRTL_SPLAY_LINKS _SplayChild; \ + _SplayParent = (PRTL_SPLAY_LINKS)(ParentLinks); \ + _SplayChild = (PRTL_SPLAY_LINKS)(ChildLinks); \ + _SplayParent->RightChild = _SplayChild; \ + _SplayChild->Parent = _SplayParent; \ + } + + #if !defined(MIDL_PASS) + + FORCEINLINE + LUID + NTAPI_INLINE + RtlConvertLongToLuid( + _In_ LONG Val) + { + LUID Luid; + LARGE_INTEGER Temp; + + Temp.QuadPart = Val; + Luid.LowPart = Temp.u.LowPart; + Luid.HighPart = Temp.u.HighPart; + return Luid; + } + + FORCEINLINE + LUID + NTAPI_INLINE + RtlConvertUlongToLuid( + _In_ ULONG Val) + { + LUID Luid; + + Luid.LowPart = Val; + Luid.HighPart = 0; + return Luid; + } + + #endif /* !defined(MIDL_PASS) */ + + #if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_) + #define RtlGetCallersAddress(CallersAddress, CallersCaller) \ + *CallersAddress = (PVOID)_ReturnAddress(); \ + *CallersCaller = NULL; + #else + #if (NTDDI_VERSION >= NTDDI_WIN2K) + NTSYSAPI + VOID + NTAPI + RtlGetCallersAddress( + _Out_ PVOID *CallersAddress, + _Out_ PVOID *CallersCaller); + #endif + #endif + + #if !defined(MIDL_PASS) && !defined(SORTPP_PASS) + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + FORCEINLINE + VOID + NTAPI + RtlInitHashTableContext( + _Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context) + { + Context->ChainHead = NULL; + Context->PrevLinkage = NULL; + } + + FORCEINLINE + VOID + NTAPI + RtlInitHashTableContextFromEnumerator( + _Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context, + _In_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator) + { + Context->ChainHead = Enumerator->ChainHead; + Context->PrevLinkage = Enumerator->HashEntry.Linkage.Blink; + } + + FORCEINLINE + VOID + NTAPI + RtlReleaseHashTableContext( + _Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context) + { + UNREFERENCED_PARAMETER(Context); + return; + } + + FORCEINLINE + ULONG + NTAPI + RtlTotalBucketsHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable) + { + return HashTable->TableSize; + } + + FORCEINLINE + ULONG + NTAPI + RtlNonEmptyBucketsHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable) + { + return HashTable->NonEmptyBuckets; + } + + FORCEINLINE + ULONG + NTAPI + RtlEmptyBucketsHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable) + { + return HashTable->TableSize - HashTable->NonEmptyBuckets; + } + + FORCEINLINE + ULONG + NTAPI + RtlTotalEntriesHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable) + { + return HashTable->NumEntries; + } + + FORCEINLINE + ULONG + NTAPI + RtlActiveEnumeratorsHashTable( + _In_ PRTL_DYNAMIC_HASH_TABLE HashTable) + { + return HashTable->NumEnumerators; + } + + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + #endif /* !defined(MIDL_PASS) && !defined(SORTPP_PASS) */ + + /****************************************************************************** + * Security Manager Functions * + ******************************************************************************/ + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTKERNELAPI + BOOLEAN + NTAPI + SeSinglePrivilegeCheck( + _In_ LUID PrivilegeValue, + _In_ KPROCESSOR_MODE PreviousMode); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + + /****************************************************************************** + * ZwXxx Functions * + ******************************************************************************/ + + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwAllocateLocallyUniqueId( + _Out_ PLUID Luid); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwTerminateProcess( + _In_opt_ HANDLE ProcessHandle, + _In_ NTSTATUS ExitStatus); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwOpenProcess( + _Out_ PHANDLE ProcessHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PCLIENT_ID ClientId); + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS + NTAPI + ZwCancelTimer( + _In_ HANDLE TimerHandle, + _Out_opt_ PBOOLEAN CurrentState); + + _IRQL_requires_max_(PASSIVE_LEVEL) + _When_(return == 0, __drv_allocatesMem(TimerObject)) + NTSTATUS + NTAPI + ZwCreateTimer( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ TIMER_TYPE TimerType); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS + NTAPI + ZwOpenTimer( + _Out_ PHANDLE TimerHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwSetInformationThread( + _In_ HANDLE ThreadHandle, + _In_ THREADINFOCLASS ThreadInformationClass, + _In_reads_bytes_(ThreadInformationLength) PVOID ThreadInformation, + _In_ ULONG ThreadInformationLength); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS + NTAPI + ZwSetTimer( + _In_ HANDLE TimerHandle, + _In_ PLARGE_INTEGER DueTime, + _In_opt_ PTIMER_APC_ROUTINE TimerApcRoutine, + _In_opt_ PVOID TimerContext, + _In_ BOOLEAN ResumeTimer, + _In_opt_ LONG Period, + _Out_opt_ PBOOLEAN PreviousState); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwDisplayString( + _In_ PUNICODE_STRING String); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwPowerInformation( + _In_ POWER_INFORMATION_LEVEL PowerInformationLevel, + _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, + _In_ ULONG OutputBufferLength); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwQueryVolumeInformationFile( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_writes_bytes_(Length) PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSYSAPI + NTSTATUS + NTAPI + ZwDeviceIoControlFile( + _In_ HANDLE FileHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _In_ ULONG IoControlCode, + _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, + _In_ ULONG OutputBufferLength); + + #endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ + + + #if (NTDDI_VERSION >= NTDDI_WIN7) + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS + NTAPI + ZwSetTimerEx( + _In_ HANDLE TimerHandle, + _In_ TIMER_SET_INFORMATION_CLASS TimerSetInformationClass, + _Inout_updates_bytes_opt_(TimerSetInformationLength) PVOID TimerSetInformation, + _In_ ULONG TimerSetInformationLength); + #endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ + + + + /* UNSORTED */ + + #define VER_SET_CONDITION(ConditionMask, TypeBitMask, ComparisonType) \ + ((ConditionMask) = VerSetConditionMask((ConditionMask), \ + (TypeBitMask), (ComparisonType))) + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + NTSYSAPI + ULONGLONG + NTAPI + VerSetConditionMask( + IN ULONGLONG ConditionMask, + IN ULONG TypeMask, + IN UCHAR Condition); + #endif + + typedef struct _KERNEL_USER_TIMES { + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + } KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; + + /* NtXxx Functions */ + + typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION { + SystemFirmwareTable_Enumerate, + SystemFirmwareTable_Get + } SYSTEM_FIRMWARE_TABLE_ACTION; + + typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { + ULONG ProviderSignature; + SYSTEM_FIRMWARE_TABLE_ACTION Action; + ULONG TableID; + ULONG TableBufferLength; + UCHAR TableBuffer[ANYSIZE_ARRAY]; + } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; + + typedef NTSTATUS + (__cdecl *PFNFTH)( + _Inout_ PSYSTEM_FIRMWARE_TABLE_INFORMATION SystemFirmwareTableInfo); + + typedef struct _SYSTEM_FIRMWARE_TABLE_HANDLER { + ULONG ProviderSignature; + BOOLEAN Register; + PFNFTH FirmwareTableHandler; + PVOID DriverObject; + } SYSTEM_FIRMWARE_TABLE_HANDLER, *PSYSTEM_FIRMWARE_TABLE_HANDLER; + + typedef ULONG_PTR + (NTAPI *PDRIVER_VERIFIER_THUNK_ROUTINE)( + _In_ PVOID Context); + + typedef struct _DRIVER_VERIFIER_THUNK_PAIRS { + PDRIVER_VERIFIER_THUNK_ROUTINE PristineRoutine; + PDRIVER_VERIFIER_THUNK_ROUTINE NewRoutine; + } DRIVER_VERIFIER_THUNK_PAIRS, *PDRIVER_VERIFIER_THUNK_PAIRS; + + #define DRIVER_VERIFIER_SPECIAL_POOLING 0x0001 + #define DRIVER_VERIFIER_FORCE_IRQL_CHECKING 0x0002 + #define DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES 0x0004 + #define DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS 0x0008 + #define DRIVER_VERIFIER_IO_CHECKING 0x0010 + + #define SHARED_GLOBAL_FLAGS_ERROR_PORT_V 0x0 + #define SHARED_GLOBAL_FLAGS_ERROR_PORT (1UL << SHARED_GLOBAL_FLAGS_ERROR_PORT_V) + + #define SHARED_GLOBAL_FLAGS_ELEVATION_ENABLED_V 0x1 + #define SHARED_GLOBAL_FLAGS_ELEVATION_ENABLED (1UL << SHARED_GLOBAL_FLAGS_ELEVATION_ENABLED_V) + + #define SHARED_GLOBAL_FLAGS_VIRT_ENABLED_V 0x2 + #define SHARED_GLOBAL_FLAGS_VIRT_ENABLED (1UL << SHARED_GLOBAL_FLAGS_VIRT_ENABLED_V) + + #define SHARED_GLOBAL_FLAGS_INSTALLER_DETECT_ENABLED_V 0x3 + #define SHARED_GLOBAL_FLAGS_INSTALLER_DETECT_ENABLED \ + (1UL << SHARED_GLOBAL_FLAGS_INSTALLER_DETECT_ENABLED_V) + + #define SHARED_GLOBAL_FLAGS_SPARE_V 0x4 + #define SHARED_GLOBAL_FLAGS_SPARE \ + (1UL << SHARED_GLOBAL_FLAGS_SPARE_V) + + #define SHARED_GLOBAL_FLAGS_DYNAMIC_PROC_ENABLED_V 0x5 + #define SHARED_GLOBAL_FLAGS_DYNAMIC_PROC_ENABLED \ + (1UL << SHARED_GLOBAL_FLAGS_DYNAMIC_PROC_ENABLED_V) + + #define SHARED_GLOBAL_FLAGS_SEH_VALIDATION_ENABLED_V 0x6 + #define SHARED_GLOBAL_FLAGS_SEH_VALIDATION_ENABLED \ + (1UL << SHARED_GLOBAL_FLAGS_SEH_VALIDATION_ENABLED_V) + + #define EX_INIT_BITS(Flags, Bit) \ + *((Flags)) |= (Bit) // Safe to use before concurrently accessible + + #define EX_TEST_SET_BIT(Flags, Bit) \ + InterlockedBitTestAndSet ((PLONG)(Flags), (Bit)) + + #define EX_TEST_CLEAR_BIT(Flags, Bit) \ + InterlockedBitTestAndReset ((PLONG)(Flags), (Bit)) + + #define PCCARD_MAP_ERROR 0x01 + #define PCCARD_DEVICE_PCI 0x10 + + #define PCCARD_SCAN_DISABLED 0x01 + #define PCCARD_MAP_ZERO 0x02 + #define PCCARD_NO_TIMER 0x03 + #define PCCARD_NO_PIC 0x04 + #define PCCARD_NO_LEGACY_BASE 0x05 + #define PCCARD_DUP_LEGACY_BASE 0x06 + #define PCCARD_NO_CONTROLLERS 0x07 + + #define MAXIMUM_EXPANSION_SIZE (KERNEL_LARGE_STACK_SIZE - (PAGE_SIZE / 2)) + + /* Filesystem runtime library routines */ + + #if (NTDDI_VERSION >= NTDDI_WIN2K) + _Must_inspect_result_ + NTKERNELAPI + BOOLEAN + NTAPI + FsRtlIsTotalDeviceFailure( + _In_ NTSTATUS Status); + #endif + + #ifdef __cplusplus + } + #endif diff --cc reactos/lib/drivers/directory.rbuild index 2c0c011058a,00000000000,2dd51908b4f..2dd51908b4f mode 100644,000000,100644..100644 --- a/reactos/lib/drivers/directory.rbuild +++ b/reactos/lib/drivers/directory.rbuild @@@@ -1,19 -1,0 -1,22 +1,22 @@@@ + + + + + + ++ ++ ++ + + + + + + + + + + + + + diff --cc reactos/lib/drivers/hidparser/CMakeLists.txt index 00000000000,00000000000,b0b15dd22f4..b0b15dd22f4 mode 000000,000000,100644..100644 --- a/reactos/lib/drivers/hidparser/CMakeLists.txt +++ b/reactos/lib/drivers/hidparser/CMakeLists.txt diff --cc reactos/lib/drivers/hidparser/api.c index 00000000000,16bbe3210fa,16bbe3210fa..16bbe3210fa mode 000000,100644,100644..100644 --- a/reactos/lib/drivers/hidparser/api.c +++ b/reactos/lib/drivers/hidparser/api.c diff --cc reactos/lib/drivers/hidparser/context.c index 00000000000,3bf3662883c,3bf3662883c..3bf3662883c mode 000000,100644,100644..100644 --- a/reactos/lib/drivers/hidparser/context.c +++ b/reactos/lib/drivers/hidparser/context.c diff --cc reactos/lib/drivers/hidparser/hidparser.c index 00000000000,1b15fd74058,1b15fd74058..1b15fd74058 mode 000000,100644,100644..100644 --- a/reactos/lib/drivers/hidparser/hidparser.c +++ b/reactos/lib/drivers/hidparser/hidparser.c diff --cc reactos/lib/drivers/hidparser/hidparser.h index 00000000000,00000000000,00000000000..beb46ecc891 new file mode 100644 --- /dev/null +++ b/reactos/lib/drivers/hidparser/hidparser.h @@@@ -1,0 -1,0 -1,0 +1,449 @@@@ +++/* +++ * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface +++ * LICENSE: GPL - See COPYING in the top level directory +++ * FILE: lib/drivers/hidparser/hidparser.c +++ * PURPOSE: HID Parser +++ * PROGRAMMERS: +++ * Michael Martin (michael.martin@reactos.org) +++ * Johannes Anderwald (johannes.anderwald@reactos.org) +++ */ +++ +++#pragma once +++ +++#define _HIDPI_ +++#define _HIDPI_NO_FUNCTION_MACROS_ +++#include +++#include +++#include +++#ifndef NDEBUG +++#define NDEBUG +++#endif +++#include +++ +++// +++// function prototypes +++// +++typedef PVOID (NTAPI *PHIDPARSER_ALLOC_FUNCTION)(ULONG Size); +++typedef VOID (NTAPI *PHIDPARSER_FREE_FUNCTION)(PVOID Item); +++typedef VOID (NTAPI *PHIDPARSER_ZERO_FUNCTION)(PVOID Item, ULONG Size); +++typedef VOID (NTAPI *PHIDPARSER_COPY_FUNCTION)(PVOID Target, PVOID Source, ULONG Size); +++typedef VOID (NTAPI *PHIDPARSER_DEBUG_FUNCTION)(LPCSTR Src, ...); +++ +++// +++// status code +++// +++typedef long HIDPARSER_STATUS; +++ +++// +++// result codes +++// +++typedef enum +++{ +++ HIDPARSER_STATUS_SUCCESS = 0, +++ HIDPARSER_STATUS_INSUFFICIENT_RESOURCES = -1, +++ HIDPARSER_STATUS_NOT_IMPLEMENTED = -2, +++ HIDPARSER_STATUS_REPORT_NOT_FOUND = -3, +++ HIDPARSER_STATUS_COLLECTION_NOT_FOUND = -4, +++ HIDPARSER_STATUS_INVALID_REPORT_LENGTH = -5, +++ HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6, +++ HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7, +++ HIDPARSER_STATUS_USAGE_NOT_FOUND = -8, +++ HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9 +++}HIDPARSER_STATUS_CODES; +++ +++typedef struct +++{ +++ // +++ // size of struct +++ // +++ unsigned long Size; +++ +++ // +++ // allocation function +++ // +++ PHIDPARSER_ALLOC_FUNCTION Alloc; +++ +++ // +++ // free function +++ // +++ PFREE_FUNCTION Free; +++ +++ // +++ // zero function +++ // +++ PHIDPARSER_ZERO_FUNCTION Zero; +++ +++ // +++ // copy function +++ // +++ PHIDPARSER_COPY_FUNCTION Copy; +++ +++ // +++ // debug function +++ // +++ PHIDPARSER_DEBUG_FUNCTION Debug; +++}HID_PARSER, *PHID_PARSER; +++ +++VOID +++HidParser_InitParser( +++ IN PHIDPARSER_ALLOC_FUNCTION AllocFunction, +++ IN PHIDPARSER_FREE_FUNCTION FreeFunction, +++ IN PHIDPARSER_ZERO_FUNCTION ZeroFunction, +++ IN PHIDPARSER_COPY_FUNCTION CopyFunction, +++ IN PHIDPARSER_DEBUG_FUNCTION DebugFunction, +++ OUT PHID_PARSER Parser); +++ +++NTSTATUS +++NTAPI +++HidParser_GetCollectionDescription( +++ IN PHID_PARSER Parser, +++ IN PHIDP_REPORT_DESCRIPTOR ReportDesc, +++ IN ULONG DescLength, +++ IN POOL_TYPE PoolType, +++ OUT PHIDP_DEVICE_DESC DeviceDescription); +++ +++VOID +++NTAPI +++HidParser_FreeCollectionDescription( +++ IN PHID_PARSER Parser, +++ IN PHIDP_DEVICE_DESC DeviceDescription); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetCaps( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ OUT PHIDP_CAPS Capabilities); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetSpecificValueCaps( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN USAGE Usage, +++ OUT PHIDP_VALUE_CAPS ValueCaps, +++ IN OUT PULONG ValueCapsLength); +++ +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetButtonCaps( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ HIDP_REPORT_TYPE ReportType, +++ PHIDP_BUTTON_CAPS ButtonCaps, +++ PUSHORT ButtonCapsLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetSpecificButtonCaps( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN USAGE Usage, +++ OUT PHIDP_BUTTON_CAPS ButtonCaps, +++ IN OUT PULONG ButtonCapsLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetScaledUsageValue( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection OPTIONAL, +++ IN USAGE Usage, +++ OUT PLONG UsageValue, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetData( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ OUT PHIDP_DATA DataList, +++ IN OUT PULONG DataLength, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetExtendedAttributes( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USHORT DataIndex, +++ OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, +++ IN OUT PULONG LengthAttributes); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetLinkCollectionNodes( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, +++ IN OUT PULONG LinkCollectionNodesLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetUsageValue( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN USAGE Usage, +++ OUT PULONG UsageValue, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_UsageListDifference( +++ IN PUSAGE PreviousUsageList, +++ IN PUSAGE CurrentUsageList, +++ OUT PUSAGE BreakUsageList, +++ OUT PUSAGE MakeUsageList, +++ IN ULONG UsageListLength); +++ +++ +++HIDAPI +++ULONG +++NTAPI +++HidParser_MaxUsageListLength( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage OPTIONAL); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetUsages( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection OPTIONAL, +++ OUT USAGE *UsageList, +++ IN OUT ULONG *UsageLength, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetUsagesEx( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USHORT LinkCollection, +++ OUT PUSAGE_AND_PAGE ButtonList, +++ IN OUT ULONG *UsageLength, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++ +++NTSTATUS +++NTAPI +++HidParser_SysPowerEvent ( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN PCHAR HidPacket, +++ IN USHORT HidPacketLength, +++ OUT PULONG OutputBuffer); +++ +++NTSTATUS +++NTAPI +++HidParser_SysPowerCaps ( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ OUT PULONG OutputBuffer); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetUsageValueArray( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection OPTIONAL, +++ IN USAGE Usage, +++ OUT PCHAR UsageValue, +++ IN USHORT UsageValueByteLength, +++ IN PCHAR Report, +++ IN ULONG ReportLength); +++ +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_UsageAndPageListDifference( +++ IN PUSAGE_AND_PAGE PreviousUsageList, +++ IN PUSAGE_AND_PAGE CurrentUsageList, +++ OUT PUSAGE_AND_PAGE BreakUsageList, +++ OUT PUSAGE_AND_PAGE MakeUsageList, +++ IN ULONG UsageListLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_UnsetUsages( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN PUSAGE UsageList, +++ IN OUT PULONG UsageLength, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_TranslateUsagesToI8042ScanCodes( +++ IN PUSAGE ChangedUsageList, +++ IN ULONG UsageListLength, +++ IN HIDP_KEYBOARD_DIRECTION KeyAction, +++ IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, +++ IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, +++ IN PVOID InsertCodesContext); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_TranslateUsageAndPagesToI8042ScanCodes( +++ IN PHID_PARSER Parser, +++ IN PUSAGE_AND_PAGE ChangedUsageList, +++ IN ULONG UsageListLength, +++ IN HIDP_KEYBOARD_DIRECTION KeyAction, +++ IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, +++ IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, +++ IN PVOID InsertCodesContext); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_SetUsages( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN PUSAGE UsageList, +++ IN OUT PULONG UsageLength, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_SetUsageValueArray( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection OPTIONAL, +++ IN USAGE Usage, +++ IN PCHAR UsageValue, +++ IN USHORT UsageValueByteLength, +++ OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_SetUsageValue( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection, +++ IN USAGE Usage, +++ IN ULONG UsageValue, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_SetScaledUsageValue( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN USAGE UsagePage, +++ IN USHORT LinkCollection OPTIONAL, +++ IN USAGE Usage, +++ IN LONG UsageValue, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_SetData( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN PHIDP_DATA DataList, +++ IN OUT PULONG DataLength, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDAPI +++ULONG +++NTAPI +++HidParser_MaxDataListLength( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_InitializeReportForID( +++ IN PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ IN HIDP_REPORT_TYPE ReportType, +++ IN UCHAR ReportID, +++ IN OUT PCHAR Report, +++ IN ULONG ReportLength); +++ +++HIDPARSER_STATUS +++HidParser_TranslateUsage( +++ IN PHID_PARSER Parser, +++ IN USAGE Usage, +++ IN HIDP_KEYBOARD_DIRECTION KeyAction, +++ IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, +++ IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, +++ IN PVOID InsertCodesContext); +++ +++HIDAPI +++NTSTATUS +++NTAPI +++HidParser_GetValueCaps( +++ PHID_PARSER Parser, +++ IN PVOID CollectionContext, +++ HIDP_REPORT_TYPE ReportType, +++ PHIDP_VALUE_CAPS ValueCaps, +++ PULONG ValueCapsLength); diff --cc reactos/lib/drivers/hidparser/hidparser.rbuild index 00000000000,00000000000,61416b5f723..61416b5f723 mode 000000,000000,100644..100644 --- a/reactos/lib/drivers/hidparser/hidparser.rbuild +++ b/reactos/lib/drivers/hidparser/hidparser.rbuild diff --cc reactos/lib/drivers/hidparser/parser.c index 00000000000,0705788aa99,0705788aa99..0705788aa99 mode 000000,100644,100644..100644 --- a/reactos/lib/drivers/hidparser/parser.c +++ b/reactos/lib/drivers/hidparser/parser.c diff --cc reactos/lib/drivers/hidparser/parser.h index 00000000000,ef0d7f3e421,ef0d7f3e421..ef0d7f3e421 mode 000000,100644,100644..100644 --- a/reactos/lib/drivers/hidparser/parser.h +++ b/reactos/lib/drivers/hidparser/parser.h diff --cc reactos/media/inf/cdrom.inf index eca08d293fe,4b06ab1a1c7,4b06ab1a1c7..4b06ab1a1c7 Binary files differ diff --cc reactos/media/inf/input.inf index 00000000000,aa0d04302f7,aa0d04302f7..aa0d04302f7 mode 000000,100644,100644..100644 --- a/reactos/media/inf/input.inf +++ b/reactos/media/inf/input.inf diff --cc reactos/media/inf/keyboard.inf index 38a2f7a0187,41f79d35a77,41f79d35a77..41f79d35a77 Binary files differ diff --cc reactos/media/inf/msmouse.inf index 2d5e6fed22c,e33232cce4e,e33232cce4e..e33232cce4e Binary files differ diff --cc reactos/media/inf/syssetup.inf index f015a13c8fa,00000000000,1c7cbd5df5d..1c7cbd5df5d mode 100644,000000,100644..100644 --- a/reactos/media/inf/syssetup.inf +++ b/reactos/media/inf/syssetup.inf @@@@ -1,87 -1,0 -1,88 +1,88 @@@@ + [Version] + Signature = $Windows NT$ + ClassGUID = {00000000-0000-0000-0000-000000000000} + + [DeviceInfsToInstall] + battery.inf + cdrom.inf + cpu.inf + disk.inf + display.inf + fdc.inf + hal.inf + hdc.inf ++ input.inf + keyboard.inf + machine.inf + msmouse.inf + NET_NIC.inf + ports.inf + scsi.inf + unknown.inf + usbport.inf + audio.inf + ks.inf + + [RegistrationPhase2] + RegisterDlls = OleControlDlls + + [OleControlDlls] + 11,,atl.dll,1 + 11,,actxprxy.dll,1 + 11,,amstream.dll,1 + 11,,avifil32.dll,1 + 11,,browseui.dll,1 + 11,,comcat.dll,1 + 11,,comctl32.dll,2 + 11,,cryptdlg.dll,1 + 11,,cryptnet.dll,1 + 11,,ddraw.dll,1 + 11,,devenum.dll,1 + 11,,dinput.dll,1 + 11,,dinput8.dll,1 + 11,,dmusic.dll,1 + 11,,dplayx.dll,1 + 11,,dsound.dll,1 + 11,,dxdiagn.dll,1 + 11,,hhctrl.ocx,1 + 11,,hlink.dll,1 + 11,,hnetcfg.dll,1 + 11,,inetcomm.dll,1 + 11,,inseng.dll,1 + 11,,itss.dll,1 + 11,,jscript.dll,1 + 11,,ksproxy.ax,1 + 11,,mlang.dll,1 + 11,,mscat32.dll,1 + 11,,msctf.dll,1 + 11,,mshtml.dll,3 + 11,,msi.dll,1 + 11,,msimtf.dll,1 + 11,,msisip.dll,1 + 11,,mstask.dll,1 + 11,,msxml3.dll,1 + 11,,netcfgx.dll,1 + 11,,netshell.dll,1 + 11,,objsel.dll,1 + 11,,ole32.dll,1 + 11,,oleacc.dll,1 + 11,,oleaut32.dll,1 + 11,,olepro32.dll,1 + 11,,pstorec.dll,1 + 11,,qedit.dll,1 + 11,,qmgr.dll,1 + 11,,qmgrprxy.dll,1 + 11,,quartz.dll,1 + 11,,rpcrt4.dll,1 + 11,,rsabase.dll,1 + 11,,rsaenh.dll,1 + 11,,shdocvw.dll,3 + 11,,shell32.dll,3 + 11,,softpub.dll,1 + 11,,sti.dll,1 + 11,,urlmon.dll,3 + 11,,windowscodecs.dll,1 + 11,,winhttp.dll,1 + 11,,wininet.dll,2 + 11,,wintrust.dll,1 + 11,,wuapi.dll,1 diff --cc reactos/media/inf/usb.inf index c2c95ab4720,02adc85a262,02adc85a262..02adc85a262 Binary files differ diff --cc reactos/media/inf/usbport.inf index 246f6f7e775,d72a801c21e,d72a801c21e..d72a801c21e Binary files differ diff --cc reactos/media/inf/usbstor.inf index 4555b17050d,0e330984c72,0e330984c72..0e330984c72 Binary files differ diff --cc reactos/ntoskrnl/io/iomgr/device.c index f5f6dd6284b,00000000000,e73f989bd7c..e73f989bd7c mode 100644,000000,100644..100644 --- a/reactos/ntoskrnl/io/iomgr/device.c +++ b/reactos/ntoskrnl/io/iomgr/device.c @@@@ -1,1752 -1,0 -1,1752 +1,1752 @@@@ + /* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/io/device.c + * PURPOSE: Device Object Management, including Notifications and Queues. + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Filip Navara (navaraf@reactos.org) + * Hervé Poussineau (hpoussin@reactos.org) + */ + + /* INCLUDES *******************************************************************/ + + #include + #define NDEBUG + #include + + /* GLOBALS ********************************************************************/ + + ULONG IopDeviceObjectNumber = 0; + LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead; + KSPIN_LOCK ShutdownListLock; + extern LIST_ENTRY IopDiskFileSystemQueueHead; + extern LIST_ENTRY IopCdRomFileSystemQueueHead; + extern LIST_ENTRY IopTapeFileSystemQueueHead; + extern ERESOURCE IopDatabaseResource; + + /* PRIVATE FUNCTIONS **********************************************************/ + + VOID + NTAPI + IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver) + { + PDEVICE_OBJECT DeviceObject; + PAGED_CODE(); + + /* Set the driver as initialized */ + Driver->Flags |= DRVO_INITIALIZED; + DeviceObject = Driver->DeviceObject; + while (DeviceObject) + { + /* Set every device as initialized too */ + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + DeviceObject = DeviceObject->NextDevice; + } + } + + VOID + NTAPI + IopDeleteDevice(IN PVOID ObjectBody) + { + PDEVICE_OBJECT DeviceObject = ObjectBody; + PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject); + PAGED_CODE(); + + /* Cleanup and free the device node */ + if (DeviceNode) + IopFreeDeviceNode(DeviceNode); + + /* Dereference the driver object, referenced in IoCreateDevice */ + if (DeviceObject->DriverObject) + ObDereferenceObject(DeviceObject->DriverObject); + } + + + PDEVICE_OBJECT + NTAPI + IopAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice, + OUT PDEVICE_OBJECT *AttachedToDeviceObject OPTIONAL) + { + PDEVICE_OBJECT AttachedDevice; + PEXTENDED_DEVOBJ_EXTENSION SourceDeviceExtension; + + /* Get the Attached Device and source extension */ + AttachedDevice = IoGetAttachedDevice(TargetDevice); + SourceDeviceExtension = IoGetDevObjExtension(SourceDevice); + ASSERT(SourceDeviceExtension->AttachedTo == NULL); + + /* Make sure that it's in a correct state */ + if ((AttachedDevice->Flags & DO_DEVICE_INITIALIZING) || + (IoGetDevObjExtension(AttachedDevice)->ExtensionFlags & + (DOE_UNLOAD_PENDING | + DOE_DELETE_PENDING | + DOE_REMOVE_PENDING | + DOE_REMOVE_PROCESSED))) + { + /* Device was unloading or being removed */ + AttachedDevice = NULL; + } + else + { + /* Update atached device fields */ + AttachedDevice->AttachedDevice = SourceDevice; + AttachedDevice->Spare1++; + + /* Update the source with the attached data */ + SourceDevice->StackSize = AttachedDevice->StackSize + 1; + SourceDevice->AlignmentRequirement = AttachedDevice-> + AlignmentRequirement; + SourceDevice->SectorSize = AttachedDevice->SectorSize; + + /* Check for pending start flag */ + if (IoGetDevObjExtension(AttachedDevice)->ExtensionFlags & + DOE_START_PENDING) + { + /* Propagate */ + IoGetDevObjExtension(SourceDevice)->ExtensionFlags |= + DOE_START_PENDING; + } + + /* Set the attachment in the device extension */ + SourceDeviceExtension->AttachedTo = AttachedDevice; + } + + /* Return the attached device */ + if (AttachedToDeviceObject) *AttachedToDeviceObject = AttachedDevice; + return AttachedDevice; + } + + VOID + NTAPI + IoShutdownPnpDevices(VOID) + { + /* This routine is only used by Driver Verifier to validate shutdown */ + return; + } + + VOID + NTAPI + IoShutdownSystem(IN ULONG Phase) + { + PLIST_ENTRY ListEntry; + PDEVICE_OBJECT DeviceObject; + PSHUTDOWN_ENTRY ShutdownEntry; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + + /* Initialize an event to wait on */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + /* What phase? */ + if (Phase == 0) + { + /* Shutdown PnP */ + IoShutdownPnpDevices(); + + /* Loop first-chance shutdown notifications */ + ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead, + &ShutdownListLock); + while (ListEntry) + { + /* Get the shutdown entry */ + ShutdownEntry = CONTAINING_RECORD(ListEntry, + SHUTDOWN_ENTRY, + ShutdownList); + + /* Get the attached device */ + DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject); + + /* Build the shutdown IRP and call the driver */ + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, + DeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait on the driver */ + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + } + + /* Get rid of our reference to it */ + ObDereferenceObject(DeviceObject); + + /* Free the shutdown entry and reset the event */ + ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY); + KeClearEvent(&Event); + + /* Go to the next entry */ + ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead, + &ShutdownListLock); + } + } + else if (Phase == 1) + { + /* Acquire resource forever */ + ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE); + + /* Shutdown disk file systems */ + IopShutdownBaseFileSystems(&IopDiskFileSystemQueueHead); + + /* Shutdown cdrom file systems */ + IopShutdownBaseFileSystems(&IopCdRomFileSystemQueueHead); + + /* Shutdown tape filesystems */ + IopShutdownBaseFileSystems(&IopTapeFileSystemQueueHead); + + /* Loop last-chance shutdown notifications */ + ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead, + &ShutdownListLock); + while (ListEntry) + { + /* Get the shutdown entry */ + ShutdownEntry = CONTAINING_RECORD(ListEntry, + SHUTDOWN_ENTRY, + ShutdownList); + + /* Get the attached device */ + DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject); + + /* Build the shutdown IRP and call the driver */ + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, + DeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait on the driver */ + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + } + + /* Get rid of our reference to it */ + ObDereferenceObject(DeviceObject); + + /* Free the shutdown entry and reset the event */ + ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY); + KeClearEvent(&Event); + + /* Go to the next entry */ + ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead, + &ShutdownListLock); + } + + } + } + + NTSTATUS + NTAPI + IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, + IN ACCESS_MASK DesiredAccess, + OUT PFILE_OBJECT *FileObject, + OUT PDEVICE_OBJECT *DeviceObject, + IN ULONG AttachFlag) + { + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK StatusBlock; + PFILE_OBJECT LocalFileObject; + HANDLE FileHandle; + NTSTATUS Status; + + /* Open the Device */ + InitializeObjectAttributes(&ObjectAttributes, + ObjectName, + OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ZwOpenFile(&FileHandle, + DesiredAccess, + &ObjectAttributes, + &StatusBlock, + 0, + FILE_NON_DIRECTORY_FILE | AttachFlag); + if (!NT_SUCCESS(Status)) return Status; + + /* Get File Object */ + Status = ObReferenceObjectByHandle(FileHandle, + 0, + IoFileObjectType, + KernelMode, + (PVOID*)&LocalFileObject, + NULL); + if (NT_SUCCESS(Status)) + { + /* Return the requested data */ + *DeviceObject = IoGetRelatedDeviceObject(LocalFileObject); + *FileObject = LocalFileObject; + } + + /* Close the handle */ + ZwClose(FileHandle); + + return Status; + } + + PDEVICE_OBJECT + NTAPI + IopGetLowestDevice(IN PDEVICE_OBJECT DeviceObject) + { + PDEVICE_OBJECT LowestDevice; + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the current device and its extension */ + LowestDevice = DeviceObject; + DeviceExtension = IoGetDevObjExtension(LowestDevice); + + /* Keep looping as long as we're attached */ + while (DeviceExtension->AttachedTo) + { + /* Get the lowest device and its extension */ + LowestDevice = DeviceExtension->AttachedTo; + DeviceExtension = IoGetDevObjExtension(LowestDevice); + } + + /* Return the lowest device */ + return LowestDevice; + } + + VOID + NTAPI + IopEditDeviceList(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject, + IN IOP_DEVICE_LIST_OPERATION Type) + { + PDEVICE_OBJECT Previous; + + /* Check the type of operation */ + if (Type == IopRemove) + { + /* Get the current device and check if it's the current one */ + Previous = DeviceObject->DriverObject->DeviceObject; + if (Previous == DeviceObject) + { + /* It is, simply unlink this one directly */ + DeviceObject->DriverObject->DeviceObject = + DeviceObject->NextDevice; + } + else + { + /* It's not, so loop until we find the device */ + while (Previous->NextDevice != DeviceObject) + { + /* Not this one, keep moving */ + Previous = Previous->NextDevice; + } + + /* We found it, now unlink us */ + Previous->NextDevice = DeviceObject->NextDevice; + } + } + else + { + /* Link the device object and the driver object */ + DeviceObject->NextDevice = DriverObject->DeviceObject; + DriverObject->DeviceObject = DeviceObject; + } + } + + VOID + NTAPI + IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject) + { + PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject; + PDEVICE_OBJECT AttachedDeviceObject, LowestDeviceObject; + PEXTENDED_DEVOBJ_EXTENSION ThisExtension, DeviceExtension; + PDEVICE_NODE DeviceNode; + BOOLEAN SafeToUnload = TRUE; + + /* Check if removal is pending */ + ThisExtension = IoGetDevObjExtension(DeviceObject); + if (ThisExtension->ExtensionFlags & DOE_REMOVE_PENDING) + { + /* Get the PDO, extension, and node */ + LowestDeviceObject = IopGetLowestDevice(DeviceObject); + DeviceExtension = IoGetDevObjExtension(LowestDeviceObject); + DeviceNode = DeviceExtension->DeviceNode; + + /* The PDO needs a device node */ + ASSERT(DeviceNode != NULL); + + /* Loop all attached objects */ + AttachedDeviceObject = LowestDeviceObject; + while (AttachedDeviceObject) + { + /* Make sure they're dereferenced */ + if (AttachedDeviceObject->ReferenceCount) return; + AttachedDeviceObject = AttachedDeviceObject->AttachedDevice; + } + + /* Loop all attached objects */ + AttachedDeviceObject = LowestDeviceObject; + while (AttachedDeviceObject) + { + /* Get the device extension */ + DeviceExtension = IoGetDevObjExtension(AttachedDeviceObject); + + /* Remove the pending flag and set processed */ + DeviceExtension->ExtensionFlags &= ~DOE_REMOVE_PENDING; + DeviceExtension->ExtensionFlags |= DOE_REMOVE_PROCESSED; + AttachedDeviceObject = AttachedDeviceObject->AttachedDevice; + } + + /* + * FIXME: TODO HPOUSSIN + * We need to parse/lock the device node, and if we have any pending + * surprise removals, query all relationships and send IRP_MN_REMOVE_ + * _DEVICE to the devices related... + */ + return; + } + + /* Check if deletion is pending */ + if (ThisExtension->ExtensionFlags & DOE_DELETE_PENDING) + { + /* Make sure unload is pending */ + if (!(ThisExtension->ExtensionFlags & DOE_UNLOAD_PENDING) || + (DriverObject->Flags & DRVO_UNLOAD_INVOKED)) + { + /* We can't unload anymore */ + SafeToUnload = FALSE; + } + + /* + * Check if we have an attached device and fail if we're attached - * and still have a reference count. ++ * or still have a reference count. + */ + AttachedDeviceObject = DeviceObject->AttachedDevice; - if ((AttachedDeviceObject) && (DeviceObject->ReferenceCount)) return; ++ if ((AttachedDeviceObject) || (DeviceObject->ReferenceCount)) return; + + /* Check if we have a Security Descriptor */ + if (DeviceObject->SecurityDescriptor) + { + /* Free it */ + ExFreePoolWithTag(DeviceObject->SecurityDescriptor, TAG_SD); + } + + /* Remove the device from the list */ + IopEditDeviceList(DeviceObject->DriverObject, DeviceObject, IopRemove); + + /* Dereference the keep-alive */ + ObDereferenceObject(DeviceObject); + + /* If we're not unloading, stop here */ + if (!SafeToUnload) return; + } + + /* Loop all the device objects */ + DeviceObject = DriverObject->DeviceObject; + while (DeviceObject) + { + /* + * Make sure we're not attached, having a reference count + * or already deleting + */ + if ((DeviceObject->ReferenceCount) || + (DeviceObject->AttachedDevice) || + (IoGetDevObjExtension(DeviceObject)->ExtensionFlags & + (DOE_DELETE_PENDING | DOE_REMOVE_PENDING))) + { + /* We're not safe to unload, quit */ + return; + } + + /* Check the next device */ + DeviceObject = DeviceObject->NextDevice; + } + + /* Set the unload invoked flag */ + DriverObject->Flags |= DRVO_UNLOAD_INVOKED; + + /* Unload it */ + if (DriverObject->DriverUnload) DriverObject->DriverUnload(DriverObject); + + /* Make object temporary so it can be deleted */ + ObMakeTemporaryObject(DriverObject); + + /* Dereference once more, referenced at driver object creation */ + ObDereferenceObject(DriverObject); + + } + + VOID + NTAPI + IopDereferenceDeviceObject(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN ForceUnload) + { + /* Sanity check */ + ASSERT(DeviceObject->ReferenceCount); + + /* Dereference the device */ + InterlockedDecrement(&DeviceObject->ReferenceCount); + + /* + * Check if we can unload it and it's safe to unload (or if we're forcing + * an unload, which is OK too). + */ + if (!(DeviceObject->ReferenceCount) && + ((ForceUnload) || (IoGetDevObjExtension(DeviceObject)->ExtensionFlags & + (DOE_UNLOAD_PENDING | + DOE_DELETE_PENDING | + DOE_REMOVE_PENDING | + DOE_REMOVE_PROCESSED)))) + { + /* Unload it */ + IopUnloadDevice(DeviceObject); + } + } + + VOID + NTAPI + IopStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable, + IN ULONG Key) + { + PKDEVICE_QUEUE_ENTRY Entry; + PIRP Irp; + KIRQL OldIrql; + + /* Acquire the cancel lock if this is cancelable */ + if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); + + /* Clear the current IRP */ + DeviceObject->CurrentIrp = NULL; + + /* Remove an entry from the queue */ + Entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, Key); + if (Entry) + { + /* Get the IRP and set it */ + Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + + /* Check if this is a cancelable packet */ + if (Cancelable) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(OldIrql); + } + + /* Call the Start I/O Routine */ + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + /* Otherwise, release the cancel lock if we had acquired it */ + if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + } + } + + VOID + NTAPI + IopStartNextPacket(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable) + { + PKDEVICE_QUEUE_ENTRY Entry; + PIRP Irp; + KIRQL OldIrql; + + /* Acquire the cancel lock if this is cancelable */ + if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); + + /* Clear the current IRP */ + DeviceObject->CurrentIrp = NULL; + + /* Remove an entry from the queue */ + Entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); + if (Entry) + { + /* Get the IRP and set it */ + Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + + /* Check if this is a cancelable packet */ + if (Cancelable) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(OldIrql); + } + + /* Call the Start I/O Routine */ + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + /* Otherwise, release the cancel lock if we had acquired it */ + if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + } + } + + VOID + NTAPI + IopStartNextPacketByKeyEx(IN PDEVICE_OBJECT DeviceObject, + IN ULONG Key, + IN ULONG Flags) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + ULONG CurrentKey = Key; + ULONG CurrentFlags = Flags; + + /* Get the device extension and start the packet loop */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + while (TRUE) + { + /* Increase the count */ + if (InterlockedIncrement(&DeviceExtension->StartIoCount) > 1) + { + /* + * We've already called the routine once... + * All we have to do is save the key and add the new flags + */ + DeviceExtension->StartIoFlags |= CurrentFlags; + DeviceExtension->StartIoKey = CurrentKey; + } + else + { + /* Mask out the current packet flags and key */ + DeviceExtension->StartIoFlags &= ~(DOE_SIO_WITH_KEY | + DOE_SIO_NO_KEY | + DOE_SIO_CANCELABLE); + DeviceExtension->StartIoKey = 0; + + /* Check if this is a packet start with key */ + if (Flags & DOE_SIO_WITH_KEY) + { + /* Start the packet with a key */ + IopStartNextPacketByKey(DeviceObject, + (Flags & DOE_SIO_CANCELABLE) ? + TRUE : FALSE, + CurrentKey); + } + else if (Flags & DOE_SIO_NO_KEY) + { + /* Start the packet */ + IopStartNextPacket(DeviceObject, + (Flags & DOE_SIO_CANCELABLE) ? + TRUE : FALSE); + } + } + + /* Decrease the Start I/O count and check if it's 0 now */ + if (!InterlockedDecrement(&DeviceExtension->StartIoCount)) + { + /* Get the current active key and flags */ + CurrentKey = DeviceExtension->StartIoKey; + CurrentFlags = DeviceExtension->StartIoFlags & (DOE_SIO_WITH_KEY | + DOE_SIO_NO_KEY | + DOE_SIO_CANCELABLE); + + /* Check if we should still loop */ + if (!(CurrentFlags & (DOE_SIO_WITH_KEY | DOE_SIO_NO_KEY))) break; + } + else + { + /* There are still Start I/Os active, so quit this loop */ + break; + } + } + } + + NTSTATUS + NTAPI + IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, + OUT PDEVICE_NODE *DeviceNode) + { + NTSTATUS Status; + IO_STACK_LOCATION Stack = {0}; + PDEVICE_RELATIONS DeviceRelations; + PDEVICE_OBJECT DeviceObject = NULL; + + ASSERT(FileObject); + + /* Get DeviceObject related to given FileObject */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + if (!DeviceObject) return STATUS_NO_SUCH_DEVICE; + + /* Define input parameters */ + Stack.MajorFunction = IRP_MJ_PNP; + Stack.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; + Stack.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation; + Stack.FileObject = FileObject; + + /* Call the driver to query all relations (IRP_MJ_PNP) */ + Status = IopSynchronousCall(DeviceObject, + &Stack, + (PVOID)&DeviceRelations); + if (!NT_SUCCESS(Status)) return Status; + + /* Make sure it's not NULL and contains only one object */ + ASSERT(DeviceRelations); + ASSERT(DeviceRelations->Count == 1); + + /* Finally get the device node */ + *DeviceNode = IopGetDeviceNode(DeviceRelations->Objects[0]); + if (!*DeviceNode) Status = STATUS_NO_SUCH_DEVICE; + + /* Free the DEVICE_RELATIONS structure, it's not needed anymore */ + ExFreePool(DeviceRelations); + + return Status; + } + + /* PUBLIC FUNCTIONS ***********************************************************/ + + /* + * IoAttachDevice + * + * Layers a device over the highest device in a device stack. + * + * Parameters + * SourceDevice + * Device to be attached. + * + * TargetDevice + * Name of the target device. + * + * AttachedDevice + * Caller storage for the device attached to. + * + * Status + * @implemented + */ + NTSTATUS + NTAPI + IoAttachDevice(PDEVICE_OBJECT SourceDevice, + PUNICODE_STRING TargetDeviceName, + PDEVICE_OBJECT *AttachedDevice) + { + NTSTATUS Status; + PFILE_OBJECT FileObject = NULL; + PDEVICE_OBJECT TargetDevice = NULL; + + /* Call the helper routine for an attach operation */ + Status = IopGetDeviceObjectPointer(TargetDeviceName, + FILE_READ_ATTRIBUTES, + &FileObject, + &TargetDevice, + IO_ATTACH_DEVICE_API); + if (!NT_SUCCESS(Status)) return Status; + + /* Attach the device */ + Status = IoAttachDeviceToDeviceStackSafe(SourceDevice, + TargetDevice, + AttachedDevice); + + /* Dereference it */ + ObDereferenceObject(FileObject); + return Status; + } + + /* + * IoAttachDeviceByPointer + * + * Status + * @implemented + */ + NTSTATUS + NTAPI + IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice) + { + PDEVICE_OBJECT AttachedDevice; + NTSTATUS Status = STATUS_SUCCESS; + + /* Do the Attach */ + AttachedDevice = IoAttachDeviceToDeviceStack(SourceDevice, TargetDevice); + if (!AttachedDevice) Status = STATUS_NO_SUCH_DEVICE; + + /* Return the status */ + return Status; + } + + /* + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice) + { + /* Attach it safely */ + return IopAttachDeviceToDeviceStackSafe(SourceDevice, + TargetDevice, + NULL); + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice, + IN OUT PDEVICE_OBJECT *AttachedToDeviceObject) + { + /* Call the internal function */ + if (!IopAttachDeviceToDeviceStackSafe(SourceDevice, + TargetDevice, + AttachedToDeviceObject)) + { + /* Nothing found */ + return STATUS_NO_SUCH_DEVICE; + } + + /* Success! */ + return STATUS_SUCCESS; + } + + /* + * IoCreateDevice + * + * Allocates memory for and intializes a device object for use for + * a driver. + * + * Parameters + * DriverObject + * Driver object passed by IO Manager when the driver was loaded. + * + * DeviceExtensionSize + * Number of bytes for the device extension. + * + * DeviceName + * Unicode name of device. + * + * DeviceType + * Device type of the new device. + * + * DeviceCharacteristics + * Bit mask of device characteristics. + * + * Exclusive + * TRUE if only one thread can access the device at a time. + * + * DeviceObject + * On successful return this parameter is filled by pointer to + * allocated device object. + * + * Status + * @implemented + */ + NTSTATUS + NTAPI + IoCreateDevice(IN PDRIVER_OBJECT DriverObject, + IN ULONG DeviceExtensionSize, + IN PUNICODE_STRING DeviceName, + IN DEVICE_TYPE DeviceType, + IN ULONG DeviceCharacteristics, + IN BOOLEAN Exclusive, + OUT PDEVICE_OBJECT *DeviceObject) + { + WCHAR AutoNameBuffer[20]; + UNICODE_STRING AutoName; + PDEVICE_OBJECT CreatedDeviceObject; + PDEVOBJ_EXTENSION DeviceObjectExtension; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + ULONG AlignedDeviceExtensionSize; + ULONG TotalSize; + HANDLE TempHandle; + PAGED_CODE(); + + /* Check if we have to generate a name */ + if (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME) + { + /* Generate it */ + swprintf(AutoNameBuffer, + L"\\Device\\%08lx", + InterlockedIncrementUL(&IopDeviceObjectNumber)); + + /* Initialize the name */ + RtlInitUnicodeString(&AutoName, AutoNameBuffer); + DeviceName = &AutoName; + } + + /* Initialize the Object Attributes */ + InitializeObjectAttributes(&ObjectAttributes, + DeviceName, + OBJ_KERNEL_HANDLE, + NULL, + NULL); + + /* Honor exclusive flag */ + if (Exclusive) ObjectAttributes.Attributes |= OBJ_EXCLUSIVE; + + /* Create a permanent object for named devices */ + if (DeviceName) ObjectAttributes.Attributes |= OBJ_PERMANENT; + + /* Align the Extension Size to 8-bytes */ + AlignedDeviceExtensionSize = (DeviceExtensionSize + 7) &~ 7; + + /* Total Size */ + TotalSize = AlignedDeviceExtensionSize + + sizeof(DEVICE_OBJECT) + + sizeof(EXTENDED_DEVOBJ_EXTENSION); + + /* Create the Device Object */ + *DeviceObject = NULL; + Status = ObCreateObject(KernelMode, + IoDeviceObjectType, + &ObjectAttributes, + KernelMode, + NULL, + TotalSize, + 0, + 0, + (PVOID*)&CreatedDeviceObject); + if (!NT_SUCCESS(Status)) return Status; + + /* Clear the whole Object and extension so we don't null stuff manually */ + RtlZeroMemory(CreatedDeviceObject, TotalSize); + + /* + * Setup the Type and Size. Note that we don't use the aligned size, + * because that's only padding for the DevObjExt and not part of the Object. + */ + CreatedDeviceObject->Type = IO_TYPE_DEVICE; + CreatedDeviceObject->Size = sizeof(DEVICE_OBJECT) + (USHORT)DeviceExtensionSize; + + /* The kernel extension is after the driver internal extension */ + DeviceObjectExtension = (PDEVOBJ_EXTENSION) + ((ULONG_PTR)(CreatedDeviceObject + 1) + + AlignedDeviceExtensionSize); + + /* Set the Type and Size. Question: why is Size 0 on Windows? */ + DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION; + DeviceObjectExtension->Size = 0; + + /* Initialize with Power Manager */ + PoInitializeDeviceObject(DeviceObjectExtension); + + /* Link the Object and Extension */ + DeviceObjectExtension->DeviceObject = CreatedDeviceObject; + CreatedDeviceObject->DeviceObjectExtension = DeviceObjectExtension; + + /* Set Device Object Data */ + CreatedDeviceObject->DeviceType = DeviceType; + CreatedDeviceObject->Characteristics = DeviceCharacteristics; + CreatedDeviceObject->DeviceExtension = DeviceExtensionSize ? + CreatedDeviceObject + 1 : + NULL; + CreatedDeviceObject->StackSize = 1; + CreatedDeviceObject->AlignmentRequirement = 0; + + /* Set the Flags */ + CreatedDeviceObject->Flags = DO_DEVICE_INITIALIZING; + if (Exclusive) CreatedDeviceObject->Flags |= DO_EXCLUSIVE; + if (DeviceName) CreatedDeviceObject->Flags |= DO_DEVICE_HAS_NAME; + + /* Attach a Vpb for Disks and Tapes, and create the Device Lock */ + if ((CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)) + { + /* Create Vpb */ + Status = IopCreateVpb(CreatedDeviceObject); + if (!NT_SUCCESS(Status)) + { + /* Reference the device object and fail */ + ObDereferenceObject(DeviceObject); + return Status; + } + + /* Initialize Lock Event */ + KeInitializeEvent(&CreatedDeviceObject->DeviceLock, + SynchronizationEvent, + TRUE); + } + + /* Set the right Sector Size */ + switch (DeviceType) + { + /* All disk systems */ + case FILE_DEVICE_DISK_FILE_SYSTEM: + case FILE_DEVICE_DISK: + case FILE_DEVICE_VIRTUAL_DISK: + + /* The default is 512 bytes */ + CreatedDeviceObject->SectorSize = 512; + break; + + /* CD-ROM file systems */ + case FILE_DEVICE_CD_ROM_FILE_SYSTEM: + + /* The default is 2048 bytes */ + CreatedDeviceObject->SectorSize = 2048; + } + + /* Create the Device Queue */ + if ((CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_FILE_SYSTEM) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) || + (CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM)) + { + /* Simple FS Devices, they don't need a real Device Queue */ + InitializeListHead(&CreatedDeviceObject->Queue.ListEntry); + } + else + { + /* An actual Device, initialize its DQ */ + KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue); + } + + /* Insert the Object */ + Status = ObInsertObject(CreatedDeviceObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 1, + (PVOID*)&CreatedDeviceObject, + &TempHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* Now do the final linking */ + ObReferenceObject(DriverObject); + ASSERT((DriverObject->Flags & DRVO_UNLOAD_INVOKED) == 0); + CreatedDeviceObject->DriverObject = DriverObject; + IopEditDeviceList(DriverObject, CreatedDeviceObject, IopAdd); + + /* Link with the power manager */ + if (CreatedDeviceObject->Vpb) PoVolumeDevice(CreatedDeviceObject); + + /* Close the temporary handle and return to caller */ + ObCloseHandle(TempHandle, KernelMode); + *DeviceObject = CreatedDeviceObject; + return STATUS_SUCCESS; + } + + /* + * IoDeleteDevice + * + * Status + * @implemented + */ + VOID + NTAPI + IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject) + { + PIO_TIMER Timer; + + /* Check if the device is registered for shutdown notifications */ + if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED) + { + /* Call the shutdown notifications */ + IoUnregisterShutdownNotification(DeviceObject); + } + + /* Check if it has a timer */ + Timer = DeviceObject->Timer; + if (Timer) + { + /* Remove it and free it */ + IopRemoveTimerFromTimerList(Timer); + ExFreePoolWithTag(Timer, TAG_IO_TIMER); + } + + /* Check if the device has a name */ + if (DeviceObject->Flags & DO_DEVICE_HAS_NAME) + { + /* It does, make it temporary so we can remove it */ + ObMakeTemporaryObject(DeviceObject); + } + + /* Set the pending delete flag */ + IoGetDevObjExtension(DeviceObject)->ExtensionFlags |= DOE_DELETE_PENDING; + + /* Check if the device object can be unloaded */ + if (!DeviceObject->ReferenceCount) IopUnloadDevice(DeviceObject); + } + + /* + * IoDetachDevice + * + * Status + * @implemented + */ + VOID + NTAPI + IoDetachDevice(IN PDEVICE_OBJECT TargetDevice) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Sanity check */ + DeviceExtension = IoGetDevObjExtension(TargetDevice->AttachedDevice); + ASSERT(DeviceExtension->AttachedTo == TargetDevice); + + /* Remove the attachment */ + DeviceExtension->AttachedTo = NULL; + TargetDevice->AttachedDevice = NULL; + + /* Check if it's ok to delete this device */ + if ((IoGetDevObjExtension(TargetDevice)->ExtensionFlags & + (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING)) && + !(TargetDevice->ReferenceCount)) + { + /* It is, do it */ + IopUnloadDevice(TargetDevice); + } + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT *DeviceObjectList, + IN ULONG DeviceObjectListSize, + OUT PULONG ActualNumberDeviceObjects) + { + ULONG ActualDevices = 1; + PDEVICE_OBJECT CurrentDevice = DriverObject->DeviceObject; + + /* Find out how many devices we'll enumerate */ + while ((CurrentDevice = CurrentDevice->NextDevice)) ActualDevices++; + + /* Go back to the first */ + CurrentDevice = DriverObject->DeviceObject; + + /* Start by at least returning this */ + *ActualNumberDeviceObjects = ActualDevices; + + /* Check if we can support so many */ + if ((ActualDevices * 4) > DeviceObjectListSize) + { + /* Fail because the buffer was too small */ + return STATUS_BUFFER_TOO_SMALL; + } + + /* Check if the caller only wanted the size */ + if (DeviceObjectList) + { + /* Loop through all the devices */ + while (ActualDevices) + { + /* Reference each Device */ + ObReferenceObject(CurrentDevice); + + /* Add it to the list */ + *DeviceObjectList = CurrentDevice; + + /* Go to the next one */ + CurrentDevice = CurrentDevice->NextDevice; + ActualDevices--; + DeviceObjectList++; + } + } + + /* Return the status */ + return STATUS_SUCCESS; + } + + /* + * IoGetAttachedDevice + * + * Status + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject) + { + /* Get the last attached device */ + while (DeviceObject->AttachedDevice) + { + /* Move to the next one */ + DeviceObject = DeviceObject->AttachedDevice; + } + + /* Return it */ + return DeviceObject; + } + + /* + * IoGetAttachedDeviceReference + * + * Status + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject) + { + /* Reference the Attached Device */ + DeviceObject = IoGetAttachedDevice(DeviceObject); + ObReferenceObject(DeviceObject); + return DeviceObject; + } + + /* + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject) + { + /* Reference the lowest attached device */ + DeviceObject = IopGetLowestDevice(DeviceObject); + ObReferenceObject(DeviceObject); + return DeviceObject; + } + + /* + * IoGetDeviceObjectPointer + * + * Status + * @implemented + */ + NTSTATUS + NTAPI + IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, + IN ACCESS_MASK DesiredAccess, + OUT PFILE_OBJECT *FileObject, + OUT PDEVICE_OBJECT *DeviceObject) + { + /* Call the helper routine for a normal operation */ + return IopGetDeviceObjectPointer(ObjectName, + DesiredAccess, + FileObject, + DeviceObject, + 0); + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject, + OUT PDEVICE_OBJECT *DiskDeviceObject) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + PVPB Vpb; + KIRQL OldIrql; + NTSTATUS Status; + + /* Make sure there's a VPB */ + if (!FileSystemDeviceObject->Vpb) return STATUS_INVALID_PARAMETER; + + /* Acquire it */ + IoAcquireVpbSpinLock(&OldIrql); + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(FileSystemDeviceObject); + + /* Make sure this one has a VPB too */ + Vpb = DeviceExtension->Vpb; + if (Vpb) + { + /* Make sure that it's mounted */ + if ((Vpb->ReferenceCount) && + (Vpb->Flags & VPB_MOUNTED)) + { + /* Return the Disk Device Object */ + *DiskDeviceObject = Vpb->RealDevice; + + /* Reference it and return success */ + ObReferenceObject(Vpb->RealDevice); + Status = STATUS_SUCCESS; + } + else + { + /* It's not, so return failure */ + Status = STATUS_VOLUME_DISMOUNTED; + } + } + else + { + /* Fail */ + Status = STATUS_INVALID_PARAMETER; + } + + /* Release the lock */ + IoReleaseVpbSpinLock(OldIrql); + return Status; + } + + /* + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + PDEVICE_OBJECT LowerDeviceObject = NULL; + + /* Make sure it's not getting deleted */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + if (!(DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING | + DOE_DELETE_PENDING | + DOE_REMOVE_PENDING | + DOE_REMOVE_PROCESSED))) + { + /* Get the Lower Device Object */ + LowerDeviceObject = DeviceExtension->AttachedTo; + + /* Check that we got a valid device object */ + if (LowerDeviceObject) + { + /* We did so let's reference it */ + ObReferenceObject(LowerDeviceObject); + } + } + + /* Return it */ + return LowerDeviceObject; + } + + /* + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject) + { + PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject; + + /* Check if we have a VPB with a device object */ + if ((FileObject->Vpb) && (FileObject->Vpb->DeviceObject)) + { + /* Then use the DO from the VPB */ + ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); + DeviceObject = FileObject->Vpb->DeviceObject; + } + else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && + (FileObject->DeviceObject->Vpb) && + (FileObject->DeviceObject->Vpb->DeviceObject)) + { + /* The disk device actually has a VPB, so get the DO from there */ + DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject; + } + else + { + /* Otherwise, this was a direct open */ + DeviceObject = FileObject->DeviceObject; + } + + /* Sanity check */ + ASSERT(DeviceObject != NULL); + + /* Check if we were attached */ + if (DeviceObject->AttachedDevice) + { + /* Check if the file object has an extension present */ + if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) + { + /* Sanity check, direct open files can't have this */ + ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)); + + /* Check if the extension is really present */ + if (FileObject->FileObjectExtension) + { + /* FIXME: Unhandled yet */ + DPRINT1("FOEs not supported\n"); + ASSERT(FALSE); + } + } + + /* Return the highest attached device */ + DeviceObject = IoGetAttachedDevice(DeviceObject); + } + + /* Return the DO we found */ + return DeviceObject; + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, + OUT PDEVICE_OBJECT *DeviceObject) + { + NTSTATUS Status; + PDEVICE_NODE DeviceNode = NULL; + + /* Call the internal helper function */ + Status = IopGetRelatedTargetDevice(FileObject, &DeviceNode); + if (NT_SUCCESS(Status) && DeviceNode) + { + *DeviceObject = DeviceNode->PhysicalDeviceObject; + } + return Status; + } + + /* + * @implemented + */ + PDEVICE_OBJECT + NTAPI + IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject) + { + PDEVICE_OBJECT DeviceObject; + + /* + * If the FILE_OBJECT's VPB is defined, + * get the device from it. + */ + if ((FileObject->Vpb) && (FileObject->Vpb->DeviceObject)) + { + /* Use the VPB's Device Object's */ + DeviceObject = FileObject->Vpb->DeviceObject; + } + else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) && + (FileObject->DeviceObject->Vpb) && + (FileObject->DeviceObject->Vpb->DeviceObject)) + { + /* Use the VPB's File System Object */ + DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject; + } + else + { + /* Use the FO's Device Object */ + DeviceObject = FileObject->DeviceObject; + } + + /* Return the device object we found */ + ASSERT(DeviceObject != NULL); + return DeviceObject; + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject) + { + PSHUTDOWN_ENTRY Entry; + + /* Allocate the shutdown entry */ + Entry = ExAllocatePoolWithTag(NonPagedPool, + sizeof(SHUTDOWN_ENTRY), + TAG_SHUTDOWN_ENTRY); + if (!Entry) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set the DO */ + Entry->DeviceObject = DeviceObject; + + /* Reference it so it doesn't go away */ + ObReferenceObject(DeviceObject); + + /* Insert it into the list */ + ExInterlockedInsertHeadList(&LastChanceShutdownListHead, + &Entry->ShutdownList, + &ShutdownListLock); + + /* Set the shutdown registered flag */ + DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; + return STATUS_SUCCESS; + } + + /* + * @implemented + */ + NTSTATUS + NTAPI + IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject) + { + PSHUTDOWN_ENTRY Entry; + + /* Allocate the shutdown entry */ + Entry = ExAllocatePoolWithTag(NonPagedPool, + sizeof(SHUTDOWN_ENTRY), + TAG_SHUTDOWN_ENTRY); + if (!Entry) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set the DO */ + Entry->DeviceObject = DeviceObject; + + /* Reference it so it doesn't go away */ + ObReferenceObject(DeviceObject); + + /* Insert it into the list */ + ExInterlockedInsertHeadList(&ShutdownListHead, + &Entry->ShutdownList, + &ShutdownListLock); + + /* Set the shutdown registered flag */ + DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; + return STATUS_SUCCESS; + } + + /* + * @implemented + */ + VOID + NTAPI + IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject) + { + PSHUTDOWN_ENTRY ShutdownEntry; + PLIST_ENTRY NextEntry; + KIRQL OldIrql; + + /* Acquire the shutdown lock and loop the shutdown list */ + KeAcquireSpinLock(&ShutdownListLock, &OldIrql); + NextEntry = ShutdownListHead.Flink; + while (NextEntry != &ShutdownListHead) + { + /* Get the entry */ + ShutdownEntry = CONTAINING_RECORD(NextEntry, + SHUTDOWN_ENTRY, + ShutdownList); + + /* Get if the DO matches */ + if (ShutdownEntry->DeviceObject == DeviceObject) + { + /* Remove it from the list */ + RemoveEntryList(NextEntry); + NextEntry = NextEntry->Blink; + + /* Free the entry */ + ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY); + + /* Get rid of our reference to it */ + ObDereferenceObject(DeviceObject); + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Now loop the last chance list */ + NextEntry = LastChanceShutdownListHead.Flink; + while (NextEntry != &LastChanceShutdownListHead) + { + /* Get the entry */ + ShutdownEntry = CONTAINING_RECORD(NextEntry, + SHUTDOWN_ENTRY, + ShutdownList); + + /* Get if the DO matches */ + if (ShutdownEntry->DeviceObject == DeviceObject) + { + /* Remove it from the list */ + RemoveEntryList(NextEntry); + NextEntry = NextEntry->Blink; + + /* Free the entry */ + ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY); + + /* Get rid of our reference to it */ + ObDereferenceObject(DeviceObject); + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Release the shutdown lock */ + KeReleaseSpinLock(&ShutdownListLock, OldIrql); + + /* Now remove the flag */ + DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED; + } + + /* + * @implemented + */ + VOID + NTAPI + IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN DeferredStartIo, + IN BOOLEAN NonCancelable) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Set the flags the caller requested */ + DeviceExtension->StartIoFlags |= (DeferredStartIo) ? DOE_SIO_DEFERRED : 0; + DeviceExtension->StartIoFlags |= (NonCancelable) ? DOE_SIO_NO_CANCEL : 0; + } + + /* + * @implemented + */ + VOID + NTAPI + IoStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable, + IN ULONG Key) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Check if deferred start was requested */ + if (DeviceExtension->StartIoFlags & DOE_SIO_DEFERRED) + { + /* Call our internal function to handle the defered case */ + IopStartNextPacketByKeyEx(DeviceObject, + Key, + DOE_SIO_WITH_KEY | + (Cancelable ? DOE_SIO_CANCELABLE : 0)); + } + else + { + /* Call the normal routine */ + IopStartNextPacketByKey(DeviceObject, Cancelable, Key); + } + } + + /* + * @implemented + */ + VOID + NTAPI + IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable) + { + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Check if deferred start was requested */ + if (DeviceExtension->StartIoFlags & DOE_SIO_DEFERRED) + { + /* Call our internal function to handle the defered case */ + IopStartNextPacketByKeyEx(DeviceObject, + 0, + DOE_SIO_NO_KEY | + (Cancelable ? DOE_SIO_CANCELABLE : 0)); + } + else + { + /* Call the normal routine */ + IopStartNextPacket(DeviceObject, Cancelable); + } + } + + /* + * @implemented + */ + VOID + NTAPI + IoStartPacket(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PULONG Key, + IN PDRIVER_CANCEL CancelFunction) + { + BOOLEAN Stat; + KIRQL OldIrql, CancelIrql; + + /* Raise to dispatch level */ + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + + /* Check if we should acquire the cancel lock */ + if (CancelFunction) + { + /* Acquire and set it */ + IoAcquireCancelSpinLock(&CancelIrql); + Irp->CancelRoutine = CancelFunction; + } + + /* Check if we have a key */ + if (Key) + { + /* Insert by key */ + Stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry, + *Key); + } + else + { + /* Insert without a key */ + Stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry); + } + + /* Check if this was a first insert */ + if (!Stat) + { + /* Set the IRP */ + DeviceObject->CurrentIrp = Irp; + + /* Check if this is a cancelable packet */ + if (CancelFunction) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(CancelIrql); + } + + /* Call the Start I/O function */ + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + /* The packet was inserted... check if we have a cancel function */ + if (CancelFunction) + { + /* Check if the IRP got cancelled */ + if (Irp->Cancel) + { + /* + * Set the cancel IRQL, clear the currnet cancel routine and + * call ours + */ + Irp->CancelIrql = CancelIrql; + Irp->CancelRoutine = NULL; + CancelFunction(DeviceObject, Irp); + } + else + { + /* Otherwise, release the lock */ + IoReleaseCancelSpinLock(CancelIrql); + } + } + } + + /* Return back to previous IRQL */ + KeLowerIrql(OldIrql); + } + + #if defined (_WIN64) + ULONG + NTAPI + IoWMIDeviceObjectToProviderId( + IN PDEVICE_OBJECT DeviceObject) + { + UNIMPLEMENTED; + return 0; + } + #endif + + /* EOF */