part.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. part.c
  9. Abstract:
  10. This module implements the partition manager driver.
  11. Author:
  12. Evan Green 30-Jan-2014
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include <minoca/lib/partlib.h>
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. #define PARTITION_ALLOCATION_TAG 0x74726150 // 'traP'
  25. #define PARTITION_STRING_SIZE sizeof("PartitionXXXXX")
  26. #define PARTITION_STRING_FORMAT "Partition%d"
  27. #define PARTITION_RAW_DISK_ID "RawDisk"
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. typedef enum _PARTITION_OBJECT_TYPE {
  32. PartitionObjectInvalid,
  33. PartitionObjectParent,
  34. PartitionObjectChild
  35. } PARTITION_OBJECT_TYPE, *PPARTITION_OBJECT_TYPE;
  36. /*++
  37. Structure Description:
  38. This structure stores the common header for a partition manager object.
  39. Members:
  40. Type - Stores the partition object type.
  41. ReferenceCount - Stores the reference count on the object.
  42. --*/
  43. typedef struct _PARTITION_OBJECT {
  44. PARTITION_OBJECT_TYPE Type;
  45. ULONG ReferenceCount;
  46. } PARTITION_OBJECT, *PPARTITION_OBJECT;
  47. /*++
  48. Structure Description:
  49. This structure stores information about a partition parent context.
  50. Members:
  51. Header - Store the common partition object header.
  52. Device - Stores the OS device this device belongs to.
  53. IoHandle - Stores an open I/O handle to the disk, active when the partition
  54. manager is reading the device.
  55. PartitionContext - Stores the partition context for this disk.
  56. Children - Stores an array of pointers to devices representing the device
  57. partitions. The raw disk is not included here.
  58. RawDisk - Stores a pointer to the raw disk device.
  59. --*/
  60. typedef struct _PARTITION_PARENT {
  61. PARTITION_OBJECT Header;
  62. PDEVICE Device;
  63. PIO_HANDLE IoHandle;
  64. PARTITION_CONTEXT PartitionContext;
  65. PDEVICE *Children;
  66. PDEVICE RawDisk;
  67. } PARTITION_PARENT, *PPARTITION_PARENT;
  68. /*++
  69. Structure Description:
  70. This structure stores information about a particular partition.
  71. Members:
  72. Header - Stores the common partition object header.
  73. Parent - Stores a pointer to the parent structure.
  74. Index - Stores the index into the partition information for this partition.
  75. --*/
  76. typedef struct _PARTITION_CHILD {
  77. PARTITION_OBJECT Header;
  78. PPARTITION_PARENT Parent;
  79. ULONG Index;
  80. } PARTITION_CHILD, *PPARTITION_CHILD;
  81. //
  82. // ----------------------------------------------- Internal Function Prototypes
  83. //
  84. KSTATUS
  85. PartAddDevice (
  86. PVOID Driver,
  87. PCSTR DeviceId,
  88. PCSTR ClassId,
  89. PCSTR CompatibleIds,
  90. PVOID DeviceToken
  91. );
  92. VOID
  93. PartDispatchStateChange (
  94. PIRP Irp,
  95. PVOID DeviceContext,
  96. PVOID IrpContext
  97. );
  98. VOID
  99. PartDispatchOpen (
  100. PIRP Irp,
  101. PVOID DeviceContext,
  102. PVOID IrpContext
  103. );
  104. VOID
  105. PartDispatchClose (
  106. PIRP Irp,
  107. PVOID DeviceContext,
  108. PVOID IrpContext
  109. );
  110. VOID
  111. PartDispatchIo (
  112. PIRP Irp,
  113. PVOID DeviceContext,
  114. PVOID IrpContext
  115. );
  116. VOID
  117. PartDispatchSystemControl (
  118. PIRP Irp,
  119. PVOID DeviceContext,
  120. PVOID IrpContext
  121. );
  122. KSTATUS
  123. PartpEnumerateChildren (
  124. PIRP Irp,
  125. PPARTITION_PARENT Parent
  126. );
  127. KSTATUS
  128. PartpReadPartitionStructures (
  129. PPARTITION_PARENT Parent
  130. );
  131. VOID
  132. PartpHandleDeviceInformationRequest (
  133. PIRP Irp,
  134. PPARTITION_CHILD Child
  135. );
  136. VOID
  137. PartpHandleBlockInformationRequest (
  138. PIRP Irp,
  139. PPARTITION_CHILD Child
  140. );
  141. PVOID
  142. PartpAllocate (
  143. UINTN Size
  144. );
  145. VOID
  146. PartpFree (
  147. PVOID Memory
  148. );
  149. KSTATUS
  150. PartpRead (
  151. PPARTITION_CONTEXT Context,
  152. ULONGLONG BlockAddress,
  153. PVOID Buffer
  154. );
  155. PPARTITION_CHILD
  156. PartpCreateChild (
  157. PPARTITION_PARENT Parent,
  158. ULONG Index
  159. );
  160. VOID
  161. PartpAddReference (
  162. PPARTITION_OBJECT Object
  163. );
  164. VOID
  165. PartpReleaseReference (
  166. PPARTITION_OBJECT Object
  167. );
  168. VOID
  169. PartpDestroyDevice (
  170. PPARTITION_OBJECT Object
  171. );
  172. //
  173. // -------------------------------------------------------------------- Globals
  174. //
  175. PDRIVER PartDriver;
  176. UUID PartPartitionDeviceInformationUuid = PARTITION_DEVICE_INFORMATION_UUID;
  177. //
  178. // ------------------------------------------------------------------ Functions
  179. //
  180. __USED
  181. KSTATUS
  182. DriverEntry (
  183. PDRIVER Driver
  184. )
  185. /*++
  186. Routine Description:
  187. This routine implements the initial entry point of the partition
  188. library, called when the library is first loaded.
  189. Arguments:
  190. Driver - Supplies a pointer to the driver object.
  191. Return Value:
  192. Status code.
  193. --*/
  194. {
  195. DRIVER_FUNCTION_TABLE FunctionTable;
  196. KSTATUS Status;
  197. PartDriver = Driver;
  198. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  199. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  200. FunctionTable.AddDevice = PartAddDevice;
  201. FunctionTable.DispatchStateChange = PartDispatchStateChange;
  202. FunctionTable.DispatchOpen = PartDispatchOpen;
  203. FunctionTable.DispatchClose = PartDispatchClose;
  204. FunctionTable.DispatchIo = PartDispatchIo;
  205. FunctionTable.DispatchSystemControl = PartDispatchSystemControl;
  206. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  207. return Status;
  208. }
  209. KSTATUS
  210. PartAddDevice (
  211. PVOID Driver,
  212. PCSTR DeviceId,
  213. PCSTR ClassId,
  214. PCSTR CompatibleIds,
  215. PVOID DeviceToken
  216. )
  217. /*++
  218. Routine Description:
  219. This routine is called when a disk is detected. The partition manager
  220. attaches to the disk.
  221. Arguments:
  222. Driver - Supplies a pointer to the driver being called.
  223. DeviceId - Supplies a pointer to a string with the device ID.
  224. ClassId - Supplies a pointer to a string containing the device's class ID.
  225. CompatibleIds - Supplies a pointer to a string containing device IDs
  226. that would be compatible with this device.
  227. DeviceToken - Supplies an opaque token that the driver can use to identify
  228. the device in the system. This token should be used when attaching to
  229. the stack.
  230. Return Value:
  231. STATUS_SUCCESS on success.
  232. Failure code if the driver was unsuccessful in attaching itself.
  233. --*/
  234. {
  235. PPARTITION_PARENT Context;
  236. KSTATUS Status;
  237. Context = PartpAllocate(sizeof(PARTITION_PARENT));
  238. if (Context == NULL) {
  239. Status = STATUS_INSUFFICIENT_RESOURCES;
  240. goto AddDeviceEnd;
  241. }
  242. RtlZeroMemory(Context, sizeof(PARTITION_PARENT));
  243. Context->Header.Type = PartitionObjectParent;
  244. Context->Header.ReferenceCount = 1;
  245. Context->Device = DeviceToken;
  246. Status = IoAttachDriverToDevice(Driver, DeviceToken, Context);
  247. AddDeviceEnd:
  248. if (!KSUCCESS(Status)) {
  249. if (Context != NULL) {
  250. PartpFree(Context);
  251. Context = NULL;
  252. }
  253. }
  254. return Status;
  255. }
  256. VOID
  257. PartDispatchStateChange (
  258. PIRP Irp,
  259. PVOID DeviceContext,
  260. PVOID IrpContext
  261. )
  262. /*++
  263. Routine Description:
  264. This routine handles State Change IRPs.
  265. Arguments:
  266. Irp - Supplies a pointer to the I/O request packet.
  267. DeviceContext - Supplies the context pointer supplied by the driver when it
  268. attached itself to the driver stack. Presumably this pointer contains
  269. driver-specific device context.
  270. IrpContext - Supplies the context pointer supplied by the driver when
  271. the IRP was created.
  272. Return Value:
  273. None.
  274. --*/
  275. {
  276. PPARTITION_CHILD Child;
  277. PPARTITION_OBJECT Object;
  278. PPARTITION_PARENT Parent;
  279. KSTATUS Status;
  280. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  281. Object = (PPARTITION_OBJECT)DeviceContext;
  282. switch (Object->Type) {
  283. //
  284. // If this is the functional driver for the disk itself, usurp the query
  285. // children IRP but don't alter any other IRP paths.
  286. //
  287. case PartitionObjectParent:
  288. Parent = PARENT_STRUCTURE(Object, PARTITION_PARENT, Header);
  289. switch (Irp->MinorCode) {
  290. case IrpMinorQueryChildren:
  291. Status = PartpEnumerateChildren(Irp, Parent);
  292. IoCompleteIrp(PartDriver, Irp, Status);
  293. break;
  294. case IrpMinorRemoveDevice:
  295. if (Irp->Direction == IrpUp) {
  296. PartpReleaseReference(Object);
  297. }
  298. break;
  299. //
  300. // For all other IRPs, do nothing.
  301. //
  302. default:
  303. break;
  304. }
  305. break;
  306. //
  307. // If this is a child, then this driver is being called as the bus driver.
  308. // Complete state change IRPs so they don't make it down to the disk.
  309. //
  310. case PartitionObjectChild:
  311. Child = PARENT_STRUCTURE(Object, PARTITION_CHILD, Header);
  312. switch (Irp->MinorCode) {
  313. case IrpMinorQueryResources:
  314. IoCompleteIrp(PartDriver, Irp, STATUS_SUCCESS);
  315. break;
  316. case IrpMinorStartDevice:
  317. //
  318. // Publish the partition information device type.
  319. //
  320. Status = IoRegisterDeviceInformation(
  321. Irp->Device,
  322. &PartPartitionDeviceInformationUuid,
  323. TRUE);
  324. IoCompleteIrp(PartDriver, Irp, Status);
  325. break;
  326. case IrpMinorQueryChildren:
  327. Status = STATUS_SUCCESS;
  328. //
  329. // If this is the raw disk coming up, then read off the partition
  330. // information.
  331. //
  332. if (Child->Index == -1) {
  333. Status = PartpReadPartitionStructures(Child->Parent);
  334. }
  335. IoCompleteIrp(PartDriver, Irp, Status);
  336. break;
  337. case IrpMinorRemoveDevice:
  338. IoRegisterDeviceInformation(Irp->Device,
  339. &PartPartitionDeviceInformationUuid,
  340. FALSE);
  341. PartpReleaseReference(Object);
  342. IoCompleteIrp(PartDriver, Irp, STATUS_SUCCESS);
  343. break;
  344. //
  345. // For all other IRPs, do nothing.
  346. //
  347. default:
  348. break;
  349. }
  350. break;
  351. default:
  352. ASSERT(FALSE);
  353. break;
  354. }
  355. return;
  356. }
  357. VOID
  358. PartDispatchOpen (
  359. PIRP Irp,
  360. PVOID DeviceContext,
  361. PVOID IrpContext
  362. )
  363. /*++
  364. Routine Description:
  365. This routine handles Open IRPs.
  366. Arguments:
  367. Irp - Supplies a pointer to the I/O request packet.
  368. DeviceContext - Supplies the context pointer supplied by the driver when it
  369. attached itself to the driver stack. Presumably this pointer contains
  370. driver-specific device context.
  371. IrpContext - Supplies the context pointer supplied by the driver when
  372. the IRP was created.
  373. Return Value:
  374. None.
  375. --*/
  376. {
  377. //
  378. // Let the IRP head down and be handled by the disk directly.
  379. //
  380. return;
  381. }
  382. VOID
  383. PartDispatchClose (
  384. PIRP Irp,
  385. PVOID DeviceContext,
  386. PVOID IrpContext
  387. )
  388. /*++
  389. Routine Description:
  390. This routine handles Close IRPs.
  391. Arguments:
  392. Irp - Supplies a pointer to the I/O request packet.
  393. DeviceContext - Supplies the context pointer supplied by the driver when it
  394. attached itself to the driver stack. Presumably this pointer contains
  395. driver-specific device context.
  396. IrpContext - Supplies the context pointer supplied by the driver when
  397. the IRP was created.
  398. Return Value:
  399. None.
  400. --*/
  401. {
  402. //
  403. // Let the IRP be handled by the disk.
  404. //
  405. return;
  406. }
  407. VOID
  408. PartDispatchIo (
  409. PIRP Irp,
  410. PVOID DeviceContext,
  411. PVOID IrpContext
  412. )
  413. /*++
  414. Routine Description:
  415. This routine handles I/O IRPs.
  416. Arguments:
  417. Irp - Supplies a pointer to the I/O request packet.
  418. DeviceContext - Supplies the context pointer supplied by the driver when it
  419. attached itself to the driver stack. Presumably this pointer contains
  420. driver-specific device context.
  421. IrpContext - Supplies the context pointer supplied by the driver when
  422. the IRP was created.
  423. Return Value:
  424. None.
  425. --*/
  426. {
  427. ULONGLONG BlockAddress;
  428. ULONGLONG BlockCount;
  429. ULONG BlockShift;
  430. ULONG BlockSize;
  431. PPARTITION_CHILD Child;
  432. PPARTITION_OBJECT Object;
  433. ULONGLONG OriginalBlockCount;
  434. PPARTITION_INFORMATION Partition;
  435. PIRP_READ_WRITE ReadWrite;
  436. KSTATUS Status;
  437. Object = (PPARTITION_OBJECT)DeviceContext;
  438. //
  439. // Don't process I/O as the parent (bus driver), let that head down to the
  440. // disk.
  441. //
  442. if (Object->Type != PartitionObjectChild) {
  443. return;
  444. }
  445. ASSERT(Irp->MajorCode == IrpMajorIo);
  446. Child = PARENT_STRUCTURE(Object, PARTITION_CHILD, Header);
  447. //
  448. // If this is the raw disk partition, let the IRP continue down to the disk
  449. // unmolested.
  450. //
  451. if (Child->Index == -1) {
  452. return;
  453. }
  454. BlockShift = Child->Parent->PartitionContext.BlockShift;
  455. BlockSize = Child->Parent->PartitionContext.BlockSize;
  456. ASSERT(BlockSize != 0);
  457. ReadWrite = &(Irp->U.ReadWrite);
  458. Partition = &(Child->Parent->PartitionContext.Partitions[Child->Index]);
  459. if (Irp->Direction == IrpDown) {
  460. //
  461. // On the way down, convert the offset into a block address, translate
  462. // the partition-relative block address into a disk block address, and
  463. // then convert back into bytes.
  464. //
  465. ASSERT((IS_ALIGNED(ReadWrite->IoOffset, BlockSize)) &&
  466. (IS_ALIGNED(ReadWrite->IoSizeInBytes, BlockSize)));
  467. BlockAddress = ReadWrite->IoOffset >> BlockShift;
  468. BlockCount = ReadWrite->IoSizeInBytes >> BlockShift;
  469. OriginalBlockCount = BlockCount;
  470. Status = PartTranslateIo(Partition, &BlockAddress, &BlockCount);
  471. if (!KSUCCESS(Status)) {
  472. goto DispatchIoEnd;
  473. }
  474. ReadWrite->IoOffset = BlockAddress << BlockShift;
  475. ReadWrite->NewIoOffset += Partition->StartOffset << BlockShift;
  476. if (BlockCount != OriginalBlockCount) {
  477. ReadWrite->IoSizeInBytes = BlockCount << BlockShift;
  478. }
  479. //
  480. // On the way back up, re-adjust the I/O offset and new I/O offset.
  481. //
  482. } else {
  483. ASSERT(Irp->Direction == IrpUp);
  484. ASSERT(ReadWrite->IoOffset >= (Partition->StartOffset << BlockShift));
  485. ReadWrite->IoOffset -= Partition->StartOffset << BlockShift;
  486. ASSERT(ReadWrite->NewIoOffset >= Partition->StartOffset << BlockShift);
  487. ReadWrite->NewIoOffset -= Partition->StartOffset << BlockShift;
  488. }
  489. Status = STATUS_SUCCESS;
  490. DispatchIoEnd:
  491. //
  492. // If something bad happened, don't let this get down to the disk.
  493. // Otherwise, let it flow to the disk.
  494. //
  495. if (!KSUCCESS(Status)) {
  496. IoCompleteIrp(PartDriver, Irp, Status);
  497. }
  498. return;
  499. }
  500. VOID
  501. PartDispatchSystemControl (
  502. PIRP Irp,
  503. PVOID DeviceContext,
  504. PVOID IrpContext
  505. )
  506. /*++
  507. Routine Description:
  508. This routine handles System Control IRPs.
  509. Arguments:
  510. Irp - Supplies a pointer to the I/O request packet.
  511. DeviceContext - Supplies the context pointer supplied by the driver when it
  512. attached itself to the driver stack. Presumably this pointer contains
  513. driver-specific device context.
  514. IrpContext - Supplies the context pointer supplied by the driver when
  515. the IRP was created.
  516. Return Value:
  517. None.
  518. --*/
  519. {
  520. ULONGLONG BlockCount;
  521. ULONG BlockSize;
  522. PPARTITION_CHILD Child;
  523. PVOID Context;
  524. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  525. ULONGLONG FileSize;
  526. PSYSTEM_CONTROL_LOOKUP Lookup;
  527. PPARTITION_OBJECT Object;
  528. PPARTITION_PARENT Parent;
  529. PPARTITION_INFORMATION Partition;
  530. PPARTITION_CONTEXT PartitionContext;
  531. PFILE_PROPERTIES Properties;
  532. ULONGLONG PropertiesFileSize;
  533. KSTATUS Status;
  534. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  535. Object = (PPARTITION_OBJECT)DeviceContext;
  536. Context = Irp->U.SystemControl.SystemContext;
  537. if (Irp->Direction != IrpDown) {
  538. return;
  539. }
  540. if (Object->Type == PartitionObjectParent) {
  541. Parent = PARENT_STRUCTURE(Object, PARTITION_PARENT, Header);
  542. switch (Irp->MinorCode) {
  543. //
  544. // If the IRP is destined for the disk, then explicitly complete it as
  545. // "not supported" so the object manager will enumerate children. If
  546. // this is IRP was actually sent to the raw disk child, then let it
  547. // flow down to the disk.
  548. //
  549. case IrpMinorSystemControlLookup:
  550. if (Irp->Device != Parent->RawDisk) {
  551. IoCompleteIrp(PartDriver, Irp, STATUS_NOT_HANDLED);
  552. }
  553. break;
  554. default:
  555. break;
  556. }
  557. } else {
  558. ASSERT(Object->Type == PartitionObjectChild);
  559. Child = PARENT_STRUCTURE(Object, PARTITION_CHILD, Header);
  560. PartitionContext = &(Child->Parent->PartitionContext);
  561. BlockSize = PartitionContext->BlockSize;
  562. Partition = NULL;
  563. BlockCount = 0;
  564. if (Child->Index != -1) {
  565. Partition = &(PartitionContext->Partitions[Child->Index]);
  566. BlockCount = Partition->EndOffset - Partition->StartOffset;
  567. }
  568. FileSize = BlockCount << PartitionContext->BlockShift;
  569. switch (Irp->MinorCode) {
  570. case IrpMinorSystemControlLookup:
  571. //
  572. // Let the IRP pass down to the disk if this is the raw disk child.
  573. //
  574. if (Child->Index == -1) {
  575. break;
  576. }
  577. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  578. Status = STATUS_PATH_NOT_FOUND;
  579. if (Lookup->Root != FALSE) {
  580. //
  581. // Enable opening of the root as a single file.
  582. //
  583. Properties = Lookup->Properties;
  584. Properties->FileId = 0;
  585. Properties->Type = IoObjectBlockDevice;
  586. Properties->HardLinkCount = 1;
  587. Properties->BlockSize = BlockSize;
  588. Properties->BlockCount = BlockCount;
  589. Properties->Size = FileSize;
  590. Status = STATUS_SUCCESS;
  591. }
  592. IoCompleteIrp(PartDriver, Irp, Status);
  593. break;
  594. //
  595. // Writes to the disk's properties are not allowed. Fail if the data
  596. // has changed.
  597. //
  598. case IrpMinorSystemControlWriteFileProperties:
  599. if (Child->Index == -1) {
  600. break;
  601. }
  602. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  603. Properties = FileOperation->FileProperties;
  604. PropertiesFileSize = Properties->Size;
  605. if ((Properties->FileId != 0) ||
  606. (Properties->Type != IoObjectBlockDevice) ||
  607. (Properties->HardLinkCount != 1) ||
  608. (Properties->BlockSize != BlockSize) ||
  609. (Properties->BlockCount != BlockCount) ||
  610. (PropertiesFileSize != FileSize)) {
  611. Status = STATUS_NOT_SUPPORTED;
  612. } else {
  613. Status = STATUS_SUCCESS;
  614. }
  615. IoCompleteIrp(PartDriver, Irp, Status);
  616. break;
  617. //
  618. // Handle get/set device information requests.
  619. //
  620. case IrpMinorSystemControlDeviceInformation:
  621. PartpHandleDeviceInformationRequest(Irp, Child);
  622. break;
  623. case IrpMinorSystemControlGetBlockInformation:
  624. PartpHandleBlockInformationRequest(Irp, Child);
  625. break;
  626. //
  627. // Let synchronize requests go down to the disk.
  628. //
  629. case IrpMinorSystemControlSynchronize:
  630. break;
  631. //
  632. // Other operations are not supported.
  633. //
  634. default:
  635. IoCompleteIrp(PartDriver, Irp, STATUS_NOT_SUPPORTED);
  636. break;
  637. }
  638. }
  639. return;
  640. }
  641. //
  642. // --------------------------------------------------------- Internal Functions
  643. //
  644. KSTATUS
  645. PartpEnumerateChildren (
  646. PIRP Irp,
  647. PPARTITION_PARENT Parent
  648. )
  649. /*++
  650. Routine Description:
  651. This routine is called to respond to enumeration requests of the parent.
  652. On the very first iteration, it enumerates only the raw disk. When the
  653. raw disk comes up, it reads the partition information and re-enumerates
  654. the parent. This routine is then called again an enumreates both the raw
  655. disk and all the partitions.
  656. Arguments:
  657. Irp - Supplies a pointer to the query children IRP.
  658. Parent - Supplies a pointer to the partition parent.
  659. Return Value:
  660. Status code.
  661. --*/
  662. {
  663. ULONG AllocationSize;
  664. PPARTITION_CHILD Child;
  665. CHAR DeviceId[PARTITION_STRING_SIZE];
  666. PPARTITION_INFORMATION Information;
  667. PPARTITION_CONTEXT PartitionContext;
  668. ULONG PartitionIndex;
  669. PARTITION_TYPE PartitionType;
  670. KSTATUS Status;
  671. Child = NULL;
  672. ASSERT(Irp->MinorCode == IrpMinorQueryChildren);
  673. //
  674. // If the raw disk has yet to be created, do that now.
  675. //
  676. if (Parent->RawDisk == NULL) {
  677. Child = PartpCreateChild(Parent, -1);
  678. if (Child == NULL) {
  679. Status = STATUS_INSUFFICIENT_RESOURCES;
  680. goto EnumerateChildrenEnd;
  681. }
  682. Status = IoCreateDevice(PartDriver,
  683. Child,
  684. Parent->Device,
  685. PARTITION_RAW_DISK_ID,
  686. PARTITION_CLASS_ID,
  687. NULL,
  688. &(Parent->RawDisk));
  689. if (!KSUCCESS(Status)) {
  690. goto EnumerateChildrenEnd;
  691. }
  692. Child = NULL;
  693. Status = IoSetTargetDevice(Parent->RawDisk, Parent->Device);
  694. if (!KSUCCESS(Status)) {
  695. goto EnumerateChildrenEnd;
  696. }
  697. }
  698. PartitionContext = &(Parent->PartitionContext);
  699. //
  700. // Allocate the array of children if needed.
  701. //
  702. if ((Parent->Children == NULL) && (PartitionContext->BlockSize != 0) &&
  703. (PartitionContext->PartitionCount != 0)) {
  704. AllocationSize = sizeof(PDEVICE) * PartitionContext->PartitionCount;
  705. Parent->Children = MmAllocatePagedPool(AllocationSize,
  706. PARTITION_ALLOCATION_TAG);
  707. if (Parent->Children == NULL) {
  708. Status = STATUS_INSUFFICIENT_RESOURCES;
  709. goto EnumerateChildrenEnd;
  710. }
  711. RtlZeroMemory(Parent->Children, AllocationSize);
  712. }
  713. //
  714. // Create a child device for every partition if needed.
  715. //
  716. for (PartitionIndex = 0;
  717. PartitionIndex < PartitionContext->PartitionCount;
  718. PartitionIndex += 1) {
  719. Information = &(PartitionContext->Partitions[PartitionIndex]);
  720. //
  721. // Skip empty and extended partitions.
  722. //
  723. PartitionType = Information->PartitionType;
  724. if ((PartitionType == PartitionTypeInvalid) ||
  725. (PartitionType == PartitionTypeEmpty) ||
  726. (PartitionType == PartitionTypeDosExtended) ||
  727. (PartitionType == PartitionTypeDosExtendedLba)) {
  728. continue;
  729. }
  730. if (Parent->Children[PartitionIndex] != NULL) {
  731. continue;
  732. }
  733. Child = PartpCreateChild(Parent, PartitionIndex);
  734. if (Child == NULL) {
  735. Status = STATUS_INSUFFICIENT_RESOURCES;
  736. goto EnumerateChildrenEnd;
  737. }
  738. RtlPrintToString(DeviceId,
  739. sizeof(DeviceId),
  740. CharacterEncodingDefault,
  741. PARTITION_STRING_FORMAT,
  742. Information->Number);
  743. Status = IoCreateDevice(PartDriver,
  744. Child,
  745. Parent->Device,
  746. DeviceId,
  747. PARTITION_CLASS_ID,
  748. NULL,
  749. &(Parent->Children[PartitionIndex]));
  750. if (!KSUCCESS(Status)) {
  751. goto EnumerateChildrenEnd;
  752. }
  753. IoSetDeviceMountable(Parent->Children[PartitionIndex]);
  754. Child = NULL;
  755. Status = IoSetTargetDevice(Parent->Children[PartitionIndex],
  756. Parent->Device);
  757. if (!KSUCCESS(Status)) {
  758. goto EnumerateChildrenEnd;
  759. }
  760. }
  761. if (PartitionContext->PartitionCount != 0) {
  762. Status = IoMergeChildArrays(Irp,
  763. Parent->Children,
  764. PartitionContext->PartitionCount,
  765. PARTITION_ALLOCATION_TAG);
  766. if (!KSUCCESS(Status)) {
  767. goto EnumerateChildrenEnd;
  768. }
  769. }
  770. ASSERT(Parent->RawDisk != NULL);
  771. Status = IoMergeChildArrays(Irp,
  772. &(Parent->RawDisk),
  773. 1,
  774. PARTITION_ALLOCATION_TAG);
  775. if (!KSUCCESS(Status)) {
  776. goto EnumerateChildrenEnd;
  777. }
  778. EnumerateChildrenEnd:
  779. if (Child != NULL) {
  780. PartpReleaseReference(&(Child->Header));
  781. }
  782. return Status;
  783. }
  784. KSTATUS
  785. PartpReadPartitionStructures (
  786. PPARTITION_PARENT Parent
  787. )
  788. /*++
  789. Routine Description:
  790. This routine is called to enumerate the partitions in a disk. This routine
  791. is called by a disk device upon starting.
  792. Arguments:
  793. Irp - Supplies a pointer to the query children IRP.
  794. Parent - Supplies a pointer to the partition parent.
  795. Return Value:
  796. Status code.
  797. --*/
  798. {
  799. ULONGLONG DiskCapacity;
  800. ULONG DiskOffsetAlignment;
  801. ULONG DiskSizeAlignment;
  802. PPARTITION_CONTEXT PartitionContext;
  803. KSTATUS Status;
  804. PartitionContext = &(Parent->PartitionContext);
  805. Status = STATUS_SUCCESS;
  806. //
  807. // Do nothing if the information has already been gathered.
  808. //
  809. if (PartitionContext->BlockSize != 0) {
  810. goto ReadPartitionStructuresEnd;
  811. }
  812. Status = IoOpenDevice(Parent->RawDisk,
  813. IO_ACCESS_READ,
  814. 0,
  815. &(Parent->IoHandle),
  816. &DiskOffsetAlignment,
  817. &DiskSizeAlignment,
  818. &DiskCapacity);
  819. if (!KSUCCESS(Status)) {
  820. goto ReadPartitionStructuresEnd;
  821. }
  822. PartitionContext->AllocateFunction = PartpAllocate;
  823. PartitionContext->FreeFunction = PartpFree;
  824. PartitionContext->ReadFunction = PartpRead;
  825. PartitionContext->BlockSize = DiskOffsetAlignment;
  826. PartitionContext->BlockCount = DiskCapacity / PartitionContext->BlockSize;
  827. PartitionContext->Alignment = MmGetIoBufferAlignment();
  828. Status = PartInitialize(PartitionContext);
  829. if (!KSUCCESS(Status)) {
  830. PartitionContext->BlockSize = 0;
  831. goto ReadPartitionStructuresEnd;
  832. }
  833. Status = PartEnumeratePartitions(PartitionContext);
  834. //
  835. // If the partition table isn't valid or no partitions enumreate, make the
  836. // entire disk mountable, maybe there's just a raw file system here.
  837. //
  838. if ((Status == STATUS_NO_ELIGIBLE_DEVICES) ||
  839. ((KSUCCESS(Status)) && (PartitionContext->PartitionCount == 0))) {
  840. IoSetDeviceMountable(Parent->RawDisk);
  841. Status = STATUS_SUCCESS;
  842. } else if (!KSUCCESS(Status)) {
  843. //
  844. // For other failures, clear the block size so it tries again next
  845. // time around.
  846. //
  847. PartitionContext->BlockSize = 0;
  848. goto ReadPartitionStructuresEnd;
  849. }
  850. //
  851. // Poke the system to re-enumerate the parent. Failure is not fatal.
  852. //
  853. IoNotifyDeviceTopologyChange(Parent->Device);
  854. ReadPartitionStructuresEnd:
  855. if (Parent->IoHandle != NULL) {
  856. IoClose(Parent->IoHandle);
  857. Parent->IoHandle = NULL;
  858. }
  859. return Status;
  860. }
  861. VOID
  862. PartpHandleDeviceInformationRequest (
  863. PIRP Irp,
  864. PPARTITION_CHILD Child
  865. )
  866. /*++
  867. Routine Description:
  868. This routine handles requests to get and set device information for the
  869. partition.
  870. Arguments:
  871. Irp - Supplies a pointer to the IRP making the request.
  872. Child - Supplies a pointer to the partition context.
  873. Return Value:
  874. None. Any completion status is set in the IRP.
  875. --*/
  876. {
  877. PPARTITION_DEVICE_INFORMATION Information;
  878. BOOL Match;
  879. PPARTITION_PARENT Parent;
  880. PPARTITION_CONTEXT PartitionContext;
  881. PPARTITION_INFORMATION PartitionInformation;
  882. PSYSTEM_CONTROL_DEVICE_INFORMATION Request;
  883. KSTATUS Status;
  884. Request = Irp->U.SystemControl.SystemContext;
  885. //
  886. // If this is not a request for the partition device information, ignore it.
  887. //
  888. Match = RtlAreUuidsEqual(&(Request->Uuid),
  889. &PartPartitionDeviceInformationUuid);
  890. if (Match == FALSE) {
  891. return;
  892. }
  893. //
  894. // Setting partition information is not supported.
  895. //
  896. if (Request->Set != FALSE) {
  897. Status = STATUS_ACCESS_DENIED;
  898. goto HandleDeviceInformationRequestEnd;
  899. }
  900. //
  901. // Make sure the size is large enough.
  902. //
  903. if (Request->DataSize < sizeof(PARTITION_DEVICE_INFORMATION)) {
  904. Request->DataSize = sizeof(PARTITION_DEVICE_INFORMATION);
  905. Status = STATUS_BUFFER_TOO_SMALL;
  906. goto HandleDeviceInformationRequestEnd;
  907. }
  908. ASSERT(Child->Header.Type == PartitionObjectChild);
  909. Parent = Child->Parent;
  910. PartitionContext = &(Parent->PartitionContext);
  911. Request->DataSize = sizeof(PARTITION_DEVICE_INFORMATION);
  912. Information = Request->Data;
  913. RtlZeroMemory(Information, sizeof(PARTITION_DEVICE_INFORMATION));
  914. Information->Version = PARTITION_DEVICE_INFORMATION_VERSION;
  915. Information->PartitionFormat = PartitionContext->Format;
  916. Information->BlockSize = PartitionContext->BlockSize;
  917. RtlCopyMemory(&(Information->DiskId),
  918. &(PartitionContext->DiskIdentifier),
  919. sizeof(Information->DiskId));
  920. //
  921. // If the index is -1, fill out the information for the parent disk itself.
  922. //
  923. if (Child->Index == -1) {
  924. Information->PartitionType = PartitionTypeNone;
  925. Information->Flags = PARTITION_FLAG_RAW_DISK;
  926. Information->FirstBlock = 0;
  927. Information->LastBlock = PartitionContext->BlockCount - 1;
  928. //
  929. // Fill out the information for the specific partition.
  930. //
  931. } else {
  932. ASSERT(Child->Index < PartitionContext->PartitionCount);
  933. PartitionInformation = &(PartitionContext->Partitions[Child->Index]);
  934. Information->PartitionType = PartitionInformation->PartitionType;
  935. Information->Flags = PartitionInformation->Flags;
  936. Information->FirstBlock = PartitionInformation->StartOffset;
  937. Information->LastBlock = PartitionInformation->EndOffset - 1;
  938. Information->Number = PartitionInformation->Number;
  939. Information->ParentNumber = PartitionInformation->ParentNumber;
  940. RtlCopyMemory(&(Information->PartitionId),
  941. &(PartitionInformation->Identifier),
  942. sizeof(Information->PartitionId));
  943. RtlCopyMemory(&(Information->PartitionTypeId),
  944. &(PartitionInformation->TypeIdentifier),
  945. sizeof(Information->PartitionTypeId));
  946. }
  947. Status = STATUS_SUCCESS;
  948. HandleDeviceInformationRequestEnd:
  949. IoCompleteIrp(PartDriver, Irp, Status);
  950. return;
  951. }
  952. VOID
  953. PartpHandleBlockInformationRequest (
  954. PIRP Irp,
  955. PPARTITION_CHILD Child
  956. )
  957. /*++
  958. Routine Description:
  959. This routine handles requests to get block information for the partition.
  960. Arguments:
  961. Irp - Supplies a pointer to the IRP making the request.
  962. Child - Supplies a pointer to the partition context.
  963. Return Value:
  964. None. Any completion status is set in the IRP.
  965. --*/
  966. {
  967. ULONGLONG BlockCount;
  968. PFILE_BLOCK_ENTRY BlockEntry;
  969. PFILE_BLOCK_INFORMATION BlockInformation;
  970. PLIST_ENTRY CurrentEntry;
  971. PPARTITION_PARENT Parent;
  972. PPARTITION_CONTEXT PartitionContext;
  973. PPARTITION_INFORMATION PartitionInformation;
  974. PPARTITION_INFORMATION Partitions;
  975. PSYSTEM_CONTROL_GET_BLOCK_INFORMATION Request;
  976. KSTATUS Status;
  977. ASSERT(Child->Header.Type == PartitionObjectChild);
  978. Request = Irp->U.SystemControl.SystemContext;
  979. BlockInformation = Request->FileBlockInformation;
  980. Parent = Child->Parent;
  981. PartitionContext = &(Parent->PartitionContext);
  982. //
  983. // If the request already contains non-empty file information, then the
  984. // partition is being requested to convert relative block offsets into
  985. // absolute block offsets.
  986. //
  987. if ((BlockInformation != NULL) &&
  988. (LIST_EMPTY(&(BlockInformation->BlockList)) == FALSE)) {
  989. //
  990. // If the index is -1, then the offsets are already accurate as there
  991. // are no partitions in the way.
  992. //
  993. if (Child->Index == -1) {
  994. Status = STATUS_SUCCESS;
  995. goto HandleBlockInformationRequestEnd;
  996. }
  997. ASSERT(Child->Index < PartitionContext->PartitionCount);
  998. Partitions = PartitionContext->Partitions;
  999. PartitionInformation = &(Partitions[Child->Index]);
  1000. //
  1001. // Otherwise, iterate over the list and convert the addresses.
  1002. //
  1003. CurrentEntry = BlockInformation->BlockList.Next;
  1004. while (CurrentEntry != &(BlockInformation->BlockList)) {
  1005. BlockEntry = LIST_VALUE(CurrentEntry, FILE_BLOCK_ENTRY, ListEntry);
  1006. Status = PartTranslateIo(PartitionInformation,
  1007. &(BlockEntry->Address),
  1008. &(BlockEntry->Count));
  1009. if (!KSUCCESS(Status)) {
  1010. goto HandleBlockInformationRequestEnd;
  1011. }
  1012. CurrentEntry = CurrentEntry->Next;
  1013. }
  1014. //
  1015. // Otherwise this is a request for the absolute block offsets and size of
  1016. // the partition.
  1017. //
  1018. } else {
  1019. if (BlockInformation == NULL) {
  1020. BlockInformation = MmAllocateNonPagedPool(
  1021. sizeof(FILE_BLOCK_INFORMATION),
  1022. PARTITION_ALLOCATION_TAG);
  1023. if (BlockInformation == NULL) {
  1024. Status = STATUS_INSUFFICIENT_RESOURCES;
  1025. goto HandleBlockInformationRequestEnd;
  1026. }
  1027. INITIALIZE_LIST_HEAD(&(BlockInformation->BlockList));
  1028. }
  1029. BlockEntry = MmAllocateNonPagedPool(sizeof(FILE_BLOCK_ENTRY),
  1030. PARTITION_ALLOCATION_TAG);
  1031. if (BlockEntry == NULL) {
  1032. Status = STATUS_INSUFFICIENT_RESOURCES;
  1033. goto HandleBlockInformationRequestEnd;
  1034. }
  1035. //
  1036. // If the index is -1, then get the information for the whole parent
  1037. // disk.
  1038. //
  1039. if (Child->Index == -1) {
  1040. BlockEntry->Address = 0;
  1041. BlockEntry->Count = PartitionContext->BlockCount;
  1042. //
  1043. // Otherwise return the information for the particular partition.
  1044. //
  1045. } else {
  1046. ASSERT(Child->Index < PartitionContext->PartitionCount);
  1047. Partitions = PartitionContext->Partitions;
  1048. PartitionInformation = &(Partitions[Child->Index]);
  1049. BlockEntry->Address = PartitionInformation->StartOffset;
  1050. BlockCount = PartitionInformation->EndOffset -
  1051. PartitionInformation->StartOffset;
  1052. BlockEntry->Count = BlockCount;
  1053. }
  1054. INSERT_BEFORE(&(BlockEntry->ListEntry), &(BlockInformation->BlockList));
  1055. //
  1056. // Fill the block information back into the request, in case it was
  1057. // allocated.
  1058. //
  1059. Request->FileBlockInformation = BlockInformation;
  1060. }
  1061. Status = STATUS_SUCCESS;
  1062. HandleBlockInformationRequestEnd:
  1063. if (!KSUCCESS(Status)) {
  1064. if ((BlockInformation != NULL) &&
  1065. (BlockInformation != Request->FileBlockInformation)) {
  1066. while (LIST_EMPTY(&(BlockInformation->BlockList)) == FALSE) {
  1067. BlockEntry = LIST_VALUE(BlockInformation->BlockList.Next,
  1068. FILE_BLOCK_ENTRY,
  1069. ListEntry);
  1070. LIST_REMOVE(&(BlockEntry->ListEntry));
  1071. MmFreeNonPagedPool(BlockEntry);
  1072. }
  1073. MmFreeNonPagedPool(BlockInformation);
  1074. }
  1075. }
  1076. IoCompleteIrp(PartDriver, Irp, Status);
  1077. return;
  1078. }
  1079. PVOID
  1080. PartpAllocate (
  1081. UINTN Size
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. This routine allocates memory for the partition manager.
  1086. Arguments:
  1087. Size - Supplies the size of the allocation request, in bytes.
  1088. Return Value:
  1089. Returns a pointer to the allocation if successful, or NULL if the
  1090. allocation failed.
  1091. --*/
  1092. {
  1093. return MmAllocateNonPagedPool(Size, PARTITION_ALLOCATION_TAG);
  1094. }
  1095. VOID
  1096. PartpFree (
  1097. PVOID Memory
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. This routine frees allocated memory for the partition manager.
  1102. Arguments:
  1103. Memory - Supplies the allocation returned by the allocation routine.
  1104. Return Value:
  1105. None.
  1106. --*/
  1107. {
  1108. MmFreeNonPagedPool(Memory);
  1109. return;
  1110. }
  1111. KSTATUS
  1112. PartpRead (
  1113. PPARTITION_CONTEXT Context,
  1114. ULONGLONG BlockAddress,
  1115. PVOID Buffer
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. This routine reads from the underlying disk.
  1120. Arguments:
  1121. Context - Supplies the partition context identifying the disk.
  1122. BlockAddress - Supplies the block address to read.
  1123. Buffer - Supplies a pointer where the data will be returned on success.
  1124. This buffer is expected to be one block in size (as specified in the
  1125. partition context).
  1126. Return Value:
  1127. Status code.
  1128. --*/
  1129. {
  1130. UINTN BytesCompleted;
  1131. PIO_BUFFER IoBuffer;
  1132. PPARTITION_PARENT Parent;
  1133. KSTATUS Status;
  1134. Parent = PARENT_STRUCTURE(Context, PARTITION_PARENT, PartitionContext);
  1135. ASSERT((Parent->Header.Type == PartitionObjectParent) &&
  1136. (Parent->IoHandle != NULL) &&
  1137. (Context->BlockSize != 0));
  1138. Status = MmCreateIoBuffer(Buffer,
  1139. Context->BlockSize,
  1140. IO_BUFFER_FLAG_KERNEL_MODE_DATA,
  1141. &IoBuffer);
  1142. if (!KSUCCESS(Status)) {
  1143. goto ReadEnd;
  1144. }
  1145. Status = IoReadAtOffset(Parent->IoHandle,
  1146. IoBuffer,
  1147. BlockAddress << Context->BlockShift,
  1148. Context->BlockSize,
  1149. 0,
  1150. WAIT_TIME_INDEFINITE,
  1151. &BytesCompleted,
  1152. NULL);
  1153. if (!KSUCCESS(Status)) {
  1154. goto ReadEnd;
  1155. }
  1156. ReadEnd:
  1157. if (IoBuffer != NULL) {
  1158. MmFreeIoBuffer(IoBuffer);
  1159. }
  1160. return Status;
  1161. }
  1162. PPARTITION_CHILD
  1163. PartpCreateChild (
  1164. PPARTITION_PARENT Parent,
  1165. ULONG Index
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. This routine creates a partition child structure.
  1170. Arguments:
  1171. Parent - Supplies a pointer to the parent structure.
  1172. Index - Supplies the child index for this child.
  1173. Return Value:
  1174. Returns a pointer to the new child structure on success.
  1175. NULL on allocation failure.
  1176. --*/
  1177. {
  1178. PPARTITION_CHILD Child;
  1179. Child = PartpAllocate(sizeof(PARTITION_CHILD));
  1180. if (Child == NULL) {
  1181. return NULL;
  1182. }
  1183. RtlZeroMemory(Child, sizeof(PARTITION_CHILD));
  1184. Child->Header.Type = PartitionObjectChild;
  1185. Child->Header.ReferenceCount = 1;
  1186. Child->Parent = Parent;
  1187. PartpAddReference(&(Parent->Header));
  1188. Child->Index = Index;
  1189. return Child;
  1190. }
  1191. VOID
  1192. PartpAddReference (
  1193. PPARTITION_OBJECT Object
  1194. )
  1195. /*++
  1196. Routine Description:
  1197. This routine adds a reference on the given partition manager context.
  1198. Arguments:
  1199. Object - Supplies a pointer to the partition manager object.
  1200. Return Value:
  1201. None.
  1202. --*/
  1203. {
  1204. ULONG OldReferenceCount;
  1205. OldReferenceCount = RtlAtomicAdd32(&(Object->ReferenceCount), 1);
  1206. ASSERT(OldReferenceCount < 0x10000000);
  1207. return;
  1208. }
  1209. VOID
  1210. PartpReleaseReference (
  1211. PPARTITION_OBJECT Object
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. This routine releases a reference on a partition object.
  1216. Arguments:
  1217. Object - Supplies a pointer to the partition manager object.
  1218. Return Value:
  1219. None.
  1220. --*/
  1221. {
  1222. ULONG OldReferenceCount;
  1223. OldReferenceCount = RtlAtomicAdd32(&(Object->ReferenceCount), (ULONG)-1);
  1224. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  1225. if (OldReferenceCount == 1) {
  1226. PartpDestroyDevice(Object);
  1227. }
  1228. return;
  1229. }
  1230. VOID
  1231. PartpDestroyDevice (
  1232. PPARTITION_OBJECT Object
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. This routine destroys a partition manager object.
  1237. Arguments:
  1238. Object - Supplies a pointer to the partition manager object.
  1239. Return Value:
  1240. None.
  1241. --*/
  1242. {
  1243. PPARTITION_CHILD Child;
  1244. PPARTITION_PARENT Parent;
  1245. switch (Object->Type) {
  1246. case PartitionObjectParent:
  1247. Parent = PARENT_STRUCTURE(Object, PARTITION_PARENT, Header);
  1248. if (Parent->PartitionContext.BlockSize != 0) {
  1249. PartDestroy(&(Parent->PartitionContext));
  1250. Parent->PartitionContext.BlockSize = 0;
  1251. }
  1252. if (Parent->Children != NULL) {
  1253. MmFreePagedPool(Parent->Children);
  1254. }
  1255. ASSERT(Parent->IoHandle == NULL);
  1256. Parent->Header.Type = PartitionObjectInvalid;
  1257. PartpFree(Parent);
  1258. break;
  1259. case PartitionObjectChild:
  1260. Child = PARENT_STRUCTURE(Object, PARTITION_CHILD, Header);
  1261. PartpReleaseReference(&(Child->Parent->Header));
  1262. Child->Header.Type = PartitionObjectInvalid;
  1263. PartpFree(Child);
  1264. break;
  1265. default:
  1266. ASSERT(FALSE);
  1267. return;
  1268. }
  1269. return;
  1270. }