part.c 41 KB

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