device.c 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. device.c
  5. Abstract:
  6. This module implements functions that interact with devices in the system.
  7. Author:
  8. Evan Green 16-Sep-2012
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include "iop.h"
  17. #include "pmp.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // Define values for the device ID suffix that is used to make device IDs
  23. // unique.
  24. //
  25. #define DEVICE_ID_SUFFIX_FORMAT "#%d"
  26. #define DEVICE_ID_SUFFIX_FORMAT_LENGTH 4
  27. #define DEVICE_ID_SUFFIX_ALTERNATE_FORMAT "%d"
  28. #define DEVICE_ID_SUFFIX_ALTERNATE_FORMAT_LENGTH 3
  29. #define DEVICE_ID_SUFFIX_START_CHARACTER '#'
  30. #define DEVICE_ID_SUFFIX_LENGTH_MAX 5
  31. //
  32. // Define the maximum number of sibling devices that can conflict with the same
  33. // name.
  34. //
  35. #define MAX_CONFLICTING_DEVICES 10000
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. //
  40. // ----------------------------------------------- Internal Function Prototypes
  41. //
  42. VOID
  43. IopDeviceWorker (
  44. PVOID Parameter
  45. );
  46. VOID
  47. IopProcessWorkEntry (
  48. PDEVICE Device,
  49. PDEVICE_WORK_ENTRY Work
  50. );
  51. VOID
  52. IopStartDevice (
  53. PDEVICE Device
  54. );
  55. KSTATUS
  56. IopAddDrivers (
  57. PDEVICE Device
  58. );
  59. PSTR
  60. IopFindDriverForDevice (
  61. PDEVICE Device
  62. );
  63. VOID
  64. IopQueryChildren (
  65. PDEVICE Device
  66. );
  67. VOID
  68. IopProcessReportedChildren (
  69. PDEVICE Device,
  70. PIRP_QUERY_CHILDREN Result
  71. );
  72. PSTR
  73. IopGetUniqueDeviceId (
  74. PDEVICE ParentDevice,
  75. PSTR DeviceId
  76. );
  77. //
  78. // -------------------------------------------------------------------- Globals
  79. //
  80. //
  81. // Store a pointer to the device work queue.
  82. //
  83. PWORK_QUEUE IoDeviceWorkQueue;
  84. //
  85. // Define the object that roots the device tree.
  86. //
  87. PDEVICE IoRootDevice;
  88. LIST_ENTRY IoDeviceList;
  89. PQUEUED_LOCK IoDeviceListLock;
  90. //
  91. // Store the number of active work items flowing around.
  92. //
  93. UINTN IoDeviceWorkItemsQueued;
  94. //
  95. // ------------------------------------------------------------------ Functions
  96. //
  97. KERNEL_API
  98. KSTATUS
  99. IoCreateDevice (
  100. PDRIVER BusDriver,
  101. PVOID BusDriverContext,
  102. PDEVICE ParentDevice,
  103. PSTR DeviceId,
  104. PSTR ClassId,
  105. PSTR CompatibleIds,
  106. PDEVICE *NewDevice
  107. )
  108. /*++
  109. Routine Description:
  110. This routine creates a new device in the system. This device can be used in
  111. subsequent calls to Query Children.
  112. Arguments:
  113. BusDriver - Supplies a pointer to the driver reporting this device.
  114. BusDriverContext - Supplies the context pointer that will be passed to the
  115. bus driver when IRPs are sent to the device.
  116. ParentDevice - Supplies a pointer to the device enumerating this device.
  117. Most devices are enumerated off of a bus, so this parameter will
  118. contain a pointer to that bus device. For unenumerable devices, this
  119. parameter can be NULL, in which case the device will be enumerated off
  120. of the root device.
  121. DeviceId - Supplies a pointer to a null terminated string identifying the
  122. device. This memory does not have to be retained, a copy of it will be
  123. created during this call.
  124. ClassId - Supplies a pointer to a null terminated string identifying the
  125. device class. This memory does not have to be retained, a copy of it
  126. will be created during this call.
  127. CompatibleIds - Supplies a semicolon-delimited list of device IDs that this
  128. device is compatible with.
  129. NewDevice - Supplies a pointer where the new device will be returned on
  130. success.
  131. Return Value:
  132. Status code.
  133. --*/
  134. {
  135. KSTATUS Status;
  136. Status = IopCreateDevice(BusDriver,
  137. BusDriverContext,
  138. ParentDevice,
  139. DeviceId,
  140. ClassId,
  141. CompatibleIds,
  142. ObjectDevice,
  143. sizeof(DEVICE),
  144. NewDevice);
  145. return Status;
  146. }
  147. KERNEL_API
  148. KSTATUS
  149. IoRemoveUnreportedDevice (
  150. PDEVICE Device
  151. )
  152. /*++
  153. Routine Description:
  154. This routine removes a device that was created but never reported. Devices
  155. created on enumerable busses must be removed by not reporting them in
  156. a query children request. This routine must only be called on devices whose
  157. parent device is the root.
  158. Arguments:
  159. Device - Supplies a pointer to the device to remove.
  160. Return Value:
  161. Status code.
  162. --*/
  163. {
  164. ULONG Flags;
  165. KSTATUS Status;
  166. ASSERT(KeGetRunLevel() == RunLevelLow);
  167. //
  168. // It is an error for a driver to yank out an enumerated device.
  169. //
  170. if ((Device->State != DeviceUnreported) &&
  171. (Device->State != DeviceInitialized) &&
  172. (Device->ParentDevice != IoRootDevice)) {
  173. KeCrashSystem(CRASH_DRIVER_ERROR,
  174. DriverErrorRemovingEnumeratedDevice,
  175. (UINTN)Device,
  176. Device->State,
  177. (UINTN)(Device->ParentDevice));
  178. }
  179. Flags = DEVICE_ACTION_SEND_TO_SUBTREE | DEVICE_ACTION_OPEN_QUEUE;
  180. Status = IopQueueDeviceWork(Device,
  181. DeviceActionPrepareRemove,
  182. NULL,
  183. Flags);
  184. //
  185. // If the action failed to queue for a reason other than that the device
  186. // was already awaiting removal, set the problem state. Do not call the
  187. // queue failure handler as that can roll back the parent's device state,
  188. // but in this case the parent isn't expecting an answer from the child's
  189. // removal process.
  190. //
  191. if (!KSUCCESS(Status) &&
  192. (Status != STATUS_DEVICE_QUEUE_CLOSING)) {
  193. IopSetDeviceProblem(Device,
  194. DeviceProblemFailedToQueuePrepareRemove,
  195. Status);
  196. }
  197. return Status;
  198. }
  199. KERNEL_API
  200. VOID
  201. IoDeviceAddReference (
  202. PDEVICE Device
  203. )
  204. /*++
  205. Routine Description:
  206. This routine increments the reference count on a device.
  207. Arguments:
  208. Device - Supplies a pointer to the device.
  209. Return Value:
  210. None.
  211. --*/
  212. {
  213. ObAddReference(Device);
  214. return;
  215. }
  216. KERNEL_API
  217. VOID
  218. IoDeviceReleaseReference (
  219. PDEVICE Device
  220. )
  221. /*++
  222. Routine Description:
  223. This routine decrements the reference count on a device.
  224. Arguments:
  225. Device - Supplies a pointer to the device.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. ObReleaseReference(Device);
  231. return;
  232. }
  233. KERNEL_API
  234. KSTATUS
  235. IoSetTargetDevice (
  236. PDEVICE Device,
  237. PDEVICE TargetDevice
  238. )
  239. /*++
  240. Routine Description:
  241. This routine sets the target device for a given device. IRPs flow through
  242. a device and then through its target device (if not completed by an
  243. earlier driver). Target devices allow the piling of stacks on one another.
  244. Target device relations must be set either before the device is reported
  245. by the bus, or during AddDevice. They cannot be changed after that. This
  246. routine is not thread safe, as it's only expected to be called by drivers
  247. on the device during early device initialization.
  248. Arguments:
  249. Device - Supplies a pointer to the device to set a target device for.
  250. TargetDevice - Supplies a pointer to the target device.
  251. Return Value:
  252. STATUS_SUCCESS on success.
  253. STATUS_TOO_LATE if the device is already too far through its initialization
  254. to have a target device added to it.
  255. --*/
  256. {
  257. if (Device->State > DeviceInitialized) {
  258. return STATUS_TOO_LATE;
  259. }
  260. if (Device->TargetDevice != NULL) {
  261. ObReleaseReference(Device->TargetDevice);
  262. }
  263. if (TargetDevice != NULL) {
  264. ObAddReference(TargetDevice);
  265. }
  266. Device->TargetDevice = TargetDevice;
  267. return STATUS_SUCCESS;
  268. }
  269. KERNEL_API
  270. PDEVICE
  271. IoGetTargetDevice (
  272. PDEVICE Device
  273. )
  274. /*++
  275. Routine Description:
  276. This routine returns the target device for the given device, if any.
  277. Arguments:
  278. Device - Supplies a pointer to the device to get the target device for.
  279. Return Value:
  280. Returns a pointer to the target device.
  281. NULL if there is no target device.
  282. --*/
  283. {
  284. return Device->TargetDevice;
  285. }
  286. PDEVICE
  287. IoGetDiskDevice (
  288. PDEVICE Device
  289. )
  290. /*++
  291. Routine Description:
  292. This routine returns the underlying disk device for a given device.
  293. Arguments:
  294. Device - Supplies a pointer to a device.
  295. Return Value:
  296. Returns a pointer to the disk device that backs the device.
  297. NULL if the given device does not have a disk backing it.
  298. --*/
  299. {
  300. if (Device->Header.Type != ObjectVolume) {
  301. return NULL;
  302. }
  303. while (Device->TargetDevice != NULL) {
  304. Device = Device->TargetDevice;
  305. }
  306. return Device;
  307. }
  308. KERNEL_API
  309. VOID
  310. IoSetDeviceMountable (
  311. PDEVICE Device
  312. )
  313. /*++
  314. Routine Description:
  315. This routine indicates that the given device is mountable. A device cannot
  316. be unmarked as mountable. This routine is not thread safe.
  317. Arguments:
  318. Device - Supplies a pointer to the device that the system could potentially
  319. mount.
  320. Return Value:
  321. None.
  322. --*/
  323. {
  324. Device->Flags |= DEVICE_FLAG_MOUNTABLE;
  325. //
  326. // If the device is not yet fully enumerated, return. The enumeration will
  327. // take care of creating the volume.
  328. //
  329. if (Device->State < DeviceStarted) {
  330. return;
  331. }
  332. //
  333. // This device is being marked mountable after it's fully started. Create
  334. // the volume for it now.
  335. //
  336. if ((Device->Flags & DEVICE_FLAG_MOUNTED) == 0) {
  337. IoCreateVolume(Device, NULL);
  338. }
  339. return;
  340. }
  341. KERNEL_API
  342. BOOL
  343. IoAreDeviceIdsEqual (
  344. PSTR DeviceIdOne,
  345. PSTR DeviceIdTwo
  346. )
  347. /*++
  348. Routine Description:
  349. This routine determines if the given device IDs match. This routine always
  350. truncates the given device IDs at the last '#' character, if it exists. If
  351. one of the supplied device IDs naturally has a '#' character within it,
  352. then caller should append a second '#' character to the device ID.
  353. Arguments:
  354. DeviceIdOne - Supplies the first device ID.
  355. DeviceIdTwo - Supplies the second device ID.
  356. Return Value:
  357. Returns TRUE if the given device IDs match. FALSE otherwise.
  358. --*/
  359. {
  360. ULONG DeviceIdOneLength;
  361. ULONG DeviceIdTwoLength;
  362. PSTR LastHash;
  363. BOOL Result;
  364. //
  365. // Find the lengths of the two device IDs. If there is a '#' in the device
  366. // ID, then that is treated as the last character.
  367. //
  368. DeviceIdOneLength = RtlStringLength(DeviceIdOne) + 1;
  369. LastHash = RtlStringFindCharacterRight(DeviceIdOne, '#', DeviceIdOneLength);
  370. if (LastHash != NULL) {
  371. DeviceIdOneLength = (UINTN)LastHash - (UINTN)DeviceIdOne + 1;
  372. }
  373. DeviceIdTwoLength = RtlStringLength(DeviceIdTwo) + 1;
  374. LastHash = RtlStringFindCharacterRight(DeviceIdTwo, '#', DeviceIdTwoLength);
  375. if (LastHash != NULL) {
  376. DeviceIdTwoLength = (UINTN)LastHash - (UINTN)DeviceIdTwo + 1;
  377. }
  378. //
  379. // If the device IDs are not the same length, then they cannot match.
  380. //
  381. if (DeviceIdOneLength != DeviceIdTwoLength) {
  382. return FALSE;
  383. }
  384. //
  385. // Compare the device IDs up to the last character. The last characters may
  386. // be NULL terminators or '#' characters, but not necessarily the same.
  387. //
  388. ASSERT((DeviceIdOne[DeviceIdOneLength - 1] == STRING_TERMINATOR) ||
  389. (DeviceIdOne[DeviceIdOneLength - 1] == '#'));
  390. ASSERT((DeviceIdTwo[DeviceIdTwoLength - 1] == STRING_TERMINATOR) ||
  391. (DeviceIdTwo[DeviceIdTwoLength - 1] == '#'));
  392. Result = RtlAreStringsEqual(DeviceIdOne,
  393. DeviceIdTwo,
  394. DeviceIdOneLength - 1);
  395. return Result;
  396. }
  397. KERNEL_API
  398. PSTR
  399. IoGetDeviceId (
  400. PDEVICE Device
  401. )
  402. /*++
  403. Routine Description:
  404. This routine returns the device ID of the given system device.
  405. Arguments:
  406. Device - Supplies the device to get the ID of.
  407. Return Value:
  408. Returns a pionter to a string representing the device's Identifier.
  409. --*/
  410. {
  411. return Device->Header.Name;
  412. }
  413. KERNEL_API
  414. PSTR
  415. IoGetCompatibleDeviceIds (
  416. PDEVICE Device
  417. )
  418. /*++
  419. Routine Description:
  420. This routine returns a semilcolon-delimited list of device IDs that this
  421. device is compatible with.
  422. Arguments:
  423. Device - Supplies the device to get the compatible IDs of.
  424. Return Value:
  425. Returns a pointer to a semicolon-delimited string of device IDs that this
  426. device is compatible with, not including the actual device ID itself.
  427. NULL if the compatible ID list is empty.
  428. --*/
  429. {
  430. return Device->CompatibleIds;
  431. }
  432. KERNEL_API
  433. PSTR
  434. IoGetDeviceClassId (
  435. PDEVICE Device
  436. )
  437. /*++
  438. Routine Description:
  439. This routine returns the class ID of the given device.
  440. Arguments:
  441. Device - Supplies the device to get the class ID of.
  442. Return Value:
  443. Returns the class ID of the given device.
  444. NULL if the device was not created with a class ID.
  445. --*/
  446. {
  447. return Device->ClassId;
  448. }
  449. KERNEL_API
  450. BOOL
  451. IoIsDeviceIdInCompatibleIdList (
  452. PSTR DeviceId,
  453. PDEVICE Device
  454. )
  455. /*++
  456. Routine Description:
  457. This routine determines if the given device ID is present in the semicolon-
  458. delimited list of compatible device IDs of the given device, or matches
  459. the device ID itself.
  460. This routine must be called at Low level.
  461. Arguments:
  462. DeviceId - Supplies the device ID in question.
  463. Device - Supplies the device whose compatible IDs should be queried.
  464. Return Value:
  465. TRUE if the given device ID string is present in the device's compatible ID
  466. list.
  467. FALSE if the device ID string is not present in the compatible ID list.
  468. --*/
  469. {
  470. PSTR CurrentId;
  471. ULONG DeviceIdSize;
  472. BOOL Match;
  473. PSTR MutableCopy;
  474. BOOL Result;
  475. PSTR Semicolon;
  476. ULONG StringSize;
  477. ASSERT(KeGetRunLevel() == RunLevelLow);
  478. Match = IoAreDeviceIdsEqual(IoGetDeviceId(Device), DeviceId);
  479. if (Match != FALSE) {
  480. return TRUE;
  481. }
  482. if (Device->CompatibleIds == NULL) {
  483. return FALSE;
  484. }
  485. Result = FALSE;
  486. //
  487. // Make a mutable copy of the compatible ID string.
  488. //
  489. StringSize = RtlStringLength(Device->CompatibleIds) + 1;
  490. MutableCopy = MmAllocatePagedPool(StringSize, IO_ALLOCATION_TAG);
  491. if (MutableCopy == NULL) {
  492. goto IoIsDeviceIdInCompatibleIdListEnd;
  493. }
  494. RtlCopyMemory(MutableCopy, Device->CompatibleIds, StringSize);
  495. //
  496. // Loop through every compatible ID.
  497. //
  498. DeviceIdSize = RtlStringLength(DeviceId) + 1;
  499. CurrentId = MutableCopy;
  500. while (TRUE) {
  501. if (*CurrentId == '\0') {
  502. break;
  503. }
  504. //
  505. // Find the next semicolon and mark it as a null terminator.
  506. //
  507. Semicolon = RtlStringFindCharacter(CurrentId,
  508. COMPATIBLE_ID_DELIMITER,
  509. StringSize);
  510. if (Semicolon != NULL) {
  511. *Semicolon = '\0';
  512. Semicolon += 1;
  513. }
  514. //
  515. // Compare the IDs.
  516. //
  517. Match = RtlAreStringsEqual(DeviceId, CurrentId, DeviceIdSize);
  518. if (Match != FALSE) {
  519. Result = TRUE;
  520. break;
  521. }
  522. //
  523. // Advance the string.
  524. //
  525. if (Semicolon == NULL) {
  526. break;
  527. }
  528. StringSize -= (UINTN)Semicolon - (UINTN)CurrentId;
  529. if (StringSize == 0) {
  530. break;
  531. }
  532. CurrentId = Semicolon;
  533. }
  534. IoIsDeviceIdInCompatibleIdListEnd:
  535. if (MutableCopy != NULL) {
  536. MmFreePagedPool(MutableCopy);
  537. }
  538. return Result;
  539. }
  540. KERNEL_API
  541. DEVICE_ID
  542. IoGetDeviceNumericId (
  543. PDEVICE Device
  544. )
  545. /*++
  546. Routine Description:
  547. This routine gets the numeric device ID for the given device.
  548. Arguments:
  549. Device - Supplies a pointer to the device whose numeric ID is being queried.
  550. Return Value:
  551. Returns the numeric device ID for the device.
  552. --*/
  553. {
  554. return Device->DeviceId;
  555. }
  556. KERNEL_API
  557. PDEVICE
  558. IoGetDeviceByNumericId (
  559. DEVICE_ID DeviceId
  560. )
  561. /*++
  562. Routine Description:
  563. This routine looks up a device given its numeric device ID. This routine
  564. will increment the reference count of the device returned, it is the
  565. caller's responsibility to release that reference. Only devices that are in
  566. the started state will be returned. This routine must be called at low
  567. level.
  568. Arguments:
  569. DeviceId - Supplies the numeric device ID of the device to get.
  570. Return Value:
  571. Returns a pointer to the device with the given numeric device ID on
  572. success. This routine will add a reference to the device returned, it is
  573. the caller's responsibility to release this reference when finished with
  574. the device.
  575. --*/
  576. {
  577. PLIST_ENTRY CurrentEntry;
  578. PDEVICE Device;
  579. PDEVICE FoundDevice;
  580. ASSERT(KeGetRunLevel() == RunLevelLow);
  581. FoundDevice = NULL;
  582. KeAcquireQueuedLock(IoDeviceListLock);
  583. CurrentEntry = IoDeviceList.Next;
  584. while (CurrentEntry != &IoDeviceList) {
  585. Device = LIST_VALUE(CurrentEntry, DEVICE, ListEntry);
  586. if (Device->DeviceId == DeviceId) {
  587. if (Device->State == DeviceStarted) {
  588. ObAddReference(Device);
  589. FoundDevice = Device;
  590. }
  591. break;
  592. }
  593. CurrentEntry = CurrentEntry->Next;
  594. }
  595. KeReleaseQueuedLock(IoDeviceListLock);
  596. return FoundDevice;
  597. }
  598. KERNEL_API
  599. KSTATUS
  600. IoMergeChildArrays (
  601. PIRP QueryChildrenIrp,
  602. PDEVICE *Children,
  603. ULONG ChildCount,
  604. ULONG AllocationTag
  605. )
  606. /*++
  607. Routine Description:
  608. This routine merges a device's enumerated children with the array that is
  609. already present in the Query Children IRP. If needed, a new array containing
  610. the merged list will be created and stored in the IRP, and the old list
  611. will be freed. If the IRP has no list yet, a copy of the array passed in
  612. will be created and set in the IRP.
  613. Arguments:
  614. QueryChildrenIrp - Supplies a pointer to the Query Children IRP.
  615. Children - Supplies a pointer to the device children. This array will not be
  616. used in the IRP, so this array can be temporarily allocated.
  617. ChildCount - Supplies the number of elements in the pointer array.
  618. AllocationTag - Supplies the allocate tag to use for the newly created
  619. array.
  620. Return Value:
  621. STATUS_SUCCESS on success.
  622. STATUS_INSUFFICIENT_RESOURCES if the new array could not be allocated.
  623. --*/
  624. {
  625. ULONG AllocationSize;
  626. PDEVICE *IrpArray;
  627. ULONG IrpArrayCount;
  628. ULONG IrpIndex;
  629. PDEVICE *NewArray;
  630. ULONG NewCount;
  631. ULONG NewIndex;
  632. KSTATUS Status;
  633. if ((QueryChildrenIrp == NULL) || (Children == NULL)) {
  634. return STATUS_INVALID_PARAMETER;
  635. }
  636. ASSERT(QueryChildrenIrp->MajorCode == IrpMajorStateChange);
  637. ASSERT(QueryChildrenIrp->MinorCode == IrpMinorQueryChildren);
  638. IrpArray = QueryChildrenIrp->U.QueryChildren.Children;
  639. IrpArrayCount = QueryChildrenIrp->U.QueryChildren.ChildCount;
  640. //
  641. // First look to see if all devices in the child array are already in the
  642. // existing IRP.
  643. //
  644. if ((IrpArray != NULL) && (IrpArrayCount != 0)) {
  645. for (NewIndex = 0; NewIndex < ChildCount; NewIndex += 1) {
  646. //
  647. // Look through the IRP array for the given child.
  648. //
  649. for (IrpIndex = 0; IrpIndex < IrpArrayCount; IrpIndex += 1) {
  650. if (IrpArray[IrpIndex] == Children[NewIndex]) {
  651. break;
  652. }
  653. }
  654. //
  655. // If the child was not found, stop looping.
  656. //
  657. if (IrpIndex == IrpArrayCount) {
  658. break;
  659. }
  660. }
  661. //
  662. // If every device in the new array was already in the existing array,
  663. // then there's nothing to do, the existing list is fine.
  664. //
  665. if (NewIndex == ChildCount) {
  666. Status = STATUS_SUCCESS;
  667. goto MergeChildArraysEnd;
  668. }
  669. }
  670. //
  671. // Make a pessimistically sized array assuming nothing will merge.
  672. //
  673. AllocationSize = (IrpArrayCount + ChildCount) * sizeof(PDEVICE);
  674. NewArray = MmAllocatePagedPool(AllocationSize, AllocationTag);
  675. if (NewArray == NULL) {
  676. Status = STATUS_INSUFFICIENT_RESOURCES;
  677. goto MergeChildArraysEnd;
  678. }
  679. RtlZeroMemory(NewArray, AllocationSize);
  680. //
  681. // If there is no existing array, just copy and finish!
  682. //
  683. if ((IrpArray == NULL) || (IrpArrayCount == 0)) {
  684. RtlCopyMemory(NewArray, Children, ChildCount * sizeof(PDEVICE));
  685. NewCount = ChildCount;
  686. QueryChildrenIrp->U.QueryChildren.Children = NewArray;
  687. QueryChildrenIrp->U.QueryChildren.ChildCount = NewCount;
  688. Status = STATUS_SUCCESS;
  689. goto MergeChildArraysEnd;
  690. }
  691. //
  692. // An existing array definitely exists. Start by copying in all the stuff
  693. // that's already there.
  694. //
  695. RtlCopyMemory(NewArray, IrpArray, IrpArrayCount * sizeof(PDEVICE));
  696. NewCount = IrpArrayCount;
  697. //
  698. // Go through every child again, and if it's not already in the list, add
  699. // it to the list.
  700. //
  701. for (NewIndex = 0; NewIndex < ChildCount; NewIndex += 1) {
  702. //
  703. // Look to see if it is already in the destination list.
  704. //
  705. for (IrpIndex = 0; IrpIndex < NewCount; IrpIndex += 1) {
  706. if (NewArray[IrpIndex] == Children[NewIndex]) {
  707. break;
  708. }
  709. }
  710. //
  711. // If the child was not found, add it to the end of the array. This
  712. // will not overflow because the array was allocated assuming nothing
  713. // would merge.
  714. //
  715. if (IrpIndex == NewCount) {
  716. NewArray[NewCount] = Children[NewIndex];
  717. NewCount += 1;
  718. }
  719. }
  720. //
  721. // Free the old array and replace it with this great one.
  722. //
  723. MmFreePagedPool(QueryChildrenIrp->U.QueryChildren.Children);
  724. QueryChildrenIrp->U.QueryChildren.Children = NewArray;
  725. QueryChildrenIrp->U.QueryChildren.ChildCount = NewCount;
  726. Status = STATUS_SUCCESS;
  727. MergeChildArraysEnd:
  728. return Status;
  729. }
  730. KERNEL_API
  731. KSTATUS
  732. IoNotifyDeviceTopologyChange (
  733. PDEVICE Device
  734. )
  735. /*++
  736. Routine Description:
  737. This routine notifies the system that the device topology has changed for
  738. the given device. This routine is meant to be called by a device driver
  739. when it notices a child device is missing or when a new device arrives.
  740. Arguments:
  741. Device - Supplies a pointer to the device whose topology has changed.
  742. Return Value:
  743. None.
  744. --*/
  745. {
  746. KSTATUS Status;
  747. ASSERT(KeGetRunLevel() == RunLevelLow);
  748. ASSERT(Device != NULL);
  749. //
  750. // Queue up a work item to handle this, allowing the driver to finish
  751. // processing.
  752. //
  753. Status = IopQueueDeviceWork(Device, DeviceActionQueryChildren, NULL, 0);
  754. if (!KSUCCESS(Status)) {
  755. goto NotifyDeviceTopologyChangeEnd;
  756. }
  757. NotifyDeviceTopologyChangeEnd:
  758. return Status;
  759. }
  760. KERNEL_API
  761. BOOL
  762. IoIsDeviceStarted (
  763. PDEVICE Device
  764. )
  765. /*++
  766. Routine Description:
  767. This routine returns whether or not the device is in the started state.
  768. Arguments:
  769. Device - Supplies a pointer to the device in question.
  770. Return Value:
  771. Returns TRUE if the device is in the started state, or FALSE otherwise.
  772. --*/
  773. {
  774. //
  775. // This is a simple spot check and does not wait on the device to signal.
  776. //
  777. if (Device->State == DeviceStarted) {
  778. return TRUE;
  779. }
  780. return FALSE;
  781. }
  782. KERNEL_API
  783. VOID
  784. IoSetDeviceDriverErrorEx (
  785. PDEVICE Device,
  786. KSTATUS Status,
  787. PDRIVER Driver,
  788. ULONG DriverError,
  789. PSTR SourceFile,
  790. ULONG LineNumber
  791. )
  792. /*++
  793. Routine Description:
  794. This routine sets a driver specific error code on a given device. This
  795. problem is preventing a device from making forward progress. Avoid calling
  796. this function directly, use the non-Ex version.
  797. Arguments:
  798. Device - Supplies a pointer to the device with the error.
  799. Status - Supplies the failure status generated by the error.
  800. Driver - Supplies a pointer to the driver reporting the error.
  801. DriverError - Supplies an optional driver specific error code.
  802. SourceFile - Supplies a pointer to the source file where the problem
  803. occurred. This is usually automatically generated by the compiler.
  804. LineNumber - Supplies the line number in the source file where the problem
  805. occurred. This is usually automatically generated by the compiler.
  806. Return Value:
  807. None.
  808. --*/
  809. {
  810. IopSetDeviceProblemEx(Device,
  811. DeviceProblemDriverError,
  812. Status,
  813. Driver,
  814. DriverError,
  815. SourceFile,
  816. LineNumber);
  817. return;
  818. }
  819. KERNEL_API
  820. KSTATUS
  821. IoClearDeviceProblem (
  822. PDEVICE Device
  823. )
  824. /*++
  825. Routine Description:
  826. This routine clears any problem code associated with a device, and attempts
  827. to start the device if it is not already started.
  828. Arguments:
  829. Device - Supplies a pointer to the device to clear.
  830. Return Value:
  831. STATUS_SUCCESS if the problem was successfully cleared and the start device
  832. work item was successfully queued (if needed).
  833. Error code if the start work item needed to be queued and had a problem.
  834. --*/
  835. {
  836. KSTATUS Status;
  837. Device->ProblemState.Problem = DeviceProblemNone;
  838. Device->ProblemState.Driver = NULL;
  839. //
  840. // Signal anyone waiting on the device. They were queued up waiting for it
  841. // to complete a state transition. It failed to do so; let them check the
  842. // status.
  843. //
  844. ObSignalObject(Device, SignalOptionUnsignal);
  845. Status = STATUS_SUCCESS;
  846. if (Device->State != DeviceStarted) {
  847. Status = IopQueueDeviceWork(Device, DeviceActionStart, NULL, 0);
  848. if (!KSUCCESS(Status)) {
  849. IopSetDeviceProblem(Device,
  850. DeviceProblemFailedToQueueStart,
  851. Status);
  852. }
  853. }
  854. return Status;
  855. }
  856. KSTATUS
  857. IopCreateDevice (
  858. PDRIVER BusDriver,
  859. PVOID BusDriverContext,
  860. PDEVICE ParentDevice,
  861. PSTR DeviceId,
  862. PSTR ClassId,
  863. PSTR CompatibleIds,
  864. OBJECT_TYPE DeviceType,
  865. ULONG DeviceSize,
  866. PDEVICE *NewDevice
  867. )
  868. /*++
  869. Routine Description:
  870. This routine creates a new device or volume. This routine must be called at
  871. low level.
  872. Arguments:
  873. BusDriver - Supplies a pointer to the driver reporting this device.
  874. BusDriverContext - Supplies the context pointer that will be passed to the
  875. bus driver when IRPs are sent to the device.
  876. ParentDevice - Supplies a pointer to the device enumerating this device.
  877. Most devices are enumerated off of a bus, so this parameter will
  878. contain a pointer to that bus device. For unenumerable devices, this
  879. parameter can be NULL, in which case the device will be enumerated off
  880. of the root device.
  881. DeviceId - Supplies a pointer to a null terminated string identifying the
  882. device. This memory does not have to be retained, a copy of it will be
  883. created during this call.
  884. ClassId - Supplies a pointer to a null terminated string identifying the
  885. device class. This memory does not have to be retained, a copy of it
  886. will be created during this call.
  887. CompatibleIds - Supplies a semicolon-delimited list of device IDs that this
  888. device is compatible with.
  889. DeviceType - Supplies the type of the new device.
  890. DeviceSize - Supplies the size of the new device's data structure.
  891. NewDevice - Supplies a pointer where the new device or volume will be
  892. returned on success.
  893. Return Value:
  894. Status code.
  895. --*/
  896. {
  897. ULONG AllocationSize;
  898. PSTR ClassIdCopy;
  899. PSTR CompatibleIdsCopy;
  900. PDEVICE Device;
  901. KSTATUS Status;
  902. PSTR StringBuffer;
  903. ULONG StringLength;
  904. PSTR UniqueDeviceId;
  905. ASSERT((DeviceType == ObjectDevice) || (DeviceType == ObjectVolume));
  906. ASSERT((DeviceSize == sizeof(DEVICE)) || (DeviceSize == sizeof(VOLUME)));
  907. ASSERT(KeGetRunLevel() == RunLevelLow);
  908. ClassIdCopy = NULL;
  909. CompatibleIdsCopy = NULL;
  910. Device = NULL;
  911. StringBuffer = NULL;
  912. UniqueDeviceId = NULL;
  913. if (NewDevice != NULL) {
  914. *NewDevice = NULL;
  915. }
  916. //
  917. // At least a device ID must be supplied.
  918. //
  919. if (DeviceId == NULL) {
  920. return STATUS_INVALID_PARAMETER;
  921. }
  922. StringLength = RtlStringLength(DeviceId) + 1;
  923. if (StringLength > MAX_DEVICE_ID) {
  924. Status = STATUS_NAME_TOO_LONG;
  925. goto CreateDeviceEnd;
  926. }
  927. //
  928. // Make sure the device ID is unique.
  929. //
  930. UniqueDeviceId = IopGetUniqueDeviceId(ParentDevice, DeviceId);
  931. if (UniqueDeviceId == NULL) {
  932. Status = STATUS_INSUFFICIENT_RESOURCES;
  933. goto CreateDeviceEnd;
  934. }
  935. //
  936. // Determine the allocation size by adding all the optional strings
  937. // together. The device ID will get copied during object creation.
  938. //
  939. AllocationSize = 0;
  940. if (ClassId != NULL) {
  941. StringLength = RtlStringLength(ClassId) + 1;
  942. if (StringLength > MAX_DEVICE_ID) {
  943. Status = STATUS_NAME_TOO_LONG;
  944. goto CreateDeviceEnd;
  945. }
  946. AllocationSize += StringLength;
  947. }
  948. if (CompatibleIds != NULL) {
  949. StringLength = RtlStringLength(CompatibleIds) + 1;
  950. if (AllocationSize + StringLength < AllocationSize) {
  951. Status = STATUS_NAME_TOO_LONG;
  952. goto CreateDeviceEnd;
  953. }
  954. AllocationSize += StringLength;
  955. }
  956. //
  957. // Allocate the optional strings at once and copy them over.
  958. //
  959. if (AllocationSize != 0) {
  960. StringBuffer = MmAllocatePagedPool(AllocationSize,
  961. DEVICE_ALLOCATION_TAG);
  962. if (StringBuffer == NULL) {
  963. Status = STATUS_INSUFFICIENT_RESOURCES;
  964. goto CreateDeviceEnd;
  965. }
  966. StringLength = 0;
  967. if (ClassId != NULL) {
  968. ClassIdCopy = StringBuffer;
  969. StringLength = RtlStringCopy(ClassIdCopy, ClassId, AllocationSize);
  970. AllocationSize -= StringLength;
  971. }
  972. if (CompatibleIds != NULL) {
  973. CompatibleIdsCopy = StringBuffer + StringLength;
  974. AllocationSize -= RtlStringCopy(CompatibleIdsCopy,
  975. CompatibleIds,
  976. AllocationSize);
  977. }
  978. }
  979. ASSERT(AllocationSize == 0);
  980. //
  981. // If no parent device was supplied, the device is created under the root.
  982. //
  983. if (ParentDevice == NULL) {
  984. ParentDevice = IoRootDevice;
  985. }
  986. //
  987. // Create the device object.
  988. //
  989. Device = ObCreateObject(DeviceType,
  990. ParentDevice,
  991. UniqueDeviceId,
  992. RtlStringLength(UniqueDeviceId) + 1,
  993. DeviceSize,
  994. IopDestroyDevice,
  995. 0,
  996. DEVICE_ALLOCATION_TAG);
  997. if (Device == NULL) {
  998. Status = STATUS_INSUFFICIENT_RESOURCES;
  999. goto CreateDeviceEnd;
  1000. }
  1001. Device->DeviceId = IopGetNextDeviceId();
  1002. Device->Lock = KeCreateSharedExclusiveLock();
  1003. if (Device->Lock == NULL) {
  1004. Status = STATUS_INSUFFICIENT_RESOURCES;
  1005. goto CreateDeviceEnd;
  1006. }
  1007. Device->QueueLock = KeCreateQueuedLock();
  1008. if (Device->QueueLock == NULL) {
  1009. Status = STATUS_INSUFFICIENT_RESOURCES;
  1010. goto CreateDeviceEnd;
  1011. }
  1012. //
  1013. // Initialize the active child list.
  1014. //
  1015. INITIALIZE_LIST_HEAD(&(Device->ActiveChildListHead));
  1016. ASSERT(Device->ActiveListEntry.Next == NULL);
  1017. //
  1018. // Initialize the arbiter lists.
  1019. //
  1020. INITIALIZE_LIST_HEAD(&(Device->ArbiterListHead));
  1021. INITIALIZE_LIST_HEAD(&(Device->ArbiterAllocationListHead));
  1022. //
  1023. // Initialize string pointers.
  1024. //
  1025. Device->ClassId = ClassIdCopy;
  1026. Device->CompatibleIds = CompatibleIdsCopy;
  1027. //
  1028. // Store the parent device. A reference does not need to be taken here
  1029. // because the object manager already took a reference on the parent.
  1030. //
  1031. Device->ParentDevice = ParentDevice;
  1032. //
  1033. // Initialize the device queue.
  1034. //
  1035. INITIALIZE_LIST_HEAD(&(Device->WorkQueue));
  1036. ASSERT(Device->DriverStackSize == 0);
  1037. INITIALIZE_LIST_HEAD(&(Device->DriverStackHead));
  1038. IopSetDeviceState(Device, DeviceUnreported);
  1039. Device->QueueState = DeviceQueueClosed;
  1040. //
  1041. // Attach the bus driver if present.
  1042. //
  1043. if (BusDriver != NULL) {
  1044. Status = IoAttachDriverToDevice(BusDriver, Device, BusDriverContext);
  1045. if (!KSUCCESS(Status)) {
  1046. goto CreateDeviceEnd;
  1047. }
  1048. }
  1049. //
  1050. // If the device was enumerated by something, then it needs to be reported
  1051. // as well. If this was an unenumerable device, set the state straight to
  1052. // initialized.
  1053. //
  1054. if ((ParentDevice == IoRootDevice) ||
  1055. (ParentDevice == (PDEVICE)IoVolumeDirectory)) {
  1056. IopSetDeviceState(Device, DeviceInitialized);
  1057. Device->QueueState = DeviceQueueOpen;
  1058. }
  1059. //
  1060. // With success on the horizon, add this element to the parent device's
  1061. // active child list, unless the parent is the volume directory.
  1062. //
  1063. if ((ParentDevice != NULL) &&
  1064. (ParentDevice != (PDEVICE)IoVolumeDirectory)) {
  1065. //
  1066. // Acquire the parent device's lock exclusivley and make sure that the
  1067. // parent isn't in the process of being removed.
  1068. //
  1069. KeAcquireSharedExclusiveLockExclusive(ParentDevice->Lock);
  1070. if (ParentDevice->State == DeviceAwaitingRemoval) {
  1071. KeReleaseSharedExclusiveLockExclusive(ParentDevice->Lock);
  1072. Status = STATUS_PARENT_AWAITING_REMOVAL;
  1073. goto CreateDeviceEnd;
  1074. }
  1075. //
  1076. // Device creation should never happen with a removed parent. A device
  1077. // in the removed state has received the remove IRP and should not be
  1078. // creating new devices.
  1079. //
  1080. ASSERT(ParentDevice->State != DeviceRemoved);
  1081. INSERT_BEFORE(&(Device->ActiveListEntry),
  1082. &(ParentDevice->ActiveChildListHead));
  1083. KeReleaseSharedExclusiveLockExclusive(ParentDevice->Lock);
  1084. }
  1085. //
  1086. // Add this device to the global list.
  1087. //
  1088. KeAcquireQueuedLock(IoDeviceListLock);
  1089. INSERT_BEFORE(&(Device->ListEntry), &IoDeviceList);
  1090. KeReleaseQueuedLock(IoDeviceListLock);
  1091. //
  1092. // If this is an unenumerable device, kick off the start action.
  1093. //
  1094. if (ParentDevice == IoRootDevice) {
  1095. Status = IopQueueDeviceWork(Device, DeviceActionStart, NULL, 0);
  1096. if (!KSUCCESS(Status)) {
  1097. IopSetDeviceProblem(Device,
  1098. DeviceProblemFailedToQueueStart,
  1099. Status);
  1100. goto CreateDeviceEnd;
  1101. }
  1102. }
  1103. Status = STATUS_SUCCESS;
  1104. CreateDeviceEnd:
  1105. if (!KSUCCESS(Status)) {
  1106. if (Device != NULL) {
  1107. //
  1108. // If the device's parent is the root, then it may have failed
  1109. // after being placed on the active list. Remove it and then
  1110. // destroy the device.
  1111. //
  1112. if ((ParentDevice == IoRootDevice) &&
  1113. (Device->ActiveListEntry.Next != NULL)) {
  1114. KeAcquireSharedExclusiveLockExclusive(ParentDevice->Lock);
  1115. if (Device->ActiveListEntry.Next != NULL) {
  1116. LIST_REMOVE(&(Device->ActiveListEntry));
  1117. }
  1118. KeReleaseSharedExclusiveLockExclusive(ParentDevice->Lock);
  1119. }
  1120. ObReleaseReference(Device);
  1121. } else {
  1122. if (StringBuffer != NULL) {
  1123. MmFreePagedPool(StringBuffer);
  1124. }
  1125. }
  1126. } else {
  1127. if (NewDevice != NULL) {
  1128. *NewDevice = Device;
  1129. }
  1130. RtlDebugPrint("New Device: %s, 0x%x\n", Device->Header.Name, Device);
  1131. }
  1132. if ((UniqueDeviceId != DeviceId) && (UniqueDeviceId != NULL)) {
  1133. MmFreePagedPool(UniqueDeviceId);
  1134. }
  1135. return Status;
  1136. }
  1137. VOID
  1138. IopSetDeviceState (
  1139. PDEVICE Device,
  1140. DEVICE_STATE NewState
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. This routine sets the device to a new state.
  1145. Arguments:
  1146. Device - Supplies a pointer to the device whose state is to be changed.
  1147. NewState - Supplies a pointer to the new device state.
  1148. Return Value:
  1149. None.
  1150. --*/
  1151. {
  1152. Device->StateHistory[Device->StateHistoryNextIndex] = Device->State;
  1153. Device->StateHistoryNextIndex += 1;
  1154. if (Device->StateHistoryNextIndex == DEVICE_STATE_HISTORY) {
  1155. Device->StateHistoryNextIndex = 0;
  1156. }
  1157. Device->State = NewState;
  1158. return;
  1159. }
  1160. KSTATUS
  1161. IopQueueDeviceWork (
  1162. PDEVICE Device,
  1163. DEVICE_ACTION Action,
  1164. PVOID Parameter,
  1165. ULONG Flags
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. This routine queues work on a device.
  1170. Arguments:
  1171. Device - Supplies a pointer to the device to queue work on.
  1172. Action - Supplies the work to be done on that device.
  1173. Parameter - Supplies a parameter that accompanies the action. The meaning
  1174. of this parameter changes with the type of work queued.
  1175. Flags - Supplies a set of flags and options about the work.
  1176. See DEVICE_ACTION_* definitions.
  1177. Return Value:
  1178. STATUS_SUCCESS if the request was queued on at least one device.
  1179. STATUS_NO_ELIGIBLE_DEVICES if the request could not be queued because the
  1180. devices are not accepting work.
  1181. STATUS_INSUFFICIENT_RESOURCES if memory could not be allocated.
  1182. Other error codes on other failures.
  1183. --*/
  1184. {
  1185. PDEVICE_WORK_ENTRY NewEntry;
  1186. BOOL NewWorkItemNeeded;
  1187. DEVICE_QUEUE_STATE OldQueueState;
  1188. BOOL Result;
  1189. KSTATUS Status;
  1190. ASSERT(KeGetRunLevel() == RunLevelLow);
  1191. //
  1192. // Attempts to queue the remove action should also close the queue.
  1193. //
  1194. ASSERT((Action != DeviceActionRemove) ||
  1195. ((Flags & DEVICE_ACTION_CLOSE_QUEUE) != 0));
  1196. NewEntry = NULL;
  1197. Status = STATUS_SUCCESS;
  1198. if (Device->QueueState == DeviceQueueActiveClosing) {
  1199. Status = STATUS_DEVICE_QUEUE_CLOSING;
  1200. goto QueueDeviceWorkEnd;
  1201. }
  1202. //
  1203. // Do not queue work to a device that is in an invalid state or whose queue
  1204. // is closed unless the open queue flag is supplied.
  1205. //
  1206. if (((Flags & DEVICE_ACTION_OPEN_QUEUE) == 0) &&
  1207. ((!IO_IS_DEVICE_ALIVE(Device)) || (!IO_IS_DEVICE_QUEUE_OPEN(Device)))) {
  1208. Status = STATUS_NO_ELIGIBLE_DEVICES;
  1209. goto QueueDeviceWorkEnd;
  1210. }
  1211. //
  1212. // Determine if a test hook is requesting this call to fail.
  1213. //
  1214. Result = IopIsTestHookSet(IO_FAIL_QUEUE_DEVICE_WORK);
  1215. if (Result != FALSE) {
  1216. Status = STATUS_UNSUCCESSFUL;
  1217. goto QueueDeviceWorkEnd;
  1218. }
  1219. //
  1220. // Allocate the work item entry.
  1221. //
  1222. NewEntry = MmAllocatePagedPool(sizeof(DEVICE_WORK_ENTRY),
  1223. DEVICE_WORK_ALLOCATION_TAG);
  1224. if (NewEntry == NULL) {
  1225. Status = STATUS_INSUFFICIENT_RESOURCES;
  1226. goto QueueDeviceWorkEnd;
  1227. }
  1228. NewEntry->Action = Action;
  1229. NewEntry->Flags = Flags;
  1230. NewEntry->Parameter = Parameter;
  1231. //
  1232. // Acquire the lock and insert the item onto the queue. While the lock is
  1233. // held, determine if a work item is already in flight for this device.
  1234. // There's also a chance that the work queue closed or was marked as
  1235. // closing since it was last checked.
  1236. //
  1237. NewWorkItemNeeded = TRUE;
  1238. KeAcquireQueuedLock(Device->QueueLock);
  1239. OldQueueState = Device->QueueState;
  1240. if (Device->QueueState == DeviceQueueActiveClosing) {
  1241. Status = STATUS_DEVICE_QUEUE_CLOSING;
  1242. } else if (IO_IS_DEVICE_QUEUE_OPEN(Device) ||
  1243. ((Flags & DEVICE_ACTION_OPEN_QUEUE) != 0)) {
  1244. ASSERT(Device->State != DeviceRemoved);
  1245. if (Device->QueueState == DeviceQueueActive) {
  1246. NewWorkItemNeeded = FALSE;
  1247. } else {
  1248. ASSERT(LIST_EMPTY(&(Device->WorkQueue)) != FALSE);
  1249. Device->QueueState = DeviceQueueActive;
  1250. }
  1251. INSERT_BEFORE(&(NewEntry->ListEntry), &(Device->WorkQueue));
  1252. //
  1253. // Mark the queue as closing if requested.
  1254. //
  1255. if ((Flags & DEVICE_ACTION_CLOSE_QUEUE) != 0) {
  1256. Device->QueueState = DeviceQueueActiveClosing;
  1257. }
  1258. } else {
  1259. Status = STATUS_NO_ELIGIBLE_DEVICES;
  1260. }
  1261. KeReleaseQueuedLock(Device->QueueLock);
  1262. if (!KSUCCESS(Status)) {
  1263. goto QueueDeviceWorkEnd;
  1264. }
  1265. //
  1266. // If the device queue was not actively processing items, queue a work
  1267. // item to process the new work.
  1268. //
  1269. if (NewWorkItemNeeded != FALSE) {
  1270. RtlAtomicAdd(&IoDeviceWorkItemsQueued, 1);
  1271. Status = KeCreateAndQueueWorkItem(IoDeviceWorkQueue,
  1272. WorkPriorityNormal,
  1273. IopDeviceWorker,
  1274. Device);
  1275. if (!KSUCCESS(Status)) {
  1276. RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
  1277. //
  1278. // Bad news if a work item could not be queued. Mark the queue as
  1279. // open but not active so that the next request will try again to
  1280. // create a work item.
  1281. //
  1282. KeAcquireQueuedLock(Device->QueueLock);
  1283. //
  1284. // If the queue was active and work item creation failed, revert to
  1285. // the old queue state so the next request can try to create a work
  1286. // item. No work item could have been allocated before the failure.
  1287. //
  1288. ASSERT((Device->QueueState == DeviceQueueActive) ||
  1289. (Device->QueueState == DeviceQueueActiveClosing));
  1290. Device->QueueState = OldQueueState;
  1291. //
  1292. // Remove this item from the list.
  1293. //
  1294. LIST_REMOVE(&(NewEntry->ListEntry));
  1295. KeReleaseQueuedLock(Device->QueueLock);
  1296. goto QueueDeviceWorkEnd;
  1297. }
  1298. }
  1299. QueueDeviceWorkEnd:
  1300. if (!KSUCCESS(Status)) {
  1301. if (NewEntry != NULL) {
  1302. MmFreePagedPool(NewEntry);
  1303. }
  1304. }
  1305. return Status;
  1306. }
  1307. VOID
  1308. IopHandleDeviceQueueFailure (
  1309. PDEVICE Device,
  1310. DEVICE_ACTION Action
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. This routine handles a failure to add a work item to a device queue.
  1315. Arguments:
  1316. Device - Supplies a pointer to the device that could not accept the action.
  1317. Action - Supplies the action that failed to be added to the given device's
  1318. work queue.
  1319. Return Value:
  1320. None.
  1321. --*/
  1322. {
  1323. switch (Action) {
  1324. //
  1325. // A prepare remove action may not have been able to be queued for a few
  1326. // reasons:
  1327. //
  1328. // 1. Another device tree removal process already scheduled the remove
  1329. // action on the given device, but it is yet to run. This case should
  1330. // be handled by the caller by ignoring the "queue closing" failure
  1331. // status from the attempt to queue the work item.
  1332. //
  1333. // 2. An allocation failed, in which case the device tree state must be
  1334. // rolled back because a parent device is expecting this child to be
  1335. // removed. This queue failure handler should only be called if the
  1336. // parent device expects a response from the prepare remove action. That
  1337. // is, do not call it when the root of a removal tree fails to queue the
  1338. // action.
  1339. //
  1340. case DeviceActionPrepareRemove:
  1341. //
  1342. // The device should not be in the removed state when queing fails.
  1343. //
  1344. ASSERT(Device->State != DeviceRemoved);
  1345. //
  1346. // The prepare remove work item can fail because it is in the awaiting
  1347. // removal state and the remove work item has already been queued. This
  1348. // case, however, should be handled by the queuer; assert here to make
  1349. // sure the case does not enter this code path.
  1350. //
  1351. ASSERT((Device->State != DeviceAwaitingRemoval) ||
  1352. (Device->QueueState != DeviceQueueActiveClosing));
  1353. IopAbortDeviceRemoval(Device,
  1354. DeviceProblemFailedToQueuePrepareRemove,
  1355. FALSE);
  1356. break;
  1357. //
  1358. // A device remove action can only be triggered from the prepare remove
  1359. // work item or from a child's removal work item. Any device that has
  1360. // children should be able to queue work items. Additionally, once a device
  1361. // is in the awaiting removal state, there should only ever be one attempt
  1362. // at queuing a removal work item. This means that the only reason for a
  1363. // removal queuing to fail is due to allocation failure. The only recourse
  1364. // to a failed allocation in this code path is to roll back the removal
  1365. // process.
  1366. //
  1367. case DeviceActionRemove:
  1368. //
  1369. // The device should be awaiting removal, meaning that the device is
  1370. // active enough to receive work items. But further assert that it is
  1371. // active, meaning there is no reason the device state kept it from
  1372. // receiving a work item.
  1373. //
  1374. ASSERT(Device->State == DeviceAwaitingRemoval);
  1375. ASSERT(IO_IS_DEVICE_ALIVE(Device) != FALSE);
  1376. //
  1377. // The removal action should not fail to be appended to the work queue
  1378. // because the queue is closed or closing.
  1379. //
  1380. ASSERT(IO_IS_DEVICE_QUEUE_OPEN(Device) != FALSE);
  1381. //
  1382. // Abort the removal process, reverting the actions of the prepare
  1383. // removal work item.
  1384. //
  1385. IopAbortDeviceRemoval(Device, DeviceProblemFailedToQueueRemove, TRUE);
  1386. break;
  1387. case DeviceActionStart:
  1388. case DeviceActionQueryChildren:
  1389. case DeviceActionInvalid:
  1390. default:
  1391. break;
  1392. }
  1393. return;
  1394. }
  1395. VOID
  1396. IopSetDeviceProblemEx (
  1397. PDEVICE Device,
  1398. DEVICE_PROBLEM Problem,
  1399. KSTATUS Status,
  1400. PDRIVER Driver,
  1401. ULONG DriverCode,
  1402. PSTR SourceFile,
  1403. ULONG LineNumber
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. This routine sets a device problem code on a given device. This problem is
  1408. usually preventing a device from starting or otherwise making forward
  1409. progress. Avoid calling this function directly, use the non-Ex version.
  1410. Arguments:
  1411. Device - Supplies a pointer to the device with the problem.
  1412. Problem - Supplies the problem with the device.
  1413. Status - Supplies the failure status generated by the error.
  1414. Driver - Supplies a pointer to the driver reporting the error. This
  1415. parameter is optional.
  1416. DriverCode - Supplies an optional problem driver-specific error code.
  1417. SourceFile - Supplies a pointer to the source file where the problem
  1418. occurred. This is usually automatically generated by the compiler.
  1419. LineNumber - Supplies the line number in the source file where the problem
  1420. occurred. This is usually automatically generated by the compiler.
  1421. Return Value:
  1422. None.
  1423. --*/
  1424. {
  1425. Device->ProblemState.Problem = Problem;
  1426. Device->ProblemState.Driver = Driver;
  1427. Device->ProblemState.Status = Status;
  1428. Device->ProblemState.DriverCode = DriverCode;
  1429. Device->ProblemState.File = SourceFile;
  1430. Device->ProblemState.Line = LineNumber;
  1431. //
  1432. // Signal anyone waiting on the device. They were queued up waiting for it
  1433. // to complete a state transition. It failed to do so; let them check the
  1434. // status.
  1435. //
  1436. ObSignalObject(Device, SignalOptionSignalAll);
  1437. return;
  1438. }
  1439. VOID
  1440. IopClearDeviceProblem (
  1441. PDEVICE Device
  1442. )
  1443. /*++
  1444. Routine Description:
  1445. This routine clears any problem code associated with a device.
  1446. Arguments:
  1447. Device - Supplies a pointer to the device whose problem code should be
  1448. cleared.
  1449. Return Value:
  1450. None.
  1451. --*/
  1452. {
  1453. RtlZeroMemory(&(Device->ProblemState), sizeof(DEVICE_PROBLEM_STATE));
  1454. return;
  1455. }
  1456. //
  1457. // --------------------------------------------------------- Internal Functions
  1458. //
  1459. VOID
  1460. IopDeviceWorker (
  1461. PVOID Parameter
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. This routine is the work item that performs actions on devices.
  1466. Arguments:
  1467. Parameter - Supplies the work item parameter, which in this case is a
  1468. pointer to the device to operate on.
  1469. Return Value:
  1470. None.
  1471. --*/
  1472. {
  1473. PDEVICE ChildDevice;
  1474. PLIST_ENTRY CurrentEntry;
  1475. PDEVICE Device;
  1476. PDEVICE FailedDevice;
  1477. ULONG NewFlags;
  1478. UINTN OldWorkItemCount;
  1479. BOOL QueueClosed;
  1480. KSTATUS Status;
  1481. PDEVICE_WORK_ENTRY Work;
  1482. Device = (PDEVICE)Parameter;
  1483. //
  1484. // Loop processing items in the queue.
  1485. //
  1486. while (TRUE) {
  1487. Work = NULL;
  1488. //
  1489. // Dequeue an item.
  1490. //
  1491. QueueClosed = FALSE;
  1492. KeAcquireQueuedLock(Device->QueueLock);
  1493. //
  1494. // If the queue is empty, this work item is finished.
  1495. //
  1496. if (LIST_EMPTY(&(Device->WorkQueue)) != FALSE) {
  1497. ASSERT(Device->QueueState == DeviceQueueActive);
  1498. Device->QueueState = DeviceQueueOpen;
  1499. //
  1500. // This list is not empty, so get an item.
  1501. //
  1502. } else {
  1503. ASSERT((Device->QueueState == DeviceQueueActive) ||
  1504. (Device->QueueState == DeviceQueueActiveClosing));
  1505. Work = LIST_VALUE(Device->WorkQueue.Next,
  1506. DEVICE_WORK_ENTRY,
  1507. ListEntry);
  1508. LIST_REMOVE(&(Work->ListEntry));
  1509. //
  1510. // If the queue is in the active closing state and this is the last
  1511. // item on the list, indicate that the queue should be closed
  1512. // immediately after the work item is executed.
  1513. //
  1514. // N.B. This requires the queue empty check because this could be
  1515. // a work item on the queue in front of the remove action.
  1516. //
  1517. if ((Device->QueueState == DeviceQueueActiveClosing) &&
  1518. (LIST_EMPTY(&(Device->WorkQueue)) != FALSE)) {
  1519. ASSERT((Work->Flags & DEVICE_ACTION_CLOSE_QUEUE) != 0);
  1520. ASSERT(Work->Action == DeviceActionRemove);
  1521. QueueClosed = TRUE;
  1522. }
  1523. }
  1524. KeReleaseQueuedLock(Device->QueueLock);
  1525. //
  1526. // If no work was found, end this work item.
  1527. //
  1528. if (Work == NULL) {
  1529. goto DeviceWorkerEnd;
  1530. }
  1531. //
  1532. // Do the work, except skip the root device itself.
  1533. //
  1534. if (Device != IoRootDevice) {
  1535. IopProcessWorkEntry(Device, Work);
  1536. }
  1537. //
  1538. // If the device queue was closed above it means that the device worker
  1539. // just processed a remove work item. The remove work item can release
  1540. // the last reference on a device, meaning that this routine can no
  1541. // longer safely touch the device structure. In this case, exit
  1542. // immediately and do not process any children.
  1543. //
  1544. if (QueueClosed != FALSE) {
  1545. ASSERT((Work->Flags & DEVICE_ACTION_SEND_TO_SUBTREE) == 0);
  1546. ASSERT((Work->Flags & DEVICE_ACTION_SEND_TO_CHILDREN) == 0);
  1547. ASSERT((Work->Flags & DEVICE_ACTION_CLOSE_QUEUE) != 0);
  1548. ASSERT(Work->Action == DeviceActionRemove);
  1549. MmFreePagedPool(Work);
  1550. goto DeviceWorkerEnd;
  1551. }
  1552. //
  1553. // If this request is to be propagated to the children, queue those
  1554. // requests now. Acquire the device's lock shared while traversing the
  1555. // children as it would be bad if the list changed in the middle of the
  1556. // loop.
  1557. //
  1558. if (((Work->Flags & DEVICE_ACTION_SEND_TO_SUBTREE) != 0) ||
  1559. ((Work->Flags & DEVICE_ACTION_SEND_TO_CHILDREN) != 0)) {
  1560. FailedDevice = NULL;
  1561. NewFlags = Work->Flags & ~DEVICE_ACTION_SEND_TO_CHILDREN;
  1562. KeAcquireSharedExclusiveLockShared(Device->Lock);
  1563. CurrentEntry = Device->ActiveChildListHead.Next;
  1564. while (CurrentEntry != &(Device->ActiveChildListHead)) {
  1565. ChildDevice = LIST_VALUE(CurrentEntry, DEVICE, ActiveListEntry);
  1566. CurrentEntry = CurrentEntry->Next;
  1567. //
  1568. // Queue the same work item for the child device. It is
  1569. // important that the device's queue lock is NOT held at this
  1570. // point because this routine will modify the queue.
  1571. //
  1572. Status = IopQueueDeviceWork(ChildDevice,
  1573. Work->Action,
  1574. Work->Parameter,
  1575. NewFlags);
  1576. if (!KSUCCESS(Status) &&
  1577. (Status != STATUS_DEVICE_QUEUE_CLOSING)) {
  1578. FailedDevice = ChildDevice;
  1579. ObAddReference(FailedDevice);
  1580. break;
  1581. }
  1582. }
  1583. KeReleaseSharedExclusiveLockShared(Device->Lock);
  1584. //
  1585. // Handle any failures outside of the loop.
  1586. //
  1587. if (FailedDevice != NULL) {
  1588. IopHandleDeviceQueueFailure(FailedDevice, Work->Action);
  1589. ObReleaseReference(FailedDevice);
  1590. }
  1591. }
  1592. //
  1593. // Free this work entry.
  1594. //
  1595. MmFreePagedPool(Work);
  1596. }
  1597. DeviceWorkerEnd:
  1598. OldWorkItemCount = RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
  1599. if (OldWorkItemCount == 1) {
  1600. IopQueueDelayedResourceAssignment();
  1601. }
  1602. return;
  1603. }
  1604. VOID
  1605. IopProcessWorkEntry (
  1606. PDEVICE Device,
  1607. PDEVICE_WORK_ENTRY Work
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. This routine processes a device work request.
  1612. Arguments:
  1613. Device - Supplies a pointer to the device to operate on.
  1614. Work - Supplies a pointer to the work request.
  1615. Return Value:
  1616. None.
  1617. --*/
  1618. {
  1619. switch (Work->Action) {
  1620. case DeviceActionStart:
  1621. IopStartDevice(Device);
  1622. break;
  1623. case DeviceActionQueryChildren:
  1624. IopQueryChildren(Device);
  1625. break;
  1626. case DeviceActionPrepareRemove:
  1627. IopPrepareRemoveDevice(Device, Work);
  1628. break;
  1629. case DeviceActionRemove:
  1630. IopRemoveDevice(Device, Work);
  1631. break;
  1632. case DeviceActionPowerTransition:
  1633. PmpDevicePowerTransition(Device);
  1634. break;
  1635. default:
  1636. ASSERT(FALSE);
  1637. break;
  1638. }
  1639. return;
  1640. }
  1641. VOID
  1642. IopStartDevice (
  1643. PDEVICE Device
  1644. )
  1645. /*++
  1646. Routine Description:
  1647. This routine attempts to process a device from initialized to started, or
  1648. as far as possible until started.
  1649. Arguments:
  1650. Device - Supplies a pointer to the device to start.
  1651. Return Value:
  1652. None.
  1653. --*/
  1654. {
  1655. BOOL Breakout;
  1656. IRP_QUERY_RESOURCES QueryResources;
  1657. IRP_START_DEVICE StartDevice;
  1658. KSTATUS Status;
  1659. //
  1660. // Loop until a resting state is achieved.
  1661. //
  1662. Breakout = FALSE;
  1663. while (Breakout == FALSE) {
  1664. switch (Device->State) {
  1665. //
  1666. // The device has been initialized. Add drivers to the stack.
  1667. //
  1668. case DeviceInitialized:
  1669. if (Device->Header.Type == ObjectVolume) {
  1670. Status = IopAddFileSystem(Device);
  1671. } else {
  1672. Status = IopAddDrivers(Device);
  1673. }
  1674. if (KSUCCESS(Status)) {
  1675. IopSetDeviceState(Device, DeviceDriversAdded);
  1676. } else {
  1677. Breakout = TRUE;
  1678. }
  1679. break;
  1680. //
  1681. // The driver stack has been built. Ask the device about resources.
  1682. //
  1683. case DeviceDriversAdded:
  1684. QueryResources.ResourceRequirements = NULL;
  1685. QueryResources.BootAllocation = NULL;
  1686. Status = IopSendStateChangeIrp(Device,
  1687. IrpMinorQueryResources,
  1688. &QueryResources,
  1689. sizeof(QueryResources));
  1690. if (!KSUCCESS(Status)) {
  1691. IopSetDeviceProblem(Device,
  1692. DeviceProblemFailedQueryResources,
  1693. Status);
  1694. Breakout = TRUE;
  1695. break;
  1696. }
  1697. Device->ResourceRequirements = QueryResources.ResourceRequirements;
  1698. Device->BootResources = QueryResources.BootAllocation;
  1699. IopSetDeviceState(Device, DeviceResourcesQueried);
  1700. break;
  1701. //
  1702. // Queue the resource assignment.
  1703. //
  1704. case DeviceResourcesQueried:
  1705. Status = IopQueueResourceAssignment(Device);
  1706. if (!KSUCCESS(Status)) {
  1707. Breakout = TRUE;
  1708. }
  1709. break;
  1710. //
  1711. // While the resource assignment is in the queue, there's nothing to
  1712. // do but wait.
  1713. //
  1714. case DeviceResourceAssignmentQueued:
  1715. Breakout = TRUE;
  1716. break;
  1717. //
  1718. // Start the device.
  1719. //
  1720. case DeviceResourcesAssigned:
  1721. StartDevice.ProcessorLocalResources =
  1722. Device->ProcessorLocalResources;
  1723. StartDevice.BusLocalResources = Device->BusLocalResources;
  1724. Status = IopSendStateChangeIrp(Device,
  1725. IrpMinorStartDevice,
  1726. &StartDevice,
  1727. sizeof(StartDevice));
  1728. if (!KSUCCESS(Status)) {
  1729. IopSetDeviceProblem(Device, DeviceProblemFailedStart, Status);
  1730. Breakout = TRUE;
  1731. break;
  1732. }
  1733. //
  1734. // Set the device state to awaiting enumeration and queue child
  1735. // enumeration.
  1736. //
  1737. IopSetDeviceState(Device, DeviceAwaitingEnumeration);
  1738. Status = IopQueueDeviceWork(Device,
  1739. DeviceActionQueryChildren,
  1740. NULL,
  1741. 0);
  1742. if (!KSUCCESS(Status)) {
  1743. IopSetDeviceProblem(Device,
  1744. DeviceProblemFailedToQueueQueryChildren,
  1745. Status);
  1746. Breakout = TRUE;
  1747. break;
  1748. }
  1749. break;
  1750. //
  1751. // If the device enumeration is in the queue, there's nothing to do but
  1752. // wait.
  1753. //
  1754. case DeviceAwaitingEnumeration:
  1755. Breakout = TRUE;
  1756. break;
  1757. //
  1758. // If enumeration completed, roll the device to the started state and
  1759. // if it is a new disk device, alert the file system.
  1760. //
  1761. case DeviceEnumerated:
  1762. IopSetDeviceState(Device, DeviceStarted);
  1763. if (((Device->Flags & DEVICE_FLAG_MOUNTABLE) != 0) &&
  1764. ((Device->Flags & DEVICE_FLAG_MOUNTED) == 0)) {
  1765. IoCreateVolume(Device, NULL);
  1766. }
  1767. //
  1768. // If the device is a volume, perform volume arrival actions. As
  1769. // this operation does not happen on the device's work queue, there
  1770. // is nothing preventing device removal from releasing the original
  1771. // reference on the volume. Take another that volume arrival will
  1772. // release.
  1773. //
  1774. if (Device->Header.Type == ObjectVolume) {
  1775. ObAddReference(Device);
  1776. Status = KeCreateAndQueueWorkItem(IoDeviceWorkQueue,
  1777. WorkPriorityNormal,
  1778. IopVolumeArrival,
  1779. Device);
  1780. if (!KSUCCESS(Status)) {
  1781. ObReleaseReference(Device);
  1782. ObSignalObject(Device, SignalOptionSignalAll);
  1783. }
  1784. //
  1785. // Otherwise signal the device now that is has reached the start
  1786. // state.
  1787. //
  1788. } else {
  1789. ObSignalObject(Device, SignalOptionSignalAll);
  1790. }
  1791. Breakout = TRUE;
  1792. break;
  1793. //
  1794. // If the device is already started, then there's nothing to do.
  1795. //
  1796. case DeviceStarted:
  1797. Breakout = TRUE;
  1798. break;
  1799. //
  1800. // If the device is awaiting removal, do not proceed with the start
  1801. // sequence.
  1802. //
  1803. case DeviceAwaitingRemoval:
  1804. Breakout = TRUE;
  1805. break;
  1806. //
  1807. // The device should not be found in this state.
  1808. //
  1809. default:
  1810. ASSERT(FALSE);
  1811. IopSetDeviceProblem(Device,
  1812. DeviceProblemInvalidState,
  1813. STATUS_UNSUCCESSFUL);
  1814. Breakout = TRUE;
  1815. break;
  1816. }
  1817. }
  1818. return;
  1819. }
  1820. KSTATUS
  1821. IopAddDrivers (
  1822. PDEVICE Device
  1823. )
  1824. /*++
  1825. Routine Description:
  1826. This routine builds the driver stack for the device. If the device stack is
  1827. partially built, this routine will attempt to finish it.
  1828. Arguments:
  1829. Device - Supplies a pointer to the device to add drivers for.
  1830. Return Value:
  1831. Status code.
  1832. --*/
  1833. {
  1834. PDRIVER_ADD_DEVICE AddDevice;
  1835. PDRIVER FunctionDriver;
  1836. PSTR FunctionDriverName;
  1837. ULONG OriginalStackSize;
  1838. KSTATUS Status;
  1839. ASSERT(KeGetRunLevel() == RunLevelLow);
  1840. ASSERT(Device->State == DeviceInitialized);
  1841. FunctionDriver = NULL;
  1842. //
  1843. // Clear a previous driver load device problem before trying a second time.
  1844. //
  1845. if (Device->ProblemState.Problem == DeviceProblemFailedDriverLoad) {
  1846. IopClearDeviceProblem(Device);
  1847. }
  1848. //
  1849. // Find and load a functional driver.
  1850. //
  1851. OriginalStackSize = Device->DriverStackSize;
  1852. FunctionDriverName = IopFindDriverForDevice(Device);
  1853. if (FunctionDriverName != NULL) {
  1854. Status = IoLoadDriver(FunctionDriverName, &FunctionDriver);
  1855. if (!KSUCCESS(Status)) {
  1856. IopSetDeviceProblem(Device,
  1857. DeviceProblemFailedDriverLoad,
  1858. Status);
  1859. goto AddDriversEnd;
  1860. }
  1861. //
  1862. // Call the driver's AddDevice.
  1863. //
  1864. if ((FunctionDriver->Flags & DRIVER_FLAG_FAILED_DRIVER_ENTRY) == 0) {
  1865. if (FunctionDriver->FunctionTable.AddDevice != NULL) {
  1866. AddDevice = FunctionDriver->FunctionTable.AddDevice;
  1867. Status = AddDevice(FunctionDriver,
  1868. IoGetDeviceId(Device),
  1869. Device->ClassId,
  1870. Device->CompatibleIds,
  1871. Device);
  1872. if (!KSUCCESS(Status)) {
  1873. IopSetDeviceProblem(Device,
  1874. DeviceProblemFailedAddDevice,
  1875. Status);
  1876. goto AddDriversEnd;
  1877. }
  1878. } else {
  1879. Status = STATUS_DRIVER_FUNCTION_MISSING;
  1880. IopSetDeviceProblem(Device, DeviceProblemNoAddDevice, Status);
  1881. goto AddDriversEnd;
  1882. }
  1883. }
  1884. //
  1885. // Release the reference on the driver added from the load call.
  1886. //
  1887. IoDriverReleaseReference(FunctionDriver);
  1888. FunctionDriver = NULL;
  1889. }
  1890. //
  1891. // Make sure the stack has added some drivers.
  1892. //
  1893. if (Device->DriverStackSize == OriginalStackSize) {
  1894. Status = STATUS_NO_DRIVERS;
  1895. IopSetDeviceProblem(Device, DeviceProblemNoDrivers, Status);
  1896. goto AddDriversEnd;
  1897. }
  1898. Status = STATUS_SUCCESS;
  1899. AddDriversEnd:
  1900. if (FunctionDriver != NULL) {
  1901. IoDriverReleaseReference(FunctionDriver);
  1902. }
  1903. return Status;
  1904. }
  1905. PSTR
  1906. IopFindDriverForDevice (
  1907. PDEVICE Device
  1908. )
  1909. /*++
  1910. Routine Description:
  1911. This routine attempts to find a functional driver for the given device.
  1912. Arguments:
  1913. Device - Supplies a pointer to the device to match with a functional driver.
  1914. Return Value:
  1915. Returns a pointer to the loaded driver on success, or NULL if no driver
  1916. could be found.
  1917. --*/
  1918. {
  1919. PLIST_ENTRY CurrentEntry;
  1920. PDEVICE_DATABASE_ENTRY DatabaseEntry;
  1921. PSTR Driver;
  1922. BOOL Match;
  1923. Driver = NULL;
  1924. ASSERT(KeGetRunLevel() == RunLevelLow);
  1925. //
  1926. // Search through the database to match the device's ID to a driver.
  1927. //
  1928. KeAcquireQueuedLock(IoDeviceDatabaseLock);
  1929. CurrentEntry = IoDeviceDatabaseHead.Next;
  1930. while (CurrentEntry != &IoDeviceDatabaseHead) {
  1931. DatabaseEntry = LIST_VALUE(CurrentEntry,
  1932. DEVICE_DATABASE_ENTRY,
  1933. ListEntry);
  1934. CurrentEntry = CurrentEntry->Next;
  1935. Match = IoAreDeviceIdsEqual(IoGetDeviceId(Device),
  1936. DatabaseEntry->U.DeviceId);
  1937. if (Match != FALSE) {
  1938. Driver = DatabaseEntry->DriverName;
  1939. goto FindDriverForDeviceEnd;
  1940. }
  1941. }
  1942. //
  1943. // Attempt to find a match with the device class.
  1944. //
  1945. if (Device->ClassId != NULL) {
  1946. CurrentEntry = IoDeviceClassDatabaseHead.Next;
  1947. while (CurrentEntry != &IoDeviceClassDatabaseHead) {
  1948. DatabaseEntry = LIST_VALUE(CurrentEntry,
  1949. DEVICE_DATABASE_ENTRY,
  1950. ListEntry);
  1951. CurrentEntry = CurrentEntry->Next;
  1952. Match = RtlAreStringsEqual(DatabaseEntry->U.ClassId,
  1953. Device->ClassId,
  1954. MAX_DEVICE_ID);
  1955. if (Match != FALSE) {
  1956. Driver = DatabaseEntry->DriverName;
  1957. goto FindDriverForDeviceEnd;
  1958. }
  1959. }
  1960. }
  1961. FindDriverForDeviceEnd:
  1962. KeReleaseQueuedLock(IoDeviceDatabaseLock);
  1963. return Driver;
  1964. }
  1965. VOID
  1966. IopQueryChildren (
  1967. PDEVICE Device
  1968. )
  1969. /*++
  1970. Routine Description:
  1971. This routine queries the given device's children, processing any changes.
  1972. Arguments:
  1973. Device - Supplies a pointer to the device whose children are to be queried.
  1974. Return Value:
  1975. None.
  1976. --*/
  1977. {
  1978. IRP_QUERY_CHILDREN QueryChildren;
  1979. KSTATUS Status;
  1980. RtlZeroMemory(&QueryChildren, sizeof(QueryChildren));
  1981. Status = IopSendStateChangeIrp(Device,
  1982. IrpMinorQueryChildren,
  1983. &QueryChildren,
  1984. sizeof(QueryChildren));
  1985. if (!KSUCCESS(Status)) {
  1986. IopSetDeviceProblem(Device, DeviceProblemFailedQueryChildren, Status);
  1987. goto QueryChildrenEnd;
  1988. }
  1989. //
  1990. // Process the children, then free the child list and destroy the
  1991. // IRP.
  1992. //
  1993. IopProcessReportedChildren(Device, &QueryChildren);
  1994. if (QueryChildren.Children != NULL) {
  1995. MmFreePagedPool(QueryChildren.Children);
  1996. }
  1997. //
  1998. // On success, if the device was awaiting enumeration, move it to the
  1999. // started state and queue the start work item to finish any additional
  2000. // initialization.
  2001. //
  2002. if (Device->State == DeviceAwaitingEnumeration) {
  2003. IopSetDeviceState(Device, DeviceEnumerated);
  2004. Status = IopQueueDeviceWork(Device, DeviceActionStart, NULL, 0);
  2005. if (!KSUCCESS(Status)) {
  2006. IopSetDeviceProblem(Device,
  2007. DeviceProblemFailedToQueueStart,
  2008. Status);
  2009. }
  2010. }
  2011. QueryChildrenEnd:
  2012. return;
  2013. }
  2014. VOID
  2015. IopProcessReportedChildren (
  2016. PDEVICE Device,
  2017. PIRP_QUERY_CHILDREN Result
  2018. )
  2019. /*++
  2020. Routine Description:
  2021. This routine processes the list of children reported by a Query Children
  2022. IRP. It will queue removals for any devices that were no longer reported
  2023. and queue starts for any new devices.
  2024. Arguments:
  2025. Device - Supplies a pointer to the device that just completed the
  2026. enumeration.
  2027. Result - Supplies a pointer to the query children data.
  2028. Return Value:
  2029. None.
  2030. --*/
  2031. {
  2032. PDEVICE *ChildArray;
  2033. PDEVICE ChildDevice;
  2034. ULONG ChildIndex;
  2035. PLIST_ENTRY CurrentEntry;
  2036. ULONG Flags;
  2037. KSTATUS Status;
  2038. //
  2039. // Looping over a device's active children requires the device lock in
  2040. // shared mode. Without locks, if a child were added during this routine
  2041. // but it is not in the query IRP's list, it would immediately get marked
  2042. // for removal. Without locks, if a child were deleted during this routine
  2043. // then corruption could occur while looping over the children. This
  2044. // requires a device to be removed from its parent's active child list
  2045. // while the parent's lock is held exclusively.
  2046. //
  2047. KeAcquireSharedExclusiveLockShared(Device->Lock);
  2048. //
  2049. // Loop through all active children of this device and clear their
  2050. // enumerated flag.
  2051. //
  2052. CurrentEntry = Device->ActiveChildListHead.Next;
  2053. while (CurrentEntry != &(Device->ActiveChildListHead)) {
  2054. ChildDevice = LIST_VALUE(CurrentEntry, DEVICE, ActiveListEntry);
  2055. ChildDevice->Flags &= ~DEVICE_FLAG_ENUMERATED;
  2056. CurrentEntry = CurrentEntry->Next;
  2057. }
  2058. //
  2059. // Loop through the array of children the device returned looking for
  2060. // brand new children.
  2061. //
  2062. ChildArray = Result->Children;
  2063. for (ChildIndex = 0; ChildIndex < Result->ChildCount; ChildIndex += 1) {
  2064. if ((ChildArray != NULL) && (ChildArray[ChildIndex] != NULL)) {
  2065. //
  2066. // Mark the child as enumerated so it does not get torn down later
  2067. // during this routine. If the device appears to be previously
  2068. // unreported, set the state to Initialized and queue work to
  2069. // start the device.
  2070. //
  2071. ChildArray[ChildIndex]->Flags |= DEVICE_FLAG_ENUMERATED;
  2072. if (ChildArray[ChildIndex]->State == DeviceUnreported) {
  2073. IopSetDeviceState(ChildArray[ChildIndex], DeviceInitialized);
  2074. Status = IopQueueDeviceWork(ChildArray[ChildIndex],
  2075. DeviceActionStart,
  2076. NULL,
  2077. DEVICE_ACTION_OPEN_QUEUE);
  2078. if (!KSUCCESS(Status)) {
  2079. IopSetDeviceProblem(ChildArray[ChildIndex],
  2080. DeviceProblemFailedToQueueStart,
  2081. Status);
  2082. }
  2083. }
  2084. }
  2085. }
  2086. //
  2087. // Loop through the active children again. If a device does not have the
  2088. // enumerated flag, the bus didn't report it this time. Queue removals for
  2089. // these devices.
  2090. //
  2091. CurrentEntry = Device->ActiveChildListHead.Next;
  2092. while (CurrentEntry != &(Device->ActiveChildListHead)) {
  2093. ChildDevice = LIST_VALUE(CurrentEntry, DEVICE, ActiveListEntry);
  2094. CurrentEntry = CurrentEntry->Next;
  2095. if ((ChildDevice->Flags & DEVICE_FLAG_ENUMERATED) == 0) {
  2096. Flags = DEVICE_ACTION_SEND_TO_SUBTREE | DEVICE_ACTION_OPEN_QUEUE;
  2097. Status = IopQueueDeviceWork(ChildDevice,
  2098. DeviceActionPrepareRemove,
  2099. NULL,
  2100. Flags);
  2101. //
  2102. // If the action failed to queue for a reason other than that the
  2103. // device was already awaiting removal, set the problem state. Do
  2104. // not call the queue failure handler as that can roll back the
  2105. // parent's device state, but in this case the parent isn't
  2106. // expecting an answer from the child's removal process.
  2107. //
  2108. if (!KSUCCESS(Status) &&
  2109. (Status != STATUS_DEVICE_QUEUE_CLOSING)) {
  2110. IopSetDeviceProblem(ChildDevice,
  2111. DeviceProblemFailedToQueuePrepareRemove,
  2112. Status);
  2113. break;
  2114. }
  2115. }
  2116. }
  2117. KeReleaseSharedExclusiveLockShared(Device->Lock);
  2118. return;
  2119. }
  2120. PSTR
  2121. IopGetUniqueDeviceId (
  2122. PDEVICE ParentDevice,
  2123. PSTR DeviceId
  2124. )
  2125. /*++
  2126. Routine Description:
  2127. This routine converts the given device ID into a device ID that is unique
  2128. amongst the children of the given parent device.
  2129. Arguments:
  2130. ParentDevice - Supplies a pointer to the parent of the device whose ID is
  2131. supplied.
  2132. DeviceId - Supplies the device ID that needs to be made unique.
  2133. Return Value:
  2134. Returns a unique device ID string.
  2135. --*/
  2136. {
  2137. ULONG BytesCopied;
  2138. ULONG DeviceIdLength;
  2139. ULONG DeviceIndex;
  2140. POBJECT_HEADER ExistingDevice;
  2141. PSTR FormatString;
  2142. ULONG FormatStringLength;
  2143. PSTR NewDeviceId;
  2144. ULONG NewDeviceIdLength;
  2145. //
  2146. // If there is no parent device or the parent device is the volume
  2147. // directory, then just return the device ID.
  2148. //
  2149. if ((ParentDevice == NULL) ||
  2150. (ParentDevice == (PDEVICE)IoVolumeDirectory)) {
  2151. return DeviceId;
  2152. }
  2153. //
  2154. // If this is the first time this device ID has been used, then just use
  2155. // the given device ID.
  2156. //
  2157. DeviceIdLength = RtlStringLength(DeviceId) + 1;
  2158. ExistingDevice = ObFindObject(DeviceId,
  2159. DeviceIdLength,
  2160. (POBJECT_HEADER)ParentDevice);
  2161. if (ExistingDevice == NULL) {
  2162. return DeviceId;
  2163. }
  2164. ObReleaseReference(ExistingDevice);
  2165. ExistingDevice = NULL;
  2166. //
  2167. // Otherwise, append a unique value to the device ID. Start by creating a
  2168. // format string. The format string is the original device ID appended with
  2169. // "#%d", unless the current device ID already ends with a '#' character.
  2170. //
  2171. if (DeviceId[DeviceIdLength - 2] == DEVICE_ID_SUFFIX_START_CHARACTER) {
  2172. FormatStringLength = DeviceIdLength +
  2173. DEVICE_ID_SUFFIX_ALTERNATE_FORMAT_LENGTH -
  2174. 1;
  2175. } else {
  2176. FormatStringLength = DeviceIdLength +
  2177. DEVICE_ID_SUFFIX_FORMAT_LENGTH -
  2178. 1;
  2179. }
  2180. NewDeviceId = NULL;
  2181. FormatString = MmAllocatePagedPool(FormatStringLength,
  2182. DEVICE_ALLOCATION_TAG);
  2183. if (FormatString == NULL) {
  2184. goto GetUniqueDeviceIdEnd;
  2185. }
  2186. BytesCopied = RtlStringCopy(FormatString, DeviceId, FormatStringLength);
  2187. ASSERT(BytesCopied == DeviceIdLength);
  2188. //
  2189. // Do not copy a second '#' character to start the suffix if the device ID
  2190. // already ends in one.
  2191. //
  2192. if (DeviceId[DeviceIdLength - 2] == DEVICE_ID_SUFFIX_START_CHARACTER) {
  2193. BytesCopied = RtlStringCopy(FormatString + (DeviceIdLength - 1),
  2194. DEVICE_ID_SUFFIX_ALTERNATE_FORMAT,
  2195. DEVICE_ID_SUFFIX_ALTERNATE_FORMAT_LENGTH);
  2196. ASSERT(BytesCopied == DEVICE_ID_SUFFIX_ALTERNATE_FORMAT_LENGTH);
  2197. } else {
  2198. BytesCopied = RtlStringCopy(FormatString + (DeviceIdLength - 1),
  2199. DEVICE_ID_SUFFIX_FORMAT,
  2200. DEVICE_ID_SUFFIX_FORMAT_LENGTH);
  2201. ASSERT(BytesCopied == DEVICE_ID_SUFFIX_FORMAT_LENGTH);
  2202. }
  2203. //
  2204. // Allocate a buffer to use for creating the new device ID string.
  2205. //
  2206. DeviceIdLength += DEVICE_ID_SUFFIX_LENGTH_MAX;
  2207. NewDeviceId = MmAllocatePagedPool(DeviceIdLength, DEVICE_ALLOCATION_TAG);
  2208. if (NewDeviceId == NULL) {
  2209. goto GetUniqueDeviceIdEnd;
  2210. }
  2211. //
  2212. // Create the possible device IDs and compare them to existing device IDs
  2213. // amongst the parent device's children. Use the first available.
  2214. //
  2215. for (DeviceIndex = 1;
  2216. DeviceIndex < MAX_CONFLICTING_DEVICES;
  2217. DeviceIndex += 1) {
  2218. NewDeviceIdLength = RtlPrintToString(NewDeviceId,
  2219. DeviceIdLength,
  2220. CharacterEncodingDefault,
  2221. FormatString,
  2222. DeviceIndex);
  2223. if (NewDeviceIdLength > DeviceIdLength) {
  2224. NewDeviceIdLength = DeviceIdLength;
  2225. }
  2226. ExistingDevice = ObFindObject(NewDeviceId,
  2227. NewDeviceIdLength,
  2228. (POBJECT_HEADER)ParentDevice);
  2229. if (ExistingDevice == NULL) {
  2230. goto GetUniqueDeviceIdEnd;
  2231. }
  2232. ObReleaseReference(ExistingDevice);
  2233. ExistingDevice = NULL;
  2234. }
  2235. //
  2236. // This device has too many children with the same device ID. Give up.
  2237. //
  2238. MmFreePagedPool(NewDeviceId);
  2239. NewDeviceId = NULL;
  2240. GetUniqueDeviceIdEnd:
  2241. return NewDeviceId;
  2242. }