From: Mike Pittelkow [mikep@xiotech.com]
Sent: Tuesday, November 02, 1999 9:09 AM
To: jkirby@storagecraft.com; robg@cdp.com
Cc: ntdev@atria.com
Subject: RE: [ntdev] New a version of IoReadPartitonTable()

I've been around in circles with MS on this one too.  Took a while to figure
out.

Here's my code for that function.  It should be fairly easy to understand,
but let me know if you need help.  You have to cache the part. info in your
device extension, and return it only if the device is not reserved.
get_drive_layout is the only routine allowed to call getpartitioninformation
(without recursing, anyway)  There's a lot of contortions here to be sure my
target device is not reserved.  This is a lot like the sample code in the
ddk (but more verbose)


	case	IOCTL_DISK_GET_PARTITION_INFO:
		{
			PPARTITION_INFORMATION	PartitionInfo =
(PPARTITION_INFORMATION)OutputBuffer;
			NTSTATUS					Status;
			PVRP_ENTRY	mVRP;
			char	*	Sector;
			PMDL		Mdl;
			UCHAR		VRPStatus;

			if (PartitionExtension == DiskExtension->Partition0)
			{
				DbgPrint("XIO: Get partition information for partition0 is invalid.\n");
				IRPSTATUS(Irp,STATUS_INVALID_DEVICE_REQUEST,0);
				break;
			}


			if (DiskExtension == NULL)
			{
					IRPSTATUS(Irp,STATUS_INVALID_DEVICE_REQUEST,0);
					break;
			}

			mVRP=GetUnbalancedVRP(DeviceExtension);	// Get a VRP for a single sector
			if (mVRP != NULL)
			{
					Sector = ExAllocatePool(NonPagedPool,DiskExtension->BlockSize);
					if (Sector != NULL)
					{

						Mdl = IoAllocateMdl(Sector,DiskExtension->BlockSize,FALSE,FALSE,NULL);
						MmBuildMdlForNonPagedPool(Mdl);

InitializeVRP(mVRP,VR_FUNC_READ,NULL,Mdl,1,FALSE,DiskExtension->VirtualID,0)
;
						mVRP->VRP->VRP_Entry.StartingAddress=0;
						if (!WaitForIO(mVRP,&VRPStatus,TRUE))
						{
							IRPSTATUS(Irp,STATUS_DEVICE_BUSY,0);	// The IO timed out, so fail
this request
						}
						ExFreePool(Sector);
						if (VRPStatus != VR_STAT_OK)
						{
							IRPSTATUS(Irp,STATUS_DEVICE_BUSY,0);		// Read was not successful, so
fail the request
							break;
						}

						// If we got here, the read was usccessful, so go on to return that
partition information
					}
					else
					{
						IRPSTATUS(Irp,STATUS_INSUFFICIENT_RESOURCES,0);		// not enough
resources to do a "check" io, so give up
						break;
					}


			}
			else
			{
					IRPSTATUS(Irp,STATUS_INVALID_DEVICE_REQUEST,0);	// Fail if we can't get
the VRP.
					break;
			}


			if (OutputBufferLength < sizeof(PARTITION_INFORMATION)) // Buffer is too
small.
				{
					DbgPrint("XIO: Get partition information, buffer is too small.\n");
					IRPSTATUS(Irp,STATUS_BUFFER_TOO_SMALL,0);
					break;
				}
				else								//Buffer big enough, so copy the data.
				{

RtlCopyMemory(PartitionInfo,&PartitionExtension->PartitionInformation,sizeof
(PARTITION_INFORMATION));
					PartitionInfo->RecognizedPartition = TRUE;
					PartitionInfo->RewritePartition = FALSE;
					DUMP_PARTITION(PartitionInfo,0xFF);
					IRPSTATUS(Irp,STATUS_SUCCESS,sizeof(PARTITION_INFORMATION));
					break;
				}

		}
	case	IOCTL_DISK_SET_DRIVE_LAYOUT:
		{

			PDRIVE_LAYOUT_INFORMATION	DriveLayout =
(PDRIVE_LAYOUT_INFORMATION)OutputBuffer; // Note: this is a little odd
			NTSTATUS	Status;
			UCHAR		Count;
			PPARTITION_INFORMATION	PartInfo;

			if (DiskExtension == NULL)
			{
					IRPSTATUS(Irp,STATUS_INVALID_DEVICE_REQUEST,0);
					break;
			}
			if (InputBufferLength < sizeof(DRIVE_LAYOUT_INFORMATION))
			{
    				IRPSTATUS(Irp,STATUS_INFO_LENGTH_MISMATCH,0);
					break;
			}

			if (InputBufferLength <
(sizeof(DRIVE_LAYOUT_INFORMATION)+(DriveLayout->PartitionCount -
1)*sizeof(PARTITION_INFORMATION)))
			{
    				IRPSTATUS(Irp,STATUS_BUFFER_TOO_SMALL,0);
					break;
			}


			ResolvePartitionObjects(DriveLayout,DiskExtension);
			Status = IoWritePartitionTable(DiskExtension->Partition0->ThisPartition,
										   DiskExtension->DiskGeometry.BytesPerSector,
										   DiskExtension->DiskGeometry.SectorsPerTrack,
										   DiskExtension->DiskGeometry.TracksPerCylinder,
										   DriveLayout);
			if (!NT_SUCCESS(Status))
			{
				IRPSTATUS(Irp,Status,0);
				break;
			}

			DUMP_PARTITION_TABLE(DriveLayout);
			IRPSTATUS(Irp,STATUS_SUCCESS,OutputBufferLength);
			break;


		}
	case	IOCTL_DISK_GET_DRIVE_LAYOUT:
		{
				PDRIVE_LAYOUT_INFORMATION	DriveLayout;
				PDRIVE_LAYOUT_INFORMATION	OutputLayout =
(PDRIVE_LAYOUT_INFORMATION)OutputBuffer;
				ULONG	TotalSize = 0;
				NTSTATUS	Status;
			if (DiskExtension == NULL)
			{
					IRPSTATUS(Irp,STATUS_INVALID_DEVICE_REQUEST,0);
					break;
			}
				DbgPrint("XIO: calling IoReadPartitionTable (DGDL)\n");
				Status =
IoReadPartitionTable(DiskExtension->Partition0->ThisPartition,DiskExtension-
>BlockSize,FALSE,&DriveLayout);
				if (!NT_SUCCESS(Status))
				{
//					DbgPrint("XIO: Get Drive Layout - Unable to read partition
table.\n");
					IRPSTATUS(Irp,Status,0);
					break;
				}

				TotalSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]);
				TotalSize = TotalSize + DriveLayout->PartitionCount *
sizeof(PARTITION_INFORMATION);
				if (OutputBufferLength < TotalSize) // Buffer is too small.
				{
 					ExFreePool(DriveLayout);
					DbgPrint("XIO: Get Drive Layout - buffer is too small.\n");
	   				IRPSTATUS(Irp,STATUS_BUFFER_TOO_SMALL,0);
					break;
				}
				else								//Buffer big enough, so copy the data.
				{
					ResolvePartitionObjects(DriveLayout,DiskExtension);
					DUMP_PARTITION_TABLE(DriveLayout);
					RtlCopyMemory(OutputLayout,DriveLayout,TotalSize);
					ExFreePool(DriveLayout);
					IRPSTATUS(Irp,STATUS_SUCCESS,TotalSize);
					break;
				}

		}

> -----Original Message-----
> From: owner-ntdev@atria.com [mailto:owner-ntdev@atria.com]On Behalf Of
> jkirby@storagecraft.com
> Sent: Monday, November 01, 1999 6:34 AM
> To: robg@cdp.com
> Cc: ntdev@atria.com
> Subject: Re: [ntdev] New a version of IoReadPartitonTable()
>
>
> No, it does not emulate the NT 4.0 functionality. Thanks for the thought.
>
> Jamey
>
>
> On Sun, 31 October 1999, Rob Green wrote:
>
> >
> > if you look at E:\NTDDK\src\storage\class\disk\drivesup.c that
> have source
> > code to xHalIoReadPartitionTable which is suppose to emulate
> that function.
> >
> > What i do is just send the request on through and get the data
> i need from
> > the completion routine.
> >
> > rob
> >
> >
> > At 10:47 AM 10/31/1999 , jkirby@storagecraft.com wrote:
> > >All,
> > >
> > >I am porting a filter driver from NT 4.0 to Windows 2000.
> Under NT 4.0,
> > >IoReadPartitionTable() issues an IRP_MJ_READ to get the
> partition table
> > >from the disk. Under Windows 2000, IoReadPartitionTable() calls
> > >IOCTL_DISK_GET_DRIVE_LAYOUT. Unfortunatly, in my
> IOCTL_GET_DRIVE_LAYOUT
> > >handler, I call IoReadPatrtitonTable() as well (I am a disk
> filter). As
> > >you can see, I hit recursion into my IOCTL_GET_DRIVE_LAYOUT handler. I
> > >need some source code to demonstrate how to read the partiton
> table and
> > >build a DRIVE_LAYOPUT_INFORMATION structure like the 4.0 version of
> > >IoReadPartitonTable().
> > >
> > >I can write my own, it is only a matter of a couple of days to
> write it
> > >and test it. It would be much easier if someone already has code to do
> > >this. I am under a extream deadline and don't really have the
> extra couple
> > >of days to write and debug the code.
> > >
> > >Amy help would be appreciated.
> > >
> > >Regards,
> > >
> > >Jamey Kirby
> > >StorageCraft
> > >www.storagecraft.com
> > >jkirby@storagecraft.com
> > >  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> > >[ To unsubscribe, send email to ntdev-request@atria.com with body
> > >UNSUBSCRIBE (the subject is ignored). ]
>
>
>  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> [ To unsubscribe, send email to ntdev-request@atria.com with body
> UNSUBSCRIBE (the subject is ignored). ]
>

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ To unsubscribe, send email to ntdev-request@atria.com with body
UNSUBSCRIBE (the subject is ignored). ]
