Making the Ramdisk sample mountable

Hello,

I want to make the Ramdisk sample a first class Windows citizen and make it
mountable and supporting arbitrary FS on it. No, this is not done for
performance reasons, I know the Cache Manager does a much better job then a
Ramdisk.

Right now the Ramdisk formats itself and creates a drive letter via a
symbolic link. The Ramdisk can’t be seen by the diskmgmt.msc tools and can’t
be formatted or remounted.

I have added support for multiple Ramdisk devices loaded simultaneously.

I have implemented support for IOCTL_MOUNTDEV_QUERY_UNIQUE_ID and
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME ioctls. From what I understand, this are
the only mandatory ioctls required by the mount manager.

case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:

{
PMOUNTDEV_NAME OutputBuffer;

//
// Return the NT Device Name to the Mount Manager
//

Status = WdfRequestRetrieveOutputBuffer(
Request,
sizeof(MOUNTDEV_NAME),
&OutputBuffer,
&bufSize
);

if (NT_SUCCESS(Status))
{
WCHAR DeviceName = NT_DEVICE_NAME;
USHORT CbDeviceNameLen = sizeof(DeviceName);

ULONG_PTR MinimumBufferLength =
OutputBuffer->NameLength + sizeof(USHORT);

//
// If the buffer retrieved is big enough, just copy the
// Device Name to it.
//
if (bufSize >= MinimumBufferLength)
{
OutputBuffer->NameLength = CbDeviceNameLen;
RtlCopyMemory(OutputBuffer->Name, DeviceName,
CbDeviceNameLen);
information = MinimumBufferLength;
Status = STATUS_SUCCESS;

break;
}

//
// If the buffer is not big enough we must return to the
mount
// manager the actual size we need.
//
else
{
OutputBuffer->NameLength = CbDeviceNameLen;
information = sizeof(MOUNTDEV_NAME);
Status = STATUS_BUFFER_OVERFLOW;

break;
}
}

break;
}

case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:

{
PMOUNTDEV_UNIQUE_ID OutputBuffer;

//
// Return a unique ID to the Mount Manager.
//

Status = WdfRequestRetrieveOutputBuffer(
Request,
sizeof(MOUNTDEV_UNIQUE_ID),
&OutputBuffer,
&bufSize
);

if (NT_SUCCESS(Status))
{
UCHAR UniqueIdName = “test only”; // hardcoded name sa far
UCHAR CbUniqueIdNameLen = sizeof(UniqueIdName);

RtlCopyMemory(
OutputBuffer->UniqueId,
UniqueIdName,
CbUniqueIdNameLen
);
OutputBuffer->UniqueIdLength = CbUniqueIdNameLen;

information = CbUniqueIdNameLen + sizeof(USHORT);

break;
}

break;
}

I have created the MOUNTDEV_MOUNTED_DEVICE_GUID device interface to register
with the mount manager like this:

NTSTATUS
RamDiskRegisterDeviceWithMountManager(
WDFDEVICE device
)
{
NTSTATUS Status;
PDEVICE_OBJECT Pdo;
UNICODE_STRING SymbolicLinkName;
KdPrint((
MGKRAMDISK
"trying to register with the mount manager… "
));
Pdo = WdfDeviceWdmGetPhysicalDevice(device);
Status = IoRegisterDeviceInterface(
Pdo,
&MOUNTDEV_MOUNTED_DEVICE_GUID,
NULL,
&SymbolicLinkName
);
KdPrint((
MGKRAMDISK
“symbolic link name is %S\n”,
SymbolicLinkName.Buffer
));
RtlFreeUnicodeString(&SymbolicLinkName);
return Status;

}

The function returns success, however, my device does not appear in
diskmgmt.msc. Is there anything else I should do? Any more ioctls I need to
support?

Thanks,


Aram Hăvărneanu

Take a look at the disk class driver in the WDK, you need to support
everything it does.

Don Burn (MVP, Windows DKD)

Windows Filesystem and Driver Consulting

Website: http://www.windrvr.com

Blog: http://msmvps.com/blogs/WinDrvr

From: Aram Havarneanu [mailto:xxxxx@mgk.ro]
Posted At: Monday, April 05, 2010 1:06 PM
Posted To: ntdev
Conversation: Making the Ramdisk sample mountable
Subject: Making the Ramdisk sample mountable

Hello,

I want to make the Ramdisk sample a first class Windows citizen and make
it mountable and supporting arbitrary FS on it. No, this is not done for
performance reasons, I know the Cache Manager does a much better job then
a Ramdisk.

Right now the Ramdisk formats itself and creates a drive letter via a
symbolic link. The Ramdisk can’t be seen by the diskmgmt.msc tools and
can’t be formatted or remounted.

I have added support for multiple Ramdisk devices loaded simultaneously.

I have implemented support for IOCTL_MOUNTDEV_QUERY_UNIQUE_ID and
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME ioctls. From what I understand, this are
the only mandatory ioctls required by the mount manager.

case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:

{

PMOUNTDEV_NAME OutputBuffer;

//

// Return the NT Device Name to the Mount Manager

//

Status = WdfRequestRetrieveOutputBuffer(

Request,

sizeof(MOUNTDEV_NAME),

&OutputBuffer,

&bufSize

);

if (NT_SUCCESS(Status))

{

WCHAR DeviceName = NT_DEVICE_NAME;

USHORT CbDeviceNameLen = sizeof(DeviceName);

ULONG_PTR MinimumBufferLength =

OutputBuffer->NameLength + sizeof(USHORT);

//

// If the buffer retrieved is big enough, just copy the

// Device Name to it.

//

if (bufSize >= MinimumBufferLength)

{

OutputBuffer->NameLength = CbDeviceNameLen;

RtlCopyMemory(OutputBuffer->Name, DeviceName,
CbDeviceNameLen);

information = MinimumBufferLength;

Status = STATUS_SUCCESS;

break;

}

//

// If the buffer is not big enough we must return to the
mount

// manager the actual size we need.

//

else

{

OutputBuffer->NameLength = CbDeviceNameLen;

information = sizeof(MOUNTDEV_NAME);

Status = STATUS_BUFFER_OVERFLOW;

break;

}

}

break;

}

case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:

{

PMOUNTDEV_UNIQUE_ID OutputBuffer;

//

// Return a unique ID to the Mount Manager.

//

Status = WdfRequestRetrieveOutputBuffer(

Request,

sizeof(MOUNTDEV_UNIQUE_ID),

&OutputBuffer,

&bufSize

);

if (NT_SUCCESS(Status))

{

UCHAR UniqueIdName = “test only”; // hardcoded name sa
far

UCHAR CbUniqueIdNameLen = sizeof(UniqueIdName);

RtlCopyMemory(

OutputBuffer->UniqueId,

UniqueIdName,

CbUniqueIdNameLen

);

OutputBuffer->UniqueIdLength = CbUniqueIdNameLen;

information = CbUniqueIdNameLen + sizeof(USHORT);

break;

}

break;

}

I have created the MOUNTDEV_MOUNTED_DEVICE_GUID device interface to
register with the mount manager like this:

NTSTATUS

RamDiskRegisterDeviceWithMountManager(

WDFDEVICE device

)

{

NTSTATUS Status;

PDEVICE_OBJECT Pdo;

UNICODE_STRING SymbolicLinkName;

KdPrint((

MGKRAMDISK

"trying to register with the mount manager… "

));

Pdo = WdfDeviceWdmGetPhysicalDevice(device);

Status = IoRegisterDeviceInterface(

Pdo,

&MOUNTDEV_MOUNTED_DEVICE_GUID,

NULL,

&SymbolicLinkName

);

KdPrint((

MGKRAMDISK

“symbolic link name is %S\n”,

SymbolicLinkName.Buffer

));

RtlFreeUnicodeString(&SymbolicLinkName);

return Status;

}

The function returns success, however, my device does not appear in
diskmgmt.msc. Is there anything else I should do? Any more ioctls I need
to support?

Thanks,

Aram Havarneanu

__________ Information from ESET Smart Security, version of virus
signature database 5001 (20100405) __________

The message was checked by ESET Smart Security.

http://www.eset.com

On Mon, Apr 5, 2010 at 8:05 PM, Aram Hăvărneanu wrote:
> Hello,
> I want to make the Ramdisk sample a first class Windows citizen and make it
> mountable and supporting arbitrary FS on it. No, this is not done for
> performance reasons, I know the Cache Manager does a much better job then a
> Ramdisk.

Well I have had SOME success.

> Right now the Ramdisk formats itself and creates a drive letter via a
> symbolic link. The Ramdisk can’t be seen by the diskmgmt.msc tools and can’t
> be formatted or remounted.
> I have added support for multiple Ramdisk devices loaded simultaneously.
> I have implemented support for IOCTL_MOUNTDEV_QUERY_UNIQUE_ID and
> IOCTL_MOUNTDEV_QUERY_DEVICE_NAME ioctls. From what I understand, this are
> the only mandatory ioctls required by the mount manager.

By implementing those things PROPERLY (the code I first posted wasn’t
right) and by supporting the MOUNTDEV_MOUNTED_DEVICE_GUID Device
Interface, the system is able to find my Ramdisk device! It
automatically assigns a letter to it (I don’t have to create a
symbolic link manually any more) and the autorun thing pops up.

However, the device STILL does not appear in diskmgmt.msc. I have
studied the classpnp sample, but I don’t see any more interaction with
the mount manager then what I already have done. In fact, MSDN
documentation seems to back me up:
http://msdn.microsoft.com/en-us/library/ff567603.aspx .

So what is the magic I need to do to be able to “see” my device in
diskmgmt.msc and other tools?

Thanks,


Aram Hăvărneanu

On Thu, Apr 8, 2010 at 6:32 PM, Aram Hăvărneanu wrote:
> On Mon, Apr 5, 2010 at 8:05 PM, Aram Hăvărneanu wrote:
>> Hello,
>> I want to make the Ramdisk sample a first class Windows citizen and make it
>> mountable and supporting arbitrary FS on it. No, this is not done for
>> performance reasons, I know the Cache Manager does a much better job then a
>> Ramdisk.
>
> Well I have had SOME success.

Even more, format.exe runs partially.

>> Right now the Ramdisk formats itself and creates a drive letter via a
>> symbolic link. The Ramdisk can’t be seen by the diskmgmt.msc tools and can’t
>> be formatted or remounted.
>> I have added support for multiple Ramdisk devices loaded simultaneously.
>> I have implemented support for IOCTL_MOUNTDEV_QUERY_UNIQUE_ID and
>> IOCTL_MOUNTDEV_QUERY_DEVICE_NAME ioctls. From what I understand, this are
>> the only mandatory ioctls required by the mount manager.
>
> By implementing those things PROPERLY (the code I first posted wasn’t
> right) and by supporting the MOUNTDEV_MOUNTED_DEVICE_GUID Device
> Interface, the system is able to find my Ramdisk device! It
> automatically assigns a letter to it (I don’t have to create a
> symbolic link manually any more) and the autorun thing pops up.

If I try to format the drive with NTFS, format.exe tells me:

“The NTFS file system does not function on floppy disks.”

So the system thinks I’m a floppy disk. Obviously, since I also get
DISK_GET_MEDIA_TYPES in my driver, and that ioctl is specific to
floppy disks.

> However, the device STILL does not appear in diskmgmt.msc. I have
> studied the classpnp sample, but I don’t see any more interaction with
> the mount manager then what I already have done. In fact, MSDN
> documentation seems to back me up:
> http://msdn.microsoft.com/en-us/library/ff567603.aspx .
>
> So what is the magic I need to do to be able to “see” my device in
> diskmgmt.msc and other tools?

I think floppy disks don’t appear there. Why does the system think I’m
a floppy disk? How to convince it that I am a fixed disk?

Thanks.


Aram Hăvărneanu

>Why does the system think I’m a floppy disk?
Do you assign ‘A’ or ‘B’ as a driver letter?

Igor Sharovar

On Mon, Apr 12, 2010 at 6:35 PM, wrote:
>>Why does the system think I’m a floppy disk?
> Do you assign ‘A’ or ‘B’ as a driver letter?

No, the system automatically assigns a letter greater then C.


Aram Hăvărneanu

You should check IOCTL_STORAGE_GET_MEDIA_TYPES or IOCTL_STORAGE_GET_MEDIA_TYPES_Ex IOCTL’s. These IOCTLs contains MediaType field which you need to specify. Put either RemovableMedia or FixedMedia as MEDIA_TYPE.
I would suggest to check all IOCTL which your driver gets. As Don said you need to support everything what a disk class driver does. In additional to study source code of the disk class driver it would be helpful to install an upper filter class disk driver on regular storage device. In this case you could see which IOCTL object of class driver gets and how it responses.

Igor Sharovar

> -----Original Message-----

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Aram
Havarneanu
Sent: Monday, April 12, 2010 4:24 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Making the Ramdisk sample mountable

I think floppy disks don’t appear there. Why does the system think I’m
a floppy disk? How to convince it that I am a fixed disk?

It is long time ago I worked in this area but I was able to format
virtual disk to NTFS (using both format.exe and GUI from exploder, not
from disk management). I don’t remember exactly what it was but here are
few things to examine:

  • DISK_GEOMETRY::MEDIA_TYPE (several IOCTLs)
  • IOCTL_STORAGE_GET_HOTPLUG_INFO
  • FILE_REMOVABLE_MEDIA in the device characteritics

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

…like Michal, I haven’t tried any of this in years. However, I seem to recall that Windows supports disks that LOOK like floppy disks but aren’t (hmmmm… I guess that’s obviously true, because your device IS one such disk).

IIRC, one way to recognize such disks is that there’s no partition table on the disk. Perhaps your answer to things like get partition table are causing this behavior?

What you’re experiencing is almost certainly the result of you trying to short-circuit all the yummy goodness that Mr. Disk Class provides. I know probably thought Mr. Burn was being abrupt with you back when you first posted your query when he replied:

“Take a look at the disk class driver in the WDK, you need to support
everything it does”

…but there’s in fact a lot of wisdom in that there statement.

You’re kinda injecting a “virtual disk” at the wrong place in the stack, you know??

I’m not saying it can’t be done… but you’ll need to get the incantation JUST right. And, when you do, you’ll come back here and share with us, right?

Peter
OSR

>So the system thinks I’m a floppy disk.

What is your DeviceObject->DeviceType?


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

I second this is not the optimal place in the stack for this. Making the RamDisk sample work as a real disk device requires an unnecessary amount of difficult work. A miniport is a simpler route since there is no need to look at disk.sys, no IOCTLs, and no interfaces to deal with. Needing much less source code compared to RamDisk, a miniport also offers other useful compatibility benefits. Miniports have nothing in them that is Windows version specific. Think about a real physical disk drive. It doesn’t care what version of Windows you plug it into, it just works. Miniports are like that. If you want logo which it sounds like you do, just be aware there is going to be a lot more work ahead shoe horning the RamDisk into this role.

Well, I did it, with one exception. It doesn’t appear in diskmgmt.msc,
but Windows assigns a letter to it and I can format it with whatever
file system I want.

So, I did this:

  1. Implemented IOCTL_MOUNTDEV_QUERY_DEVICE_NAME and
    IOCTL_MOUNTDEV_QUERY_UNIQUE_ID.
  2. Registered with the mount manager via MOUNTDEV_MOUNTED_DEVICE_GUID interface.
  3. Set MediaType to FixedMedia.
  4. Implemented IOCTL_DISK_GET_MEDIA_TYPES,
    IOCTL_STORAGE_GET_MEDIA_TYPES, IOCTL_DISK_UPDATE_DRIVE_SIZE,
    IOCTL_STORAGE_CHECK_VERIFY, IOCTL_STORAGE_CHECK_VERIFY2,
    IOCTL_DISK_GET_LENGTH_INFO and IOCTL_STORAGE_GET_HOTPLUG_INFO.

That’s about it. Code soon.


Aram Hăvărneanu

On Mon, Apr 12, 2010 at 7:19 PM, wrote:
> You should check IOCTL_STORAGE_GET_MEDIA_TYPES or IOCTL_STORAGE_GET_MEDIA_TYPES_Ex IOCTL’s. These IOCTLs contains MediaType field which you need to specify. Put either RemovableMedia or FixedMedia as MEDIA_TYPE.

You are correct, the RamDisk sample uses 0xF8 for MediaType field (wtf
is that?). I changed it to FixedDisk and implemented the above IOCTLs.


Aram Hăvărneanu

On Tue, Apr 13, 2010 at 4:20 AM, wrote:
> I second this is not the optimal place in the stack for this. Making the RamDisk sample work as a real disk device requires an unnecessary amount of difficult work. A miniport is a simpler route since there is no need to look at disk.sys, no IOCTLs, and no interfaces to deal with. Needing much less source code compared to RamDisk, a miniport also offers other useful compatibility benefits. Miniports have nothing in them that is Windows version specific. Think about a real physical disk drive. It doesn’t care what version of Windows you plug it into, it just works. Miniports are like that. If you want logo which it sounds like you do, just be aware there is going to be a lot more work ahead shoe horning the RamDisk into this role.
>

Are you referring to Storport Miniport Drivers? AFAIK Storport
Miniport Drivers work only in post-Windows 2003 systems. I need to
support Windows 2000…


Aram Hăvărneanu

On Tue, Apr 13, 2010 at 12:38 AM, Maxim S. Shatskih
wrote:
> What is your DeviceObject->DeviceType?
>

FILE_DEVICE_DISK.


Aram Hăvărneanu

On Tue, Apr 13, 2010 at 12:08 AM, wrote:
> What you’re experiencing is almost certainly the result of you trying to short-circuit all the yummy goodness that Mr. Disk Class provides. I know probably thought Mr. Burn was being abrupt with you back when you first posted your query when he replied:
>
> “Take a look at the disk class driver in the WDK, you need to support
> everything it does”
>
> …but there’s in fact a lot of wisdom in that there statement.

Well that advice was very good advice. Everything I implemented in
this driver is modeled after classpnp. I tried to do it just like
classpnp does it. I could not have done it without classpnp.

> I’m not saying it can’t be done… but you’ll need to get the incantation JUST right. And, when you do, you’ll come back here and share with us, right?

Well yeah, sure. The thing works now. You can format arbitrary FSs on
it. It doesn’t appear in diskmgmt.msc though. I suspect I need to
interact with the volume manager (not only with the mount manager),
but classpnp doesn’t seem to do this. I’ll clean the code a bit and
then it will be available for anyone else…


Aram Hăvărneanu

On Mon, Apr 12, 2010 at 11:51 PM, Michal Vodicka
wrote:
> It is long time ago I worked in this area but I was able to format
> virtual disk to NTFS (using both format.exe and GUI from exploder, not
> from disk management). I don’t remember exactly what it was but here are
> few things to examine:
>
> - DISK_GEOMETRY::MEDIA_TYPE (several IOCTLs)
> - IOCTL_STORAGE_GET_HOTPLUG_INFO
> - FILE_REMOVABLE_MEDIA in the device characteritics
>

I managed to do the same :-). My device has a FixedMedia MediaType
though, RemovableMedia requires additional IOCTLs.


Aram Hăvărneanu

>Are you referring to Storport Miniport Drivers? AFAIK Storport Miniport Drivers work only in

post-Windows 2003 systems. I need to support Windows 2000…

For RAMDISK you need a Virtual Storport Miniport driver not a Storport Miniport driver.
I believe, Virtual Storport Miniport driver available only since Windows Vista SP1.
If you need to support Windows 2000 you are in the right direction.

Igor Sharovar

Actually, the virtual storport is supported for Server 2003 see
http://support.microsoft.com/kb/943295

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

-----Original Message-----
From: xxxxx@hotmail.com [mailto:xxxxx@hotmail.com]
Posted At: Tuesday, April 13, 2010 11:27 AM
Posted To: ntdev
Conversation: Making the Ramdisk sample mountable
Subject: RE: Making the Ramdisk sample mountable

>Are you referring to Storport Miniport Drivers? AFAIK Storport
Miniport
>Drivers work only in post-Windows 2003 systems. I need to support
Windows
2000…

For RAMDISK you need a Virtual Storport Miniport driver not a
Storport
Miniport driver.
I believe, Virtual Storport Miniport driver available only since
Windows Vista
SP1.
If you need to support Windows 2000 you are in the right direction.

Igor Sharovar

__________ Information from ESET Smart Security, version of virus
signature
database 5025 (20100413) __________

The message was checked by ESET Smart Security.

http://www.eset.com