none
How to make a device show up as a real disk RRS feed

  • Question

  • 1) Disk.sys does not load, the entry point is never called.

    2) ramdisk works, but only creates a FDO.

    2a) I added this bit of code which is supposed to create a child PDO...

    	 {
    		 WDF_OBJECT_ATTRIBUTES   pdo_deviceAttributes;
    		 PWDFDEVICE_INIT pdo_init = WdfPdoInitAllocate( device );
    		 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdo_deviceAttributes, PDO_DEVICE_EXTENSION);
    
    		 status = WdfDeviceInitAssignName(pdo_init, &ntDeviceNamePDO);
           DbgPrint( "name assign is %08x\n", status );
    
    		 WdfDeviceInitSetDeviceType( pdo_init, FILE_DEVICE_DISK );
    		 WdfDeviceInitSetIoType( pdo_init, WdfDeviceIoDirect);
    		 WdfDeviceInitSetExclusive( pdo_init, FALSE);
    
    		 pdo_deviceAttributes.EvtCleanupCallback = RamDiskEvtPDODeviceContextCleanup;
    		 status = WdfDeviceCreate( &pdo_init, &pdo_deviceAttributes, &pdo_device );
           DbgPrint( "PDO Device Create is %d(%08x)\n", status, status );
    	 }
    



    which ends with status == STATUS_SUCCESS which is good... but the devices shows as unnamed...

    The new device is the first device listed in the driverObject, and the old device is it's NextDevice

    But then this bit of code doesn't work...

    		 PDRIVER_OBJECT driverObject = WdfDriverWdmGetDriverObject( Driver );
    		 PDEVICE_OBJECT deviceObject = driverObject->DeviceObject;
    
    		 //DbgPrint( "device %p wdfdriver %p\n", device, pdo_device );
           //DbgPrint( "Driver %p device %p next %p\n", driverObject, deviceObject, deviceObject->NextDevice );
    
    		 status = IoRegisterDeviceInterface( deviceObject
    													  , &MOUNTDEV_MOUNTED_DEVICE_GUID
    													  , NULL
    													  , &pDeviceExtension->InterfaceName );
           DbgPrint( "RegisterDev status %d(%08x)\n", status, status );
    		 if( status == STATUS_SUCCESS )
    		 {
    			 status = IoSetDeviceInterfaceState(&pDeviceExtension->InterfaceName
    														  , TRUE);
    			 DbgPrint( "Set Dev State status %d(%08x)\n", status, status );
    			 if( status != STATUS_SUCCESS )
    				 RtlFreeUnicodeString( &pDeviceExtension->InterfaceName );
    		 }
    

    registerdev status is STATUS_INVALID_DEVICE_REQUEST ... so the question on that is; how do I check if a thing is a PDO device or a FDO device?

    So I found this other method that's supposed to use an IOCTL to notify the mount manager; but registering the FDO doesn't work, aand using the PDO name doesn't work because the code above that creates the child PDO doesn't make it named.

    		  {
    			  UNICODE_STRING MountManagerName;
    			  PFILE_OBJECT MountMgrFileObject;
    			  PDEVICE_OBJECT MountMgrDeviceObject;
    			  NTSTATUS Status;
    			  size_t Length;
    			  MOUNTMGR_TARGET_NAME *TargetName;
    			  KEVENT Event;
    			  PIRP Irp;
    			  IO_STATUS_BLOCK IoStatusBlock;
    			  RtlInitUnicodeString( &MountManagerName
    										 , MOUNTMGR_DEVICE_NAME );
    			  Status = IoGetDeviceObjectPointer( &MountManagerName
    														  , FILE_READ_ATTRIBUTES
    														  , &MountMgrFileObject
    														  , &MountMgrDeviceObject );
    
    			  Length = sizeof(MOUNTMGR_TARGET_NAME) + ntDeviceNamePDO.Length + 1;
    			  TargetName = ExAllocatePoolWithTag( NonPagedPool
    															, Length
    															, RAMDISK_TAG );
    			  if (!TargetName) {
    				  DbgPrint( "Failed to alloc targetnmae %d\n", Length );
    				  return STATUS_INSUFFICIENT_RESOURCES;
    			  }
    			  else
    			  {
    				  RtlCopyMemory( TargetName->DeviceName
    									, ntDeviceNamePDO.Buffer
    									, ntDeviceNamePDO.Length );
    				  TargetName->DeviceNameLength = ntDeviceNamePDO.Length;  // is this right...?
    				  DbgPrint( "Name to be : %*.*S\n"
    							 , TargetName->DeviceNameLength/sizeof( TargetName->DeviceName[0])
    							 , TargetName->DeviceNameLength/sizeof( TargetName->DeviceName[0])
    							 , TargetName->DeviceName );
    
    				  KeInitializeEvent( &Event
    										 , NotificationEvent
    										 , FALSE );
    
    				  Irp = IoBuildDeviceIoControlRequest( IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
    																 , MountMgrDeviceObject
    																 , TargetName
    																 , Length
    																 , NULL
    																 , 0
    																 , FALSE
    																 , &Event
    																 , &IoStatusBlock );
    
    				  if (!Irp) {
    					  DbgPrint( "Failed to make IRP\n" );
    				  }
    
    				  /*
    					IoSetCompletionRoutine(
    					Irp,
    					VdIoCompletion,
    					NULL,
    					TRUE,
    					TRUE,
    					TRUE
    					);
    					*/
    				  else
    				  {
    					  DbgPrint( "Do IO Call Driver with IRP\n" );
    					  status = IoCallDriver( MountMgrDeviceObject
    												  , Irp );
    					  DbgPrint( "Result of iocall is %d(%08x)\n", status, status );
    				  }
    			  }
    		  }

    result of IOCall is 0xc0000034 ( STATUS_OBJECT_NAME_NOT_FOUND ) if I use the PDO device's name which didn't take... or STATUS_NO_SUCH_DEVICE if I use the ramdisk's FDO name ... so am I somehow doing it too early?

    ------

    I somehow feel I should be spending more time remembering all possible questions, otherwise I'll get one vague answer it'll get marked as an answer and I can't get any more information related to this when said answer fails.

    Saturday, May 23, 2015 7:53 PM

All replies

  • When I told you in the other thread that you could use disk.sys as a BASIS for a new driver, I meant exactly that.  Disk.sys is part of a stack, and unless you modify it extensively, you do not have anything.  What basically you need to do is take disk.sys and use that sample to understand all the queries you need to handle, and create a driver like ramdisk that supports everything.

    This is why I recommended using a virtual storport, but your requirements of XP make that impossible.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Saturday, May 23, 2015 11:13 PM
  • When I told you in the other thread that you could use disk.sys as a BASIS for a new driver, I meant exactly that.  Disk.sys is part of a stack, and unless you modify it extensively, you do not have anything.  What basically you need to do is take disk.sys and use that sample to understand all the queries you need to handle, and create a driver like ramdisk that supports everything.

    This is why I recommended using a virtual storport, but your requirements of XP make that impossible.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    but if it doesn't DO anything that is a lot of code to absorb including all of class PNP.  I can't even be sure that it will show up in diskpart of computer management, for all I can tell it's just as crippled as all other drivers.

    I find it really hard to beleive that this is really such a difficult feat; I mean the driver really has no need to know about the managment around it of where it is mounted.  

    BUT I did go through the code and track it down and find this referenced in the CDROM.sys and in class.c (storage/class/classpnp)

        status = IoRegisterDeviceInterface(
                    pdo,
                    &MOUNTDEV_MOUNTED_DEVICE_GUID,
                    NULL,
                    &interfaceName
                    );

    but; I know that requires a PDO, which 

    PWDFDEVICE_INIT pdo_init = WdfPdoInitAllocate( device );

    is supposed to give me, but the IoRegisterDevice doesn't like that device any more than the original FDO device....

    When that failed I dug some more for information and found more partial hints which is when I found IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION which is based on names; but the PDO created isn't taking the name I supplied with 

    status = WdfDeviceInitAssignName(pdo_init, &ntDeviceNamePDO);

    which is basically the same as the prior code referencing a UNICODE_STRING built from 

    #define NT_DEVICE_NAME                  L"\\Device\\Ramdisk"
    #define NT_DEVICE_NAME_PDO              L"\\Device\\RamdiskPDO"

    the _PDO variation is the one I'm using for the other device so it's even unique.



    • Edited by d3x0r Sunday, May 24, 2015 4:57 PM
    Sunday, May 24, 2015 4:55 PM
  • It is a major project, you can't just throw together some code quickly and get a driver.  You need to respond to all the IOCTL's that disk.sys supports in an appropriate manner. 

    My own approach would be create a KMDF driver, based on ramdisk for the read and write paths, and supporting all the IOCTL's from disk.sys.  Even then you will need to do some debugging to find what you are missing for this effort.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Sunday, May 24, 2015 5:18 PM
  • But I have logging on all IOCTLs that my device is getting; and the only one that I'm returning unsupported on is SMART_GET_VERSION.  Which I would think has little to do with being a managable disk.

    If I can't register my device with the mount manager, I'm not going to get any additional IOCTLs.

    If I don't know what disk.sys is missing to even get DriverEntry called, then that's just a black box of code, and no amount of modifying is likely to get driverentry called.

    Sorry to be ... upset, but it's been weeks and I didn't want to bother anyone about this in the first place.  

    In the case of the disk, I even rebuilt classpnp (I even renamed both outputs to be PRamDisk.sys and PRamClassPNP.sys and installed both so they would both be under my control) and they installed, and using Dependency walker I could load disk.sys(Err PRamDisk.sys) and not have missing symbols.


    • Edited by d3x0r Sunday, May 24, 2015 5:37 PM
    Sunday, May 24, 2015 5:32 PM
  • you will have a pdo in your driver if are in a pnp stack. If this is a kmdf driver, alll you have to do is register the device interface, kmdf will set the state for you. When you create your own pdo, you can't use it as a pdo immediately, it needs to be reported to pnp first (later asynchronously). Again, if you create the device interface on the pdo you create, kmdf will enable it for you later. You don't need to assign a name to the pdo, a name will be auto generated for you

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Sunday, May 24, 2015 6:19 PM
  • I basically have a whole new driver.  it's KMDF as far as I can tell... doesn't use any WdfXXX stuff.

    It successfully registers with MountMgr; its device gets attacked to PartMgr, but it still doesn't show up as a disk or volume.

    I'm handling All known PNP and IOCTL requests to it as appropriate.  I just can't imagine what's missing now.

    I'm not setting any Device Capabilities... maybe there's something there I need to enable?

    IOCTL_VOLUME_GET_GPT_ATTRIBUTES doesn't have good documentation for handling it... it only has a document page for invoking it.

    Edit3:

    re IOCTL_MOUNTDEV_QUERY_DEVICE_NAME... the first buffer I get is '4' which is just the size of a bare MOUNTDEV_NAME... have to return buffer too small..

    But then later get one that's 540 so can fill in a name there... is there some sort of format this name needs to be? (although re-looking at this I forgot a return so it was still getting back a unsupported status... (fixing and testing more) No change.  (edit4: actually, returning success after the 4 byte one I now get something new ...)


    • Edited by d3x0r Sunday, May 31, 2015 6:42 PM
    Sunday, May 31, 2015 5:19 PM
  • If it doesn't use WdfXXX then it is not KMDF.  


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Sunday, May 31, 2015 9:19 PM