- 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
--- /dev/null
- ;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
+ ; 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\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
--- /dev/null
- usbdrv.sys=,,,,,,,,,,,,4
+ [Version]
+ Signature = "$ReactOS$"
+
+ [Directories]
+ ; <directory_id> = <path>
+ 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
++ 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]
+ ;<id> = <pnp id string>
+ 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]
+ ;<id> = <user friendly name>,<spare>,<service key name>,<hight>,<width>,<bpp>
+ 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]
+ ;<id> = <pnp id string>
+ 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
--- /dev/null
+ <?xml version="1.0"?>
+ <!DOCTYPE group SYSTEM "../tools/rbuild/project.dtd">
+ <group xmlns:xi="http://www.w3.org/2001/XInclude">
+ <directory name="base">
+ <xi:include href="base/directory.rbuild" />
+ </directory>
+ <directory name="battery">
+ <xi:include href="battery/directory.rbuild" />
+ </directory>
+ <directory name="bluetooth">
+ <xi:include href="bluetooth/directory.rbuild" />
+ </directory>
+ <directory name="bus">
+ <xi:include href="bus/directory.rbuild" />
+ </directory>
+ <directory name="directx">
+ <xi:include href="directx/directory.rbuild" />
+ </directory>
+ <directory name="filesystems">
+ <xi:include href="filesystems/directory.rbuild" />
+ </directory>
++ <directory name="hid">
++ <xi:include href="hid/directory.rbuild" />
++ </directory>
++ <directory name="filters>
++ <xi:include href="filters/directory.rbuild" />
++ </directory>
+ <directory name="input">
+ <xi:include href="input/directory.rbuild" />
+ </directory>
+ <directory name="ksfilter">
+ <xi:include href="ksfilter/directory.rbuild" />
+ </directory>
+ <directory name="multimedia">
+ <xi:include href="multimedia/directory.rbuild" />
+ </directory>
+ <directory name="network">
+ <xi:include href="network/directory.rbuild" />
+ </directory>
+ <directory name="parallel">
+ <xi:include href="parallel/directory.rbuild" />
+ </directory>
+ <directory name="sac">
+ <xi:include href="sac/directory.rbuild" />
+ </directory>
+ <directory name="serial">
+ <xi:include href="serial/directory.rbuild" />
+ </directory>
+ <directory name="setup">
+ <xi:include href="setup/directory.rbuild" />
+ </directory>
+ <directory name="storage">
+ <xi:include href="storage/directory.rbuild" />
+ </directory>
+ <directory name="usb">
+ <xi:include href="usb/directory.rbuild" />
+ </directory>
+ <directory name="video">
+ <xi:include href="video/directory.rbuild" />
+ </directory>
+ <directory name="wdm">
+ <xi:include href="wdm/wdm.rbuild" />
+ </directory>
+ <directory name="wmi">
+ <xi:include href="wmi/wmilib.rbuild" />
+ </directory>
+ </group>
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
+++#ifndef _MNTMGR_H_
+++#define _MNTMGR_H_
+++
+++#include <ntifs.h>
+++#include <ntddk.h>
+++#include <mountdev.h>
+++#include <ntddvol.h>
+++#include <wdmguid.h>
+++#include <ioevent.h>
+++#include <psfuncs.h>
+++#include <ntdddisk.h>
+++#include <ntddvol.h>
+++
+++/* 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_ */
--- /dev/null
--- /dev/null
--- /dev/null
+++/*
+++ * 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 <debug.h>
+++
+++/* 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;
+++}
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
+ /*
+ * 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;
+ }
--- /dev/null
- ULONG portNumber = 0;
+ /*
+ * 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 <ntddk.h>
+ #include <ntdddisk.h>
+ #include <scsi.h>
+ #include <include/class2.h>
+ #include <stdio.h>
+
++ /* Part of the drive letter hack */
++ #include <ntifs.h>
++ #include <ketypes.h>
++
+ //#define NDEBUG
+ #include <debug.h>
+
+ #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,
++